Fix twenty sdk build (#17729)
- remove worksapce:* dependencies from published packages - Use common tsconfig.ts in create-twenty-app - Increase version to 0.4.4
This commit is contained in:
+8
-2
@@ -11,7 +11,9 @@ import unicornPlugin from 'eslint-plugin-unicorn';
|
||||
import unusedImportsPlugin from 'eslint-plugin-unused-imports';
|
||||
import jsoncParser from 'jsonc-eslint-parser';
|
||||
|
||||
const twentyRules = await nxPlugin.loadWorkspaceRules('packages/twenty-eslint-rules');
|
||||
const twentyRules = await nxPlugin.loadWorkspaceRules(
|
||||
'packages/twenty-eslint-rules',
|
||||
);
|
||||
|
||||
export default [
|
||||
// Base JavaScript configuration
|
||||
@@ -65,6 +67,10 @@ export default [
|
||||
sourceTag: 'scope:sdk',
|
||||
onlyDependOnLibsWithTags: ['scope:sdk', 'scope:shared'],
|
||||
},
|
||||
{
|
||||
sourceTag: 'scope:create-app',
|
||||
onlyDependOnLibsWithTags: ['scope:create-app', 'scope:shared'],
|
||||
},
|
||||
{
|
||||
sourceTag: 'scope:shared',
|
||||
onlyDependOnLibsWithTags: ['scope:shared'],
|
||||
@@ -197,7 +203,7 @@ export default [
|
||||
plugins: {
|
||||
...mdxPlugin.flat.plugins,
|
||||
'@nx': nxPlugin,
|
||||
'twenty': { rules: twentyRules },
|
||||
twenty: { rules: twentyRules },
|
||||
},
|
||||
},
|
||||
mdxPlugin.flatCodeBlocks,
|
||||
|
||||
@@ -1,111 +1,20 @@
|
||||
import js from '@eslint/js';
|
||||
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||
import typescriptParser from '@typescript-eslint/parser';
|
||||
import prettierPlugin from 'eslint-plugin-prettier';
|
||||
import baseConfig from '../../eslint.config.mjs';
|
||||
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
...baseConfig,
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
globals: {
|
||||
// Node.js globals
|
||||
process: 'readonly',
|
||||
console: 'readonly',
|
||||
Buffer: 'readonly',
|
||||
__dirname: 'readonly',
|
||||
__filename: 'readonly',
|
||||
global: 'readonly',
|
||||
setTimeout: 'readonly',
|
||||
clearTimeout: 'readonly',
|
||||
setInterval: 'readonly',
|
||||
clearInterval: 'readonly',
|
||||
// Browser globals that Node.js also has
|
||||
URL: 'readonly',
|
||||
URLSearchParams: 'readonly',
|
||||
// Node.js types
|
||||
NodeJS: 'readonly',
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint,
|
||||
prettier: prettierPlugin,
|
||||
},
|
||||
ignores: ['**/dist/**'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||
rules: {
|
||||
...typescriptEslint.configs.recommended.rules,
|
||||
'prettier/prettier': 'error',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'no-useless-escape': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.js'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
process: 'readonly',
|
||||
console: 'readonly',
|
||||
Buffer: 'readonly',
|
||||
__dirname: 'readonly',
|
||||
__filename: 'readonly',
|
||||
global: 'readonly',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**/*.ts'],
|
||||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
globals: {
|
||||
// Node.js globals
|
||||
process: 'readonly',
|
||||
console: 'readonly',
|
||||
Buffer: 'readonly',
|
||||
__dirname: 'readonly',
|
||||
__filename: 'readonly',
|
||||
global: 'readonly',
|
||||
// Jest globals
|
||||
describe: 'readonly',
|
||||
it: 'readonly',
|
||||
test: 'readonly',
|
||||
expect: 'readonly',
|
||||
jest: 'readonly',
|
||||
beforeEach: 'readonly',
|
||||
afterEach: 'readonly',
|
||||
beforeAll: 'readonly',
|
||||
afterAll: 'readonly',
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint,
|
||||
prettier: prettierPlugin,
|
||||
},
|
||||
rules: {
|
||||
...typescriptEslint.configs.recommended.rules,
|
||||
'prettier/prettier': 'error',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'no-useless-escape': 'off',
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
ignores: ['dist/**', 'node_modules/**'],
|
||||
ignores: ['src/**/*.ts', '!src/cli/**/*.ts'],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-twenty-app",
|
||||
"version": "0.4.3",
|
||||
"version": "0.4.4",
|
||||
"description": "Command-line interface to create Twenty application",
|
||||
"main": "dist/cli.cjs",
|
||||
"bin": "dist/cli.cjs",
|
||||
@@ -8,7 +8,9 @@
|
||||
"dist/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npx rimraf dist && npx vite build"
|
||||
"build": "npx rimraf dist && npx vite build",
|
||||
"prepack": "tsx ../twenty-utils/pack-scripts/prepack.ts",
|
||||
"postpack": "tsx ../twenty-utils/pack-scripts/postpack.ts"
|
||||
},
|
||||
"keywords": [
|
||||
"twenty",
|
||||
@@ -34,6 +36,7 @@
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.startcase": "^4.4.0",
|
||||
"twenty-shared": "workspace:*",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -43,6 +46,7 @@
|
||||
"@types/lodash.kebabcase": "^4.1.7",
|
||||
"@types/lodash.startcase": "^4",
|
||||
"@types/node": "^20.0.0",
|
||||
"typescript": "^5.9.2",
|
||||
"vite": "^7.0.0",
|
||||
"vite-plugin-dts": "^4.5.4",
|
||||
"vite-tsconfig-paths": "^4.2.1"
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
const packageJson = await fs.readJson(packageJsonPath);
|
||||
expect(packageJson.name).toBe('my-test-app');
|
||||
expect(packageJson.version).toBe('0.1.0');
|
||||
expect(packageJson.dependencies['twenty-sdk']).toBe('0.4.3');
|
||||
expect(packageJson.dependencies['twenty-sdk']).toBe('0.4.4');
|
||||
expect(packageJson.scripts['app:dev']).toBe('twenty app:dev');
|
||||
});
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ const createPackageJson = async ({
|
||||
'lint:fix': 'eslint --fix',
|
||||
},
|
||||
dependencies: {
|
||||
'twenty-sdk': '0.4.3',
|
||||
'twenty-sdk': '0.4.4',
|
||||
},
|
||||
devDependencies: {
|
||||
typescript: '^5.9.3',
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"types": ["jest", "node"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-sdk",
|
||||
"version": "0.4.3",
|
||||
"version": "0.4.4",
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.mjs",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -14,8 +14,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npx rimraf dist && npx vite build",
|
||||
"prepack": "tsx ./scripts/prepack.ts",
|
||||
"postpack": "tsx ./scripts/postpack.ts"
|
||||
"prepack": "tsx ../twenty-utils/pack-scripts/prepack.ts",
|
||||
"postpack": "tsx ../twenty-utils/pack-scripts/postpack.ts"
|
||||
},
|
||||
"keywords": [
|
||||
"twenty",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { defineConfig } from 'vite';
|
||||
import dts from 'vite-plugin-dts';
|
||||
@@ -12,8 +11,6 @@ const entries = [
|
||||
'src/front-component/index.ts',
|
||||
];
|
||||
|
||||
export const PACKAGES_TO_VENDOR = ['twenty-ui', 'twenty-shared'];
|
||||
|
||||
const entryFileNames = (chunk: any, extension: 'cjs' | 'mjs') => {
|
||||
if (!chunk.isEntry) {
|
||||
throw new Error(
|
||||
@@ -32,20 +29,6 @@ const entryFileNames = (chunk: any, extension: 'cjs' | 'mjs') => {
|
||||
return `${modulePath}/index.${extension}`;
|
||||
};
|
||||
|
||||
const copyTwentyPackagesInVendor = (packages: string[]) => {
|
||||
return packages.map((packageName) => ({
|
||||
name: `copy-${packageName}-dist`,
|
||||
closeBundle: async () => {
|
||||
const sharedDist = path.resolve(__dirname, `../${packageName}/dist`);
|
||||
const vendorDist = path.resolve(__dirname, `dist/vendor/${packageName}`);
|
||||
|
||||
await fs.remove(vendorDist);
|
||||
await fs.ensureDir(path.dirname(vendorDist));
|
||||
await fs.copy(sharedDist, vendorDist);
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
export default defineConfig(() => {
|
||||
const tsConfigPath = path.resolve(__dirname, './tsconfig.lib.json');
|
||||
|
||||
@@ -61,36 +44,7 @@ export default defineConfig(() => {
|
||||
tsconfigPaths({
|
||||
root: __dirname,
|
||||
}),
|
||||
...copyTwentyPackagesInVendor(PACKAGES_TO_VENDOR),
|
||||
dts({
|
||||
entryRoot: './src',
|
||||
tsconfigPath: tsConfigPath,
|
||||
exclude: ['vite.config.ts'],
|
||||
beforeWriteFile: (filePath, content) => {
|
||||
const fromDir = path.dirname(filePath);
|
||||
const vendorDir = path.resolve(process.cwd(), 'dist/vendor');
|
||||
|
||||
let rel = path
|
||||
.relative(fromDir, vendorDir)
|
||||
.split(path.sep)
|
||||
.join(path.posix.sep);
|
||||
if (!rel.startsWith('.')) rel = `./${rel}`;
|
||||
|
||||
const formattedContent = PACKAGES_TO_VENDOR.reduce((acc, pkg) => {
|
||||
const regex = new RegExp(
|
||||
`(from\\s+["'])${pkg}(\\/[^"']*)?(["'])`,
|
||||
'g',
|
||||
);
|
||||
|
||||
return acc.replace(regex, `$1${rel}/${pkg}$2$3`);
|
||||
}, content);
|
||||
|
||||
return {
|
||||
filePath,
|
||||
content: formattedContent,
|
||||
};
|
||||
},
|
||||
}),
|
||||
dts({ entryRoot: './src', tsconfigPath: tsConfigPath }),
|
||||
],
|
||||
worker: {
|
||||
format: 'iife',
|
||||
@@ -124,9 +78,7 @@ export default defineConfig(() => {
|
||||
warn(warning);
|
||||
},
|
||||
external: [
|
||||
...Object.keys((packageJson as any).dependencies || {}).filter(
|
||||
(dep) => !PACKAGES_TO_VENDOR.includes(dep),
|
||||
),
|
||||
...Object.keys((packageJson as any).dependencies || {}),
|
||||
'path',
|
||||
'fs',
|
||||
'fs/promises',
|
||||
|
||||
@@ -1,494 +0,0 @@
|
||||
import prettier from '@prettier/sync';
|
||||
import * as fs from 'fs';
|
||||
import { globSync } from 'glob';
|
||||
import * as path from 'path';
|
||||
import ts from 'typescript';
|
||||
const prettierConfigFile = prettier.resolveConfigFile();
|
||||
if (prettierConfigFile == null) {
|
||||
throw new Error('Prettier config file not found');
|
||||
}
|
||||
const prettierConfiguration = prettier.resolveConfig(prettierConfigFile);
|
||||
|
||||
type DeclarationOccurrence = { kind: string; name: string };
|
||||
type ExtractedExports = Array<{
|
||||
file: string;
|
||||
exports: DeclarationOccurrence[];
|
||||
}>;
|
||||
type ExtractedImports = Array<{ file: string; imports: string[] }>;
|
||||
|
||||
type ExportPerModule = Array<{
|
||||
moduleName: string;
|
||||
exports: ExtractedExports[number]['exports'];
|
||||
}>;
|
||||
function findAllExports(directoryPath: string): ExtractedExports {
|
||||
const results: ExtractedExports = [];
|
||||
|
||||
const files = getTypeScriptFiles(directoryPath);
|
||||
|
||||
for (const file of files) {
|
||||
const sourceFile = ts.createSourceFile(
|
||||
file,
|
||||
fs.readFileSync(file, 'utf8'),
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
const exports = extractExports(sourceFile);
|
||||
if (exports.length > 0) {
|
||||
results.push({
|
||||
file,
|
||||
exports,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function findAllImports(directoryPath: string): ExtractedImports {
|
||||
const results: ExtractedImports = [];
|
||||
|
||||
const includeIndex = true;
|
||||
const files = getTypeScriptFiles(directoryPath, includeIndex);
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
const sourceFile = ts.createSourceFile(
|
||||
file,
|
||||
fs.readFileSync(file, 'utf8'),
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
const imports = extractImports(sourceFile);
|
||||
if (imports.length > 0) {
|
||||
results.push({
|
||||
file,
|
||||
imports,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('Because of file: ', file);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function getTypeScriptFiles(
|
||||
directoryPath: string,
|
||||
includeIndex: boolean = false,
|
||||
): string[] {
|
||||
const pattern = path.join(directoryPath, '**/*.{ts,tsx}');
|
||||
const files = globSync(pattern);
|
||||
|
||||
return files.filter(
|
||||
(file) =>
|
||||
!file.endsWith('.d.ts') &&
|
||||
(includeIndex ? true : !file.endsWith('index.ts')),
|
||||
);
|
||||
}
|
||||
|
||||
const getKind = (node: ts.VariableStatement) => {
|
||||
const isConst = (node.declarationList.flags & ts.NodeFlags.Const) !== 0;
|
||||
if (isConst) {
|
||||
return 'const';
|
||||
}
|
||||
|
||||
const isLet = (node.declarationList.flags & ts.NodeFlags.Let) !== 0;
|
||||
if (isLet) {
|
||||
return 'let';
|
||||
}
|
||||
|
||||
return 'var';
|
||||
};
|
||||
|
||||
function extractExports(sourceFile: ts.SourceFile) {
|
||||
const exports: DeclarationOccurrence[] = [];
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (!ts.canHaveModifiers(node)) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
const modifiers = ts.getModifiers(node);
|
||||
const isExport = modifiers?.some(
|
||||
(mod) => mod.kind === ts.SyntaxKind.ExportKeyword,
|
||||
);
|
||||
|
||||
if (!isExport) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case ts.isTypeAliasDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'type',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isInterfaceDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'interface',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isEnumDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'enum',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isFunctionDeclaration(node) && node.name !== undefined:
|
||||
exports.push({
|
||||
kind: 'function',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isVariableStatement(node):
|
||||
node.declarationList.declarations.forEach((decl) => {
|
||||
if (ts.isIdentifier(decl.name)) {
|
||||
const kind = getKind(node);
|
||||
exports.push({
|
||||
kind,
|
||||
name: decl.name.text,
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isClassDeclaration(node) && node.name !== undefined:
|
||||
exports.push({
|
||||
kind: 'class',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
}
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
return exports;
|
||||
}
|
||||
|
||||
function extractImports(sourceFile: ts.SourceFile): string[] {
|
||||
const imports: string[] = [];
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (!ts.isImportDeclaration(node)) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
const modulePath = node.moduleSpecifier.getText(sourceFile);
|
||||
// Quite static
|
||||
if (modulePath !== `'twenty-shared'`) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (!node.importClause) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (!node.importClause.namedBindings) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
||||
const namedImports = node.importClause.namedBindings.elements.map(
|
||||
(element) => {
|
||||
if (element.propertyName) {
|
||||
return `${element.propertyName.text} as ${element.name.text}`;
|
||||
}
|
||||
|
||||
return element.name.text;
|
||||
},
|
||||
);
|
||||
|
||||
// imports.push(`import { ${namedImports} } from ${modulePath}`);
|
||||
namedImports.forEach((namedImport) => {
|
||||
imports.push(namedImport);
|
||||
});
|
||||
}
|
||||
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
return imports;
|
||||
}
|
||||
|
||||
const getSubDirectoryPaths = (directoryPath: string): string[] =>
|
||||
fs
|
||||
.readdirSync(directoryPath)
|
||||
.filter((fileOrDirectoryName) => {
|
||||
const isDirectory = fs
|
||||
.statSync(path.join(directoryPath, fileOrDirectoryName))
|
||||
.isDirectory();
|
||||
return isDirectory;
|
||||
})
|
||||
.map((subDirectoryName) => path.join(directoryPath, subDirectoryName));
|
||||
|
||||
const retrievePackageExportsPerModule = (srcPath: string) => {
|
||||
const subdirectories = getSubDirectoryPaths(srcPath);
|
||||
return subdirectories.map<ExportPerModule[number]>((moduleDirectory) => {
|
||||
const moduleExportsPerFile = findAllExports(moduleDirectory);
|
||||
const moduleName = moduleDirectory.split('/').pop();
|
||||
if (!moduleName) {
|
||||
throw new Error(
|
||||
`Should never occurs moduleName not found ${moduleDirectory}`,
|
||||
);
|
||||
}
|
||||
|
||||
const flattenExports = Object.values(moduleExportsPerFile).flatMap(
|
||||
(arr) => arr.exports,
|
||||
);
|
||||
return {
|
||||
moduleName,
|
||||
exports: flattenExports,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type NewImport = { barrel: string; modules: string[] };
|
||||
type MappedResolution = {
|
||||
newImports: Record<string, NewImport>;
|
||||
file: string;
|
||||
};
|
||||
type MapSourceImportToBarrelArgs = {
|
||||
importsPerFile: ExtractedImports;
|
||||
exportsPerModule: ExportPerModule;
|
||||
};
|
||||
const mapSourceImportToBarrel = ({
|
||||
exportsPerModule,
|
||||
importsPerFile,
|
||||
}: MapSourceImportToBarrelArgs): MappedResolution[] => {
|
||||
const mappedResolution: MappedResolution[] = [];
|
||||
for (const fileImport of importsPerFile) {
|
||||
const { file, imports } = fileImport;
|
||||
let result: MappedResolution = {
|
||||
file,
|
||||
newImports: {},
|
||||
};
|
||||
|
||||
for (const importedDeclaration of imports) {
|
||||
const findResult = exportsPerModule.find(({ exports }) =>
|
||||
exports.some((el) => el.name === importedDeclaration),
|
||||
);
|
||||
|
||||
if (findResult === undefined) {
|
||||
throw new Error(
|
||||
`Should never occurs no barrel exports ${importedDeclaration}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { moduleName } = findResult;
|
||||
if (result.newImports[moduleName]) {
|
||||
result.newImports[moduleName].modules.push(importedDeclaration);
|
||||
} else {
|
||||
result.newImports[moduleName] = {
|
||||
barrel: moduleName,
|
||||
modules: [importedDeclaration],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
mappedResolution.push(result);
|
||||
}
|
||||
|
||||
return mappedResolution;
|
||||
};
|
||||
|
||||
const retrieveImportFromPackageInSource = (srcPath: string) => {
|
||||
return findAllImports(srcPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts a new import statement at the top of a TypeScript file
|
||||
* @param filePath Path to the TypeScript file
|
||||
* @param importSpecifier The module to import from (e.g., 'twenty-shared/utils')
|
||||
* @param namedImports Array of named imports (e.g., ['useQuery', 'useMutation'])
|
||||
*/
|
||||
type InsertImportAtTopArgs = {
|
||||
filePath: string;
|
||||
importSpecifier: string;
|
||||
namedImports: string[];
|
||||
};
|
||||
function insertImportAtTop({
|
||||
filePath,
|
||||
importSpecifier,
|
||||
namedImports,
|
||||
}: InsertImportAtTopArgs): void {
|
||||
// Read the file content
|
||||
const sourceText = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Create a source file
|
||||
const sourceFile = ts.createSourceFile(
|
||||
filePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
// Build the new import statement
|
||||
let newImport = `import { ${namedImports.join(', ')} } from '${importSpecifier}';\n`;
|
||||
|
||||
// Find the position to insert the import
|
||||
let insertPos = 0;
|
||||
|
||||
// Case 1: File has imports - insert after the last import
|
||||
let lastImportEnd = 0;
|
||||
|
||||
ts.forEachChild(sourceFile, (node) => {
|
||||
if (
|
||||
ts.isImportDeclaration(node) ||
|
||||
ts.isImportEqualsDeclaration(node) ||
|
||||
(ts.isExpressionStatement(node) &&
|
||||
ts.isCallExpression(node.expression) &&
|
||||
node.expression.expression.kind === ts.SyntaxKind.ImportKeyword) // Overkill ?
|
||||
) {
|
||||
const end = node.getEnd();
|
||||
if (end > lastImportEnd) {
|
||||
lastImportEnd = end;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (lastImportEnd > 0) {
|
||||
// Insert after the last import with a newline
|
||||
insertPos = lastImportEnd;
|
||||
|
||||
// Check if there's already a newline after the last import
|
||||
if (sourceText[insertPos] !== '\n') {
|
||||
newImport = '\n' + newImport;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the new import
|
||||
const updatedSourceText =
|
||||
sourceText.substring(0, insertPos) +
|
||||
newImport +
|
||||
sourceText.substring(insertPos);
|
||||
|
||||
// Write back to file
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
prettier.format(updatedSourceText, {
|
||||
parser: 'typescript',
|
||||
...prettierConfiguration,
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
type RemoveSpecificImports = {
|
||||
filePath: string;
|
||||
moduleSpecifier: string;
|
||||
};
|
||||
function removeSpecificImports({
|
||||
filePath,
|
||||
moduleSpecifier,
|
||||
}: RemoveSpecificImports) {
|
||||
const sourceText = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
const sourceFile = ts.createSourceFile(
|
||||
filePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
type Replacement = {
|
||||
start: number;
|
||||
end: number;
|
||||
newText: string;
|
||||
};
|
||||
let replacement: Replacement | undefined;
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
const importSource = node.moduleSpecifier
|
||||
.getText(sourceFile)
|
||||
.replace(/^['"]|['"]$/g, '');
|
||||
|
||||
if (importSource === moduleSpecifier && node.importClause) {
|
||||
replacement = {
|
||||
start: node.getFullStart(),
|
||||
end: node.getEnd(),
|
||||
newText: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
|
||||
let updatedSourceText = sourceText;
|
||||
|
||||
if (replacement) {
|
||||
const { end, newText, start } = replacement;
|
||||
updatedSourceText =
|
||||
updatedSourceText.substring(0, start) +
|
||||
newText +
|
||||
updatedSourceText.substring(end);
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
prettier.format(updatedSourceText, {
|
||||
parser: 'typescript',
|
||||
...prettierConfiguration,
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const migrateImports = (mappedResolutions: MappedResolution[]) => {
|
||||
for (const { file, newImports } of mappedResolutions) {
|
||||
for (const { barrel, modules } of Object.values(newImports)) {
|
||||
// TODO could refactor to avoid double source file and read
|
||||
removeSpecificImports({
|
||||
filePath: file,
|
||||
moduleSpecifier: 'twenty-shared',
|
||||
});
|
||||
insertImportAtTop({
|
||||
filePath: file,
|
||||
importSpecifier: `twenty-shared/${barrel}`,
|
||||
namedImports: modules,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const main = () => {
|
||||
const packageSrcPath = 'packages/twenty-shared/src';
|
||||
const exportsPerModule = retrievePackageExportsPerModule(packageSrcPath);
|
||||
|
||||
const packagesToMigrate = [
|
||||
'twenty-front',
|
||||
'twenty-ui',
|
||||
'twenty-server',
|
||||
'twenty-emails',
|
||||
'twenty-zapier',
|
||||
];
|
||||
for (const currPackage of packagesToMigrate) {
|
||||
console.log(`About to run over ${currPackage}`);
|
||||
const importsPerFile = retrieveImportFromPackageInSource(
|
||||
`packages/${currPackage}`,
|
||||
);
|
||||
|
||||
const mappedResolutions = mapSourceImportToBarrel({
|
||||
exportsPerModule,
|
||||
importsPerFile,
|
||||
});
|
||||
migrateImports(mappedResolutions);
|
||||
console.log(`${currPackage} migrated`);
|
||||
}
|
||||
console.log('SUCCESSFULLY COMPLETED');
|
||||
};
|
||||
main();
|
||||
@@ -1,527 +0,0 @@
|
||||
import prettier from '@prettier/sync';
|
||||
import * as fs from 'fs';
|
||||
import { globSync } from 'glob';
|
||||
import * as path from 'path';
|
||||
import ts from 'typescript';
|
||||
const prettierConfigFile = prettier.resolveConfigFile();
|
||||
if (prettierConfigFile == null) {
|
||||
throw new Error('Prettier config file not found');
|
||||
}
|
||||
const prettierConfiguration = prettier.resolveConfig(prettierConfigFile);
|
||||
|
||||
type DeclarationOccurrence = { kind: string; name: string };
|
||||
type ExtractedExports = Array<{
|
||||
file: string;
|
||||
exports: DeclarationOccurrence[];
|
||||
}>;
|
||||
type ExtractedImports = Array<{ file: string; imports: string[] }>;
|
||||
|
||||
type ExportPerModule = Array<{
|
||||
moduleName: string;
|
||||
exports: ExtractedExports[number]['exports'];
|
||||
}>;
|
||||
function findAllExports(directoryPath: string): ExtractedExports {
|
||||
const results: ExtractedExports = [];
|
||||
|
||||
const files = getTypeScriptFiles(directoryPath);
|
||||
|
||||
for (const file of files) {
|
||||
const sourceFile = ts.createSourceFile(
|
||||
file,
|
||||
fs.readFileSync(file, 'utf8'),
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
const exports = extractExports(sourceFile);
|
||||
if (exports.length > 0) {
|
||||
results.push({
|
||||
file,
|
||||
exports,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function findAllImports(directoryPath: string): ExtractedImports {
|
||||
const results: ExtractedImports = [];
|
||||
|
||||
const includeIndex = true;
|
||||
const files = getTypeScriptFiles(directoryPath, includeIndex);
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
const sourceFile = ts.createSourceFile(
|
||||
file,
|
||||
fs.readFileSync(file, 'utf8'),
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
const imports = extractImports(sourceFile);
|
||||
if (imports.length > 0) {
|
||||
results.push({
|
||||
file,
|
||||
imports,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log('Because of file: ', file);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function getTypeScriptFiles(
|
||||
directoryPath: string,
|
||||
includeIndex: boolean = false,
|
||||
): string[] {
|
||||
const pattern = path.join(directoryPath, '**/*.{ts,tsx,d.ts}');
|
||||
const files = globSync(pattern);
|
||||
|
||||
return files.filter(
|
||||
(file) =>
|
||||
(includeIndex ? true : !file.endsWith('.d.ts')) &&
|
||||
(includeIndex ? true : !file.endsWith('index.ts')),
|
||||
);
|
||||
}
|
||||
|
||||
const getKind = (node: ts.VariableStatement) => {
|
||||
const isConst = (node.declarationList.flags & ts.NodeFlags.Const) !== 0;
|
||||
if (isConst) {
|
||||
return 'const';
|
||||
}
|
||||
|
||||
const isLet = (node.declarationList.flags & ts.NodeFlags.Let) !== 0;
|
||||
if (isLet) {
|
||||
return 'let';
|
||||
}
|
||||
|
||||
return 'var';
|
||||
};
|
||||
|
||||
function extractExports(sourceFile: ts.SourceFile) {
|
||||
const exports: DeclarationOccurrence[] = [];
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (!ts.canHaveModifiers(node)) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
const modifiers = ts.getModifiers(node);
|
||||
const isExport = modifiers?.some(
|
||||
(mod) => mod.kind === ts.SyntaxKind.ExportKeyword,
|
||||
);
|
||||
|
||||
if (!isExport && !ts.isExportDeclaration(node)) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case ts.isTypeAliasDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'type',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isInterfaceDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'interface',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isEnumDeclaration(node):
|
||||
exports.push({
|
||||
kind: 'enum',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isFunctionDeclaration(node) && node.name !== undefined:
|
||||
exports.push({
|
||||
kind: 'function',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isVariableStatement(node):
|
||||
node.declarationList.declarations.forEach((decl) => {
|
||||
const kind = getKind(node);
|
||||
|
||||
if (ts.isIdentifier(decl.name)) {
|
||||
exports.push({
|
||||
kind,
|
||||
name: decl.name.text,
|
||||
});
|
||||
} else if (ts.isObjectBindingPattern(decl.name)) {
|
||||
decl.name.elements.forEach((element) => {
|
||||
if (
|
||||
!ts.isBindingElement(element) ||
|
||||
!ts.isIdentifier(element.name)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
exports.push({
|
||||
kind,
|
||||
name: element.name.text,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isClassDeclaration(node) && node.name !== undefined:
|
||||
exports.push({
|
||||
kind: 'class',
|
||||
name: node.name.text,
|
||||
});
|
||||
break;
|
||||
|
||||
case ts.isExportDeclaration(node):
|
||||
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
||||
node.exportClause.elements.forEach((element) => {
|
||||
const exportName = element.name.text;
|
||||
|
||||
// Check both the declaration and the individual specifier for type-only exports
|
||||
const isTypeExport =
|
||||
node.isTypeOnly || ts.isTypeOnlyExportDeclaration(node);
|
||||
if (isTypeExport) {
|
||||
// should handle kind
|
||||
exports.push({
|
||||
kind: 'type',
|
||||
name: exportName,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
exports.push({
|
||||
kind: 'const',
|
||||
name: exportName,
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
return exports;
|
||||
}
|
||||
function extractImports(sourceFile: ts.SourceFile): string[] {
|
||||
const imports: string[] = [];
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (!ts.isImportDeclaration(node)) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
const modulePath = node.moduleSpecifier.getText(sourceFile);
|
||||
// Quite static
|
||||
if (modulePath !== `'twenty-ui'` && modulePath !== '"twenty-ui"') {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (!node.importClause) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (!node.importClause.namedBindings) {
|
||||
return ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
if (ts.isNamedImports(node.importClause.namedBindings)) {
|
||||
const namedImports = node.importClause.namedBindings.elements.map(
|
||||
(element) => {
|
||||
if (element.propertyName) {
|
||||
return `${element.propertyName.text} as ${element.name.text}`;
|
||||
}
|
||||
|
||||
return element.name.text;
|
||||
},
|
||||
);
|
||||
|
||||
// imports.push(`import { ${namedImports} } from ${modulePath}`);
|
||||
namedImports.forEach((namedImport) => {
|
||||
imports.push(namedImport);
|
||||
});
|
||||
}
|
||||
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
return imports;
|
||||
}
|
||||
|
||||
const getSubDirectoryPaths = (directoryPath: string): string[] =>
|
||||
fs
|
||||
.readdirSync(directoryPath)
|
||||
.filter((fileOrDirectoryName) => {
|
||||
const isDirectory = fs
|
||||
.statSync(path.join(directoryPath, fileOrDirectoryName))
|
||||
.isDirectory();
|
||||
return isDirectory;
|
||||
})
|
||||
.map((subDirectoryName) => path.join(directoryPath, subDirectoryName));
|
||||
|
||||
const retrievePackageExportsPerModule = (srcPath: string) => {
|
||||
const subdirectories = getSubDirectoryPaths(srcPath);
|
||||
return subdirectories.map<ExportPerModule[number]>((moduleDirectory) => {
|
||||
const moduleExportsPerFile = findAllExports(moduleDirectory);
|
||||
const moduleName = moduleDirectory.split('/').pop();
|
||||
if (!moduleName) {
|
||||
throw new Error(
|
||||
`Should never occurs moduleName not found ${moduleDirectory}`,
|
||||
);
|
||||
}
|
||||
|
||||
const flattenExports = Object.values(moduleExportsPerFile).flatMap(
|
||||
(arr) => arr.exports,
|
||||
);
|
||||
return {
|
||||
moduleName,
|
||||
exports: flattenExports,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type NewImport = { barrel: string; modules: string[] };
|
||||
type MappedResolution = {
|
||||
newImports: Record<string, NewImport>;
|
||||
file: string;
|
||||
};
|
||||
type MapSourceImportToBarrelArgs = {
|
||||
importsPerFile: ExtractedImports;
|
||||
exportsPerModule: ExportPerModule;
|
||||
};
|
||||
const mapSourceImportToBarrel = ({
|
||||
exportsPerModule,
|
||||
importsPerFile,
|
||||
}: MapSourceImportToBarrelArgs): MappedResolution[] => {
|
||||
const mappedResolution: MappedResolution[] = [];
|
||||
for (const fileImport of importsPerFile) {
|
||||
const { file, imports } = fileImport;
|
||||
let result: MappedResolution = {
|
||||
file,
|
||||
newImports: {},
|
||||
};
|
||||
|
||||
for (const importedDeclaration of imports) {
|
||||
const findResult = exportsPerModule.find(({ exports }) =>
|
||||
exports.some((el) => el.name === importedDeclaration),
|
||||
);
|
||||
|
||||
if (findResult === undefined) {
|
||||
throw new Error(
|
||||
`Should never occurs no barrel exports ${importedDeclaration}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { moduleName } = findResult;
|
||||
if (result.newImports[moduleName]) {
|
||||
result.newImports[moduleName].modules.push(importedDeclaration);
|
||||
} else {
|
||||
result.newImports[moduleName] = {
|
||||
barrel: moduleName,
|
||||
modules: [importedDeclaration],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
mappedResolution.push(result);
|
||||
}
|
||||
|
||||
return mappedResolution;
|
||||
};
|
||||
|
||||
const retrieveImportFromPackageInSource = (srcPath: string) => {
|
||||
return findAllImports(srcPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts a new import statement at the top of a TypeScript file
|
||||
* @param filePath Path to the TypeScript file
|
||||
* @param importSpecifier The module to import from (e.g., 'twenty-ui/utils')
|
||||
* @param namedImports Array of named imports (e.g., ['useQuery', 'useMutation'])
|
||||
*/
|
||||
type InsertImportAtTopArgs = {
|
||||
filePath: string;
|
||||
importSpecifier: string;
|
||||
namedImports: string[];
|
||||
};
|
||||
function insertImportAtTop({
|
||||
filePath,
|
||||
importSpecifier,
|
||||
namedImports,
|
||||
}: InsertImportAtTopArgs): void {
|
||||
// Read the file content
|
||||
const sourceText = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Create a source file
|
||||
const sourceFile = ts.createSourceFile(
|
||||
filePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
// Build the new import statement
|
||||
let newImport = `import { ${namedImports.join(', ')} } from '${importSpecifier}';\n`;
|
||||
|
||||
// Find the position to insert the import
|
||||
let insertPos = 0;
|
||||
|
||||
// Case 1: File has imports - insert after the last import
|
||||
let lastImportEnd = 0;
|
||||
|
||||
ts.forEachChild(sourceFile, (node) => {
|
||||
if (
|
||||
ts.isImportDeclaration(node) ||
|
||||
ts.isImportEqualsDeclaration(node) ||
|
||||
(ts.isExpressionStatement(node) &&
|
||||
ts.isCallExpression(node.expression) &&
|
||||
node.expression.expression.kind === ts.SyntaxKind.ImportKeyword) // Overkill ?
|
||||
) {
|
||||
const end = node.getEnd();
|
||||
if (end > lastImportEnd) {
|
||||
lastImportEnd = end;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (lastImportEnd > 0) {
|
||||
// Insert after the last import with a newline
|
||||
insertPos = lastImportEnd;
|
||||
|
||||
// Check if there's already a newline after the last import
|
||||
if (sourceText[insertPos] !== '\n') {
|
||||
newImport = '\n' + newImport;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the new import
|
||||
const updatedSourceText =
|
||||
sourceText.substring(0, insertPos) +
|
||||
newImport +
|
||||
sourceText.substring(insertPos);
|
||||
|
||||
// Write back to file
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
prettier.format(updatedSourceText, {
|
||||
parser: 'typescript',
|
||||
...prettierConfiguration,
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
type RemoveSpecificImports = {
|
||||
filePath: string;
|
||||
moduleSpecifier: string;
|
||||
};
|
||||
function removeSpecificImports({
|
||||
filePath,
|
||||
moduleSpecifier,
|
||||
}: RemoveSpecificImports) {
|
||||
const sourceText = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
const sourceFile = ts.createSourceFile(
|
||||
filePath,
|
||||
sourceText,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
);
|
||||
|
||||
type Replacement = {
|
||||
start: number;
|
||||
end: number;
|
||||
newText: string;
|
||||
};
|
||||
let replacement: Replacement | undefined;
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
const importSource = node.moduleSpecifier
|
||||
.getText(sourceFile)
|
||||
.replace(/^['"]|['"]$/g, '');
|
||||
|
||||
if (importSource === moduleSpecifier && node.importClause) {
|
||||
replacement = {
|
||||
start: node.getFullStart(),
|
||||
end: node.getEnd(),
|
||||
newText: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
|
||||
let updatedSourceText = sourceText;
|
||||
|
||||
if (replacement) {
|
||||
const { end, newText, start } = replacement;
|
||||
updatedSourceText =
|
||||
updatedSourceText.substring(0, start) +
|
||||
newText +
|
||||
updatedSourceText.substring(end);
|
||||
fs.writeFileSync(
|
||||
filePath,
|
||||
prettier.format(updatedSourceText, {
|
||||
parser: 'typescript',
|
||||
...prettierConfiguration,
|
||||
}),
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const migrateImports = (mappedResolutions: MappedResolution[]) => {
|
||||
for (const { file, newImports } of mappedResolutions) {
|
||||
for (const { barrel, modules } of Object.values(newImports)) {
|
||||
// TODO could refactor to avoid double source file and read
|
||||
removeSpecificImports({
|
||||
filePath: file,
|
||||
moduleSpecifier: 'twenty-ui',
|
||||
});
|
||||
insertImportAtTop({
|
||||
filePath: file,
|
||||
importSpecifier: `twenty-ui/${barrel}`,
|
||||
namedImports: modules,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const main = () => {
|
||||
const packageSrcPath = 'packages/twenty-ui/src';
|
||||
const exportsPerModule = retrievePackageExportsPerModule(packageSrcPath);
|
||||
|
||||
const packagesToMigrate = ['twenty-front'];
|
||||
for (const currPackage of packagesToMigrate) {
|
||||
console.log(`About to run over ${currPackage}`);
|
||||
const importsPerFile = retrieveImportFromPackageInSource(
|
||||
`packages/${currPackage}`,
|
||||
);
|
||||
|
||||
const mappedResolutions = mapSourceImportToBarrel({
|
||||
exportsPerModule,
|
||||
importsPerFile,
|
||||
});
|
||||
migrateImports(mappedResolutions);
|
||||
console.log(`${currPackage} migrated`);
|
||||
}
|
||||
console.log('SUCCESSFULLY COMPLETED');
|
||||
};
|
||||
main();
|
||||
@@ -0,0 +1,7 @@
|
||||
import path from 'path';
|
||||
|
||||
export const PKG_PATH = path.resolve(process.cwd(), 'package.json');
|
||||
export const BACKUP_PATH = path.resolve(
|
||||
process.cwd(),
|
||||
'package.__backup__.json',
|
||||
);
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import fs from 'fs-extra';
|
||||
import { BACKUP_PATH, PKG_PATH } from './prepack';
|
||||
import { BACKUP_PATH, PKG_PATH } from './constants';
|
||||
|
||||
const main = async () => {
|
||||
if (await fs.pathExists(BACKUP_PATH)) {
|
||||
const original = await fs.readJson(BACKUP_PATH);
|
||||
await fs.rm(PKG_PATH);
|
||||
await fs.remove(PKG_PATH);
|
||||
await fs.writeJson(PKG_PATH, original, { spaces: 2 });
|
||||
await fs.remove(BACKUP_PATH);
|
||||
}
|
||||
+2
-11
@@ -1,18 +1,9 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { PACKAGES_TO_VENDOR } from '../vite.config';
|
||||
|
||||
export const PKG_PATH = path.resolve(process.cwd(), 'package.json');
|
||||
export const BACKUP_PATH = path.resolve(
|
||||
process.cwd(),
|
||||
'package.__backup__.json',
|
||||
);
|
||||
import { BACKUP_PATH, PKG_PATH } from './constants';
|
||||
|
||||
const stripWorkspace = (deps = {}) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(deps).filter(
|
||||
([key, _]) => !PACKAGES_TO_VENDOR.includes(key),
|
||||
),
|
||||
Object.entries(deps).filter(([_, value]) => !value.startsWith('workspace:')),
|
||||
);
|
||||
|
||||
const main = async () => {
|
||||
Reference in New Issue
Block a user