@open-mercato/cli 0.6.7-develop.6565.1.1026d85fff → 0.6.7-develop.6566.1.15385fa179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/agentic/guides/module-facts.json +53 -53
- package/dist/agentic/guides/modules/ai_assistant.md +1 -1
- package/dist/agentic/guides/modules/api_docs.md +1 -1
- package/dist/agentic/guides/modules/api_keys.md +1 -1
- package/dist/agentic/guides/modules/attachments.md +1 -1
- package/dist/agentic/guides/modules/audit_logs.md +1 -1
- package/dist/agentic/guides/modules/auth.md +1 -1
- package/dist/agentic/guides/modules/business_rules.md +1 -1
- package/dist/agentic/guides/modules/catalog.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail.md +1 -1
- package/dist/agentic/guides/modules/channel_imap.md +1 -1
- package/dist/agentic/guides/modules/checkout.md +1 -1
- package/dist/agentic/guides/modules/communication_channels.md +1 -1
- package/dist/agentic/guides/modules/configs.md +1 -1
- package/dist/agentic/guides/modules/content.md +1 -1
- package/dist/agentic/guides/modules/currencies.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts.md +1 -1
- package/dist/agentic/guides/modules/customers.md +1 -1
- package/dist/agentic/guides/modules/dashboards.md +1 -1
- package/dist/agentic/guides/modules/data_sync.md +1 -1
- package/dist/agentic/guides/modules/dictionaries.md +1 -1
- package/dist/agentic/guides/modules/directory.md +1 -1
- package/dist/agentic/guides/modules/entities.md +1 -1
- package/dist/agentic/guides/modules/events.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe.md +1 -1
- package/dist/agentic/guides/modules/generators.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops.md +1 -1
- package/dist/agentic/guides/modules/integrations.md +1 -1
- package/dist/agentic/guides/modules/messages.md +1 -1
- package/dist/agentic/guides/modules/notifications.md +1 -1
- package/dist/agentic/guides/modules/onboarding.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways.md +1 -1
- package/dist/agentic/guides/modules/perspectives.md +1 -1
- package/dist/agentic/guides/modules/planner.md +1 -1
- package/dist/agentic/guides/modules/portal.md +1 -1
- package/dist/agentic/guides/modules/progress.md +1 -1
- package/dist/agentic/guides/modules/query_index.md +1 -1
- package/dist/agentic/guides/modules/record_locks.md +1 -1
- package/dist/agentic/guides/modules/resources.md +1 -1
- package/dist/agentic/guides/modules/sales.md +1 -1
- package/dist/agentic/guides/modules/scheduler.md +1 -1
- package/dist/agentic/guides/modules/search.md +1 -1
- package/dist/agentic/guides/modules/security.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers.md +1 -1
- package/dist/agentic/guides/modules/sso.md +1 -1
- package/dist/agentic/guides/modules/staff.md +1 -1
- package/dist/agentic/guides/modules/storage_s3.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo.md +1 -1
- package/dist/agentic/guides/modules/sync_excel.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays.md +1 -1
- package/dist/agentic/guides/modules/translations.md +1 -1
- package/dist/agentic/guides/modules/webhooks.md +1 -1
- package/dist/agentic/guides/modules/workflows.md +1 -1
- package/dist/lib/db/commands.js +1 -1
- package/dist/lib/db/commands.js.map +1 -1
- package/dist/lib/generators/ast/imports.js +1 -1
- package/dist/lib/generators/ast/imports.js.map +1 -1
- package/dist/lib/generators/entity-ids.js +1 -1
- package/dist/lib/generators/entity-ids.js.map +1 -1
- package/dist/lib/generators/extensions/injection-widgets.js +1 -1
- package/dist/lib/generators/extensions/injection-widgets.js.map +1 -1
- package/dist/lib/generators/module-facts.js +1 -1
- package/dist/lib/generators/module-facts.js.map +1 -1
- package/dist/lib/generators/module-registry.js +1 -1
- package/dist/lib/generators/module-registry.js.map +1 -1
- package/dist/lib/modules-config.js +1 -1
- package/dist/lib/modules-config.js.map +1 -1
- package/dist/lib/resolver.js +1 -1
- package/dist/lib/resolver.js.map +1 -1
- package/package.json +7 -6
- package/src/lib/db/commands.ts +1 -1
- package/src/lib/generators/__tests__/structural-contracts.test.ts +1 -1
- package/src/lib/generators/ast/imports.ts +1 -1
- package/src/lib/generators/entity-ids.ts +1 -1
- package/src/lib/generators/extensions/injection-widgets.ts +1 -1
- package/src/lib/generators/module-facts.ts +1 -1
- package/src/lib/generators/module-registry.ts +1 -1
- package/src/lib/modules-config.ts +1 -1
- package/src/lib/resolver.ts +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# feature_toggles — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.7-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.7-develop.6566.1.15385fa179 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# gateway_stripe — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.7-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.7-develop.6566.1.15385fa179 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# payment_gateways — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.7-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.7-develop.6566.1.15385fa179 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# shipping_carriers — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.7-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.7-develop.6566.1.15385fa179 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# system_status_overlays — module facts (generated, do not edit)
|
|
2
|
-
<!-- generated from @open-mercato/core 0.6.7-develop.
|
|
2
|
+
<!-- generated from @open-mercato/core 0.6.7-develop.6566.1.15385fa179 — R1 staleness stamp -->
|
|
3
3
|
|
|
4
4
|
## Entities
|
|
5
5
|
|
package/dist/lib/db/commands.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
-
import ts from "typescript";
|
|
4
|
+
import ts from "typescript-js";
|
|
5
5
|
import { MikroORM, MetadataStorage } from "@mikro-orm/core";
|
|
6
6
|
import { ReflectMetadataProvider } from "@mikro-orm/decorators/legacy";
|
|
7
7
|
import { PostgreSqlDriver } from "@mikro-orm/postgresql";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/db/commands.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport { pathToFileURL } from 'node:url'\nimport ts from 'typescript'\nimport { MikroORM, MetadataStorage, type Logger } from '@mikro-orm/core'\nimport { ReflectMetadataProvider } from '@mikro-orm/decorators/legacy'\nimport { Migrator } from '@mikro-orm/migrations'\nimport { PostgreSqlDriver } from '@mikro-orm/postgresql'\nimport { getSslConfig } from '@open-mercato/shared/lib/db/ssl'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { quotePostgresIdentifier } from './identifiers'\n\nconst QUIET_MODE = process.env.OM_CLI_QUIET === '1' || process.env.MERCATO_QUIET === '1'\nconst PROGRESS_EMOJI = ''\n\nfunction formatResult(modId: string, message: string, emoji = '\\u2022') {\n return `${emoji} ${modId}: ${message}`\n}\n\nfunction createProgressRenderer(total: number) {\n const width = 20\n const normalizedTotal = total > 0 ? total : 1\n return (current: number) => {\n const clamped = Math.min(Math.max(current, 0), normalizedTotal)\n const filled = Math.round((clamped / normalizedTotal) * width)\n const bar = `${'='.repeat(filled)}${'.'.repeat(Math.max(width - filled, 0))}`\n return `[${bar}] ${clamped}/${normalizedTotal}`\n }\n}\n\nfunction createMinimalLogger(): Logger {\n return {\n log: () => { },\n error: (_namespace, message) => console.error(message),\n warn: (_namespace, message) => {\n if (!QUIET_MODE) console.warn(message)\n },\n logQuery: () => { },\n setDebugMode: () => { },\n isEnabled: () => false,\n }\n}\n\nfunction getClientUrl(): string {\n const url = process.env.DATABASE_URL\n if (!url) throw new Error('DATABASE_URL is not set')\n return url\n}\n\nfunction sortModules(mods: ModuleEntry[]): ModuleEntry[] {\n // Sort modules alphabetically since they are now isomorphic\n return mods.slice().sort((a, b) => a.id.localeCompare(b.id))\n}\n\n/**\n * Custom dynamic import provider for MikroORM that properly handles Windows paths.\n * MikroORM's built-in handling has a bug where it converts file:// URLs back to\n * Windows paths when the extension isn't in require.extensions (which is always\n * true for .ts files in ESM mode).\n */\nasync function dynamicImportProvider(id: string): Promise<any> {\n // On Windows, convert absolute paths to file:// URLs\n // Check if it's a Windows absolute path (e.g., C:\\... or D:\\...)\n if (process.platform === 'win32' && /^[a-zA-Z]:[\\\\/]/.test(id)) {\n id = pathToFileURL(id).href\n }\n return import(id)\n}\n\n/**\n * Sanitizes a module ID for use in SQL identifiers (table names).\n * Replaces non-alphanumeric characters with underscores to prevent SQL injection.\n * @public Exported for testing\n */\nexport function sanitizeModuleId(modId: string): string {\n return modId.replace(/[^a-z0-9_]/gi, '_')\n}\n\n/**\n * Validates that a table name is safe for use in SQL queries.\n * @throws Error if the table name contains invalid characters.\n * @public Exported for testing\n */\nexport function validateTableName(tableName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {\n throw new Error(`Invalid table name: ${tableName}. Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`)\n }\n}\n\nexport function makeConstraintDropsIdempotent(sql: string): string {\n return sql.replace(/alter table\\s+(\"[^\"]+\"|\\S+)\\s+drop constraint\\s+(\"[^\"]+\"|\\S+);/gi, 'alter table $1 drop constraint if exists $2;')\n}\n\nexport function getMigrationSnapshotName(resolver: Pick<PackageResolver, 'getRootDir'>): string {\n void resolver\n return '.snapshot-open-mercato'\n}\n\nexport function shouldCreateInitialModuleMigration(migrationsPath: string, snapshotName: string): boolean {\n const snapshotPath = path.join(migrationsPath, `${snapshotName}.json`)\n if (fs.existsSync(snapshotPath)) return false\n if (!fs.existsSync(migrationsPath)) return true\n\n const migrationFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => /^Migration.*\\.(ts|js)$/.test(file) && !file.endsWith('.d.ts'))\n\n return migrationFiles.length === 0\n}\n\nexport function resolveGeneratedMigrationPath(fileName: string, migrationsPath: string): string {\n return path.isAbsolute(fileName) ? fileName : path.join(migrationsPath, fileName)\n}\n\nlet tsxLoaderRegistered = false\nlet temporaryModuleCounter = 0\n\nasync function ensureTsxLoaderRegistered() {\n if (tsxLoaderRegistered) return\n try {\n const { register } = await import('tsx/esm/api')\n register()\n tsxLoaderRegistered = true\n } catch {\n // Continue without the loader. Relative TypeScript imports may fail in this case.\n }\n}\n\nasync function importWithTypeScriptFile(filePath: string): Promise<any> {\n await ensureTsxLoaderRegistered()\n const source = fs.readFileSync(filePath, 'utf8')\n const compiled = ts.transpileModule(source, {\n fileName: filePath,\n compilerOptions: {\n module: ts.ModuleKind.ESNext,\n target: ts.ScriptTarget.ES2022,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n esModuleInterop: true,\n resolveJsonModule: true,\n jsx: ts.JsxEmit.ReactJSX,\n experimentalDecorators: true,\n emitDecoratorMetadata: false,\n useDefineForClassFields: false,\n },\n }).outputText\n const tempPath = `${filePath}.mercato-db-generate-${process.pid}-${temporaryModuleCounter++}.mjs`\n fs.writeFileSync(tempPath, compiled, 'utf8')\n try {\n return await import(pathToFileURL(tempPath).href)\n } finally {\n try {\n fs.unlinkSync(tempPath)\n } catch {\n // Ignore cleanup failures for temporary compiled modules.\n }\n }\n}\n\nasync function loadModuleEntities(entry: ModuleEntry, resolver: PackageResolver): Promise<any[]> {\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const isAppModule = entry.from === '@app'\n const shouldImportFromSource = isAppModule || resolver.isMonorepo()\n const bases = [\n path.join(roots.appBase, 'data'),\n path.join(roots.pkgBase, 'data'),\n path.join(roots.appBase, 'db'),\n path.join(roots.pkgBase, 'db'),\n ]\n const candidates = ['entities.ts', 'schema.ts']\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = path.join(base, f)\n if (fs.existsSync(p)) {\n const sub = path.basename(base)\n const fromApp = base.startsWith(roots.appBase)\n const importPath = fromApp || shouldImportFromSource\n ? pathToFileURL(p).href\n : `${imps.pkgBase}/${sub}/${f.replace(/\\.ts$/, '')}`\n try {\n const mod = fromApp || shouldImportFromSource\n ? await importWithTypeScriptFile(p)\n : await import(importPath)\n const entities = Object.values(mod).filter((v) => typeof v === 'function')\n if (entities.length) return entities as any[]\n } catch (err) {\n // For @app modules we try a TS loader fallback; otherwise propagate errors\n if (isAppModule) {\n if (process.env.MERCATO_CLI_DEBUG_IMPORTS === '1') {\n console.warn(`[db] failed to load app module entities from ${p}: ${(err as Error)?.message || String(err)}`)\n }\n continue\n }\n throw err\n }\n }\n }\n }\n return []\n}\n\nfunction getMigrationsPath(entry: ModuleEntry, resolver: PackageResolver): string {\n const roots = resolver.getModulePaths(entry)\n\n if (entry.from === '@app') {\n // @app modules: use src/ (user's TypeScript source)\n // Normalize to forward slashes for ESM compatibility on Windows\n return path.join(roots.appBase, 'migrations').replace(/\\\\/g, '/')\n }\n\n // Package modules: in standalone mode, use dist/ (compiled JS) since Node.js\n // can't run TypeScript from node_modules. In monorepo, use src/ (TypeScript).\n if (!resolver.isMonorepo()) {\n // Replace src/modules with dist/modules for standalone apps\n // Use regex to handle both forward and backslashes\n const distPath = roots.pkgBase.replace(/[/\\\\]src[/\\\\]modules[/\\\\]/, '/dist/modules/')\n return path.join(distPath, 'migrations').replace(/\\\\/g, '/')\n }\n\n // Normalize to forward slashes for ESM compatibility on Windows\n return path.join(roots.pkgBase, 'migrations').replace(/\\\\/g, '/')\n}\n\nexport interface DbOptions {\n quiet?: boolean\n}\n\nexport interface GreenfieldOptions extends DbOptions {\n yes: boolean\n}\n\nexport async function dbGenerate(resolver: PackageResolver, options: DbOptions = {}): Promise<void> {\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n\n const sslConfig = getSslConfig()\n const usedFileNames = new Set<string>()\n\n for (const entry of ordered) {\n // Clear the global @Entity() decorator registry before loading this module's\n // entities. MikroORM's migrator reads MetadataStorage at createMigration()\n // time, so without this clear, every module's migration would include every\n // previously-loaded module's tables (see issue #1911).\n MetadataStorage.clear()\n\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const entities = await loadModuleEntities(entry, resolver)\n if (!entities.length) {\n if (entry.from === '@app') {\n results.push(formatResult(modId, 'no entities discovered', ''))\n }\n continue\n }\n\n const migrationsPath = getMigrationsPath(entry, resolver)\n fs.mkdirSync(migrationsPath, { recursive: true })\n\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n const snapshotName = getMigrationSnapshotName(resolver)\n const createInitialMigration = shouldCreateInitialModuleMigration(migrationsPath, snapshotName)\n\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n dynamicImportProvider,\n entities,\n metadataProvider: ReflectMetadataProvider,\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n snapshotName,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n // acquireTimeoutMillis removed for v7 (pg.Pool doesn't support it; use connectionTimeoutMillis in driverOptions if needed)\n },\n driverOptions: sslConfig ? {\n ssl: sslConfig,\n } : undefined,\n })\n\n try {\n const diff = await orm.migrator.create(undefined, false, createInitialMigration)\n if (diff && diff.fileName) {\n try {\n const orig = resolveGeneratedMigrationPath(diff.fileName, migrationsPath)\n const base = path.basename(orig)\n const dir = path.dirname(orig)\n const ext = path.extname(base)\n const stem = base.replace(ext, '')\n const suffix = `_${modId}`\n let candidate = stem.endsWith(suffix) ? base : `${stem}${suffix}${ext}`\n let dedupe = 1\n\n while (usedFileNames.has(path.join(dir, candidate))) {\n candidate = `${stem}${suffix}_${dedupe++}${ext}`\n }\n\n const newPath = path.join(dir, candidate)\n let content = fs.readFileSync(orig, 'utf8')\n content = makeConstraintDropsIdempotent(content)\n content = content.replace(\n /export class (Migration\\d+)/,\n `export class $1_${modId.replace(/[^a-zA-Z0-9]/g, '_')}`\n )\n fs.writeFileSync(newPath, content, 'utf8')\n if (newPath !== orig) fs.unlinkSync(orig)\n usedFileNames.add(newPath)\n results.push(formatResult(modId, `generated ${path.basename(newPath)}`, ''))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push(formatResult(modId, `generated ${path.basename(diff.fileName)} (rename failed: ${message})`, ''))\n }\n } else {\n results.push(formatResult(modId, 'no changes', ''))\n }\n } finally {\n await orm.close(true)\n }\n }\n\n console.log(results.join('\\n'))\n}\n\nexport async function dbMigrate(resolver: PackageResolver, options: DbOptions = {}): Promise<void> {\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n\n for (const entry of ordered) {\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const entities = await loadModuleEntities(entry, resolver)\n\n const migrationsPath = getMigrationsPath(entry, resolver)\n\n // Skip if no entities AND no migrations directory exists\n // (allows @app modules to run migrations even if entities can't be dynamically imported)\n if (!entities.length && !fs.existsSync(migrationsPath)) continue\n fs.mkdirSync(migrationsPath, { recursive: true })\n\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n\n // dbMigrate only runs existing migration files \u2014 entities are intentionally\n // omitted so MikroORM does not compare them against the snapshot and\n // auto-generate a phantom diff migration (that would duplicate tables\n // already created by committed migrations).\n const sslConfig = getSslConfig()\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n dynamicImportProvider,\n entities: [],\n metadataProvider: ReflectMetadataProvider,\n discovery: { warnWhenNoEntities: false },\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n snapshot: false,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n // acquireTimeoutMillis removed for v7 (pg.Pool doesn't support it; use connectionTimeoutMillis in driverOptions if needed)\n },\n driverOptions: sslConfig ? {\n ssl: sslConfig,\n } : undefined,\n })\n\n const migrator = orm.migrator as Migrator\n const pending = await migrator.getPending()\n if (!pending.length) {\n results.push(formatResult(modId, 'no pending migrations', ''))\n } else {\n const renderProgress = createProgressRenderer(pending.length)\n let applied = 0\n if (!QUIET_MODE) {\n process.stdout.write(` ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`)\n }\n for (const migration of pending) {\n const migrationName =\n typeof migration === 'string'\n ? migration\n : (migration as any).name ?? (migration as any).fileName\n await migrator.up(migrationName ? { migrations: [migrationName] } : undefined)\n applied += 1\n if (!QUIET_MODE) {\n process.stdout.write(`\\r ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`)\n }\n }\n if (!QUIET_MODE) process.stdout.write('\\n')\n results.push(\n formatResult(modId, `${pending.length} migration${pending.length === 1 ? '' : 's'} applied`, '')\n )\n }\n\n await orm.close(true)\n }\n\n console.log(results.join('\\n'))\n}\n\nexport async function dbGreenfield(resolver: PackageResolver, options: GreenfieldOptions): Promise<void> {\n if (!options.yes) {\n console.error('This command will DELETE all data. Use --yes to confirm.')\n process.exit(1)\n }\n\n console.log('Cleaning up migrations and snapshots for greenfield setup...')\n\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n const outputDir = resolver.getOutputDir()\n\n for (const entry of ordered) {\n const modId = entry.id\n const migrationsPath = getMigrationsPath(entry, resolver)\n\n if (fs.existsSync(migrationsPath)) {\n // Remove all migration files\n const migrationFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => file.endsWith('.ts') && file.startsWith('Migration'))\n\n for (const file of migrationFiles) {\n fs.unlinkSync(path.join(migrationsPath, file))\n }\n\n // Remove snapshot files\n const snapshotFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => file.endsWith('.json') && file.includes('snapshot'))\n\n for (const file of snapshotFiles) {\n fs.unlinkSync(path.join(migrationsPath, file))\n }\n\n if (migrationFiles.length > 0 || snapshotFiles.length > 0) {\n results.push(\n formatResult(modId, `cleaned ${migrationFiles.length} migrations, ${snapshotFiles.length} snapshots`, '')\n )\n } else {\n results.push(formatResult(modId, 'already clean', ''))\n }\n } else {\n results.push(formatResult(modId, 'no migrations directory', ''))\n }\n\n // Clean up checksum files using glob pattern\n if (fs.existsSync(outputDir)) {\n const files = fs.readdirSync(outputDir)\n const checksumFiles = files.filter((file) => file.endsWith('.checksum'))\n\n for (const file of checksumFiles) {\n fs.unlinkSync(path.join(outputDir, file))\n }\n\n if (checksumFiles.length > 0) {\n results.push(formatResult(modId, `cleaned ${checksumFiles.length} checksum files`, ''))\n }\n }\n }\n\n console.log(results.join('\\n'))\n\n // Drop per-module MikroORM migration tables to ensure clean slate\n console.log('Dropping per-module migration tables...')\n try {\n const { Client } = await import('pg')\n const client = new Client({ connectionString: getClientUrl(), ssl: getSslConfig() })\n await client.connect()\n try {\n await client.query('BEGIN')\n for (const entry of ordered) {\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n await client.query(`DROP TABLE IF EXISTS \"${tableName}\"`)\n console.log(` ${modId}: dropped table ${tableName}`)\n }\n await client.query('COMMIT')\n } catch (e) {\n await client.query('ROLLBACK')\n throw e\n } finally {\n try {\n await client.end()\n } catch { }\n }\n } catch (e) {\n console.error('Failed to drop migration tables:', (e as any)?.message || e)\n throw e\n }\n\n // Drop all existing user tables to ensure fresh CREATE-only migrations\n console.log('Dropping ALL public tables for true greenfield...')\n try {\n const { Client } = await import('pg')\n const client = new Client({ connectionString: getClientUrl(), ssl: getSslConfig() })\n await client.connect()\n try {\n const res = await client.query(`SELECT tablename FROM pg_tables WHERE schemaname = current_schema()`)\n const tables: string[] = (res.rows || []).map((r: any) => String(r.tablename))\n if (tables.length) {\n await client.query('BEGIN')\n try {\n await client.query(\"SET session_replication_role = 'replica'\")\n for (const t of tables) {\n await client.query(`DROP TABLE IF EXISTS ${quotePostgresIdentifier(t)} CASCADE`)\n }\n await client.query(\"SET session_replication_role = 'origin'\")\n await client.query('COMMIT')\n console.log(` Dropped ${tables.length} tables.`)\n } catch (e) {\n await client.query('ROLLBACK')\n throw e\n }\n } else {\n console.log(' No tables found to drop.')\n }\n } finally {\n try {\n await client.end()\n } catch { }\n }\n } catch (e) {\n console.error('Failed to drop public tables:', (e as any)?.message || e)\n throw e\n }\n\n // Generate fresh migrations for all modules\n console.log('Generating fresh migrations for all modules...')\n await dbGenerate(resolver)\n\n // Apply migrations\n console.log('Applying migrations...')\n await dbMigrate(resolver)\n\n console.log('Greenfield reset complete! Fresh migrations generated and applied.')\n}\n"],
|
|
4
|
+
"sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport { pathToFileURL } from 'node:url'\nimport ts from 'typescript-js'\nimport { MikroORM, MetadataStorage, type Logger } from '@mikro-orm/core'\nimport { ReflectMetadataProvider } from '@mikro-orm/decorators/legacy'\nimport { Migrator } from '@mikro-orm/migrations'\nimport { PostgreSqlDriver } from '@mikro-orm/postgresql'\nimport { getSslConfig } from '@open-mercato/shared/lib/db/ssl'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { quotePostgresIdentifier } from './identifiers'\n\nconst QUIET_MODE = process.env.OM_CLI_QUIET === '1' || process.env.MERCATO_QUIET === '1'\nconst PROGRESS_EMOJI = ''\n\nfunction formatResult(modId: string, message: string, emoji = '\\u2022') {\n return `${emoji} ${modId}: ${message}`\n}\n\nfunction createProgressRenderer(total: number) {\n const width = 20\n const normalizedTotal = total > 0 ? total : 1\n return (current: number) => {\n const clamped = Math.min(Math.max(current, 0), normalizedTotal)\n const filled = Math.round((clamped / normalizedTotal) * width)\n const bar = `${'='.repeat(filled)}${'.'.repeat(Math.max(width - filled, 0))}`\n return `[${bar}] ${clamped}/${normalizedTotal}`\n }\n}\n\nfunction createMinimalLogger(): Logger {\n return {\n log: () => { },\n error: (_namespace, message) => console.error(message),\n warn: (_namespace, message) => {\n if (!QUIET_MODE) console.warn(message)\n },\n logQuery: () => { },\n setDebugMode: () => { },\n isEnabled: () => false,\n }\n}\n\nfunction getClientUrl(): string {\n const url = process.env.DATABASE_URL\n if (!url) throw new Error('DATABASE_URL is not set')\n return url\n}\n\nfunction sortModules(mods: ModuleEntry[]): ModuleEntry[] {\n // Sort modules alphabetically since they are now isomorphic\n return mods.slice().sort((a, b) => a.id.localeCompare(b.id))\n}\n\n/**\n * Custom dynamic import provider for MikroORM that properly handles Windows paths.\n * MikroORM's built-in handling has a bug where it converts file:// URLs back to\n * Windows paths when the extension isn't in require.extensions (which is always\n * true for .ts files in ESM mode).\n */\nasync function dynamicImportProvider(id: string): Promise<any> {\n // On Windows, convert absolute paths to file:// URLs\n // Check if it's a Windows absolute path (e.g., C:\\... or D:\\...)\n if (process.platform === 'win32' && /^[a-zA-Z]:[\\\\/]/.test(id)) {\n id = pathToFileURL(id).href\n }\n return import(id)\n}\n\n/**\n * Sanitizes a module ID for use in SQL identifiers (table names).\n * Replaces non-alphanumeric characters with underscores to prevent SQL injection.\n * @public Exported for testing\n */\nexport function sanitizeModuleId(modId: string): string {\n return modId.replace(/[^a-z0-9_]/gi, '_')\n}\n\n/**\n * Validates that a table name is safe for use in SQL queries.\n * @throws Error if the table name contains invalid characters.\n * @public Exported for testing\n */\nexport function validateTableName(tableName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {\n throw new Error(`Invalid table name: ${tableName}. Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`)\n }\n}\n\nexport function makeConstraintDropsIdempotent(sql: string): string {\n return sql.replace(/alter table\\s+(\"[^\"]+\"|\\S+)\\s+drop constraint\\s+(\"[^\"]+\"|\\S+);/gi, 'alter table $1 drop constraint if exists $2;')\n}\n\nexport function getMigrationSnapshotName(resolver: Pick<PackageResolver, 'getRootDir'>): string {\n void resolver\n return '.snapshot-open-mercato'\n}\n\nexport function shouldCreateInitialModuleMigration(migrationsPath: string, snapshotName: string): boolean {\n const snapshotPath = path.join(migrationsPath, `${snapshotName}.json`)\n if (fs.existsSync(snapshotPath)) return false\n if (!fs.existsSync(migrationsPath)) return true\n\n const migrationFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => /^Migration.*\\.(ts|js)$/.test(file) && !file.endsWith('.d.ts'))\n\n return migrationFiles.length === 0\n}\n\nexport function resolveGeneratedMigrationPath(fileName: string, migrationsPath: string): string {\n return path.isAbsolute(fileName) ? fileName : path.join(migrationsPath, fileName)\n}\n\nlet tsxLoaderRegistered = false\nlet temporaryModuleCounter = 0\n\nasync function ensureTsxLoaderRegistered() {\n if (tsxLoaderRegistered) return\n try {\n const { register } = await import('tsx/esm/api')\n register()\n tsxLoaderRegistered = true\n } catch {\n // Continue without the loader. Relative TypeScript imports may fail in this case.\n }\n}\n\nasync function importWithTypeScriptFile(filePath: string): Promise<any> {\n await ensureTsxLoaderRegistered()\n const source = fs.readFileSync(filePath, 'utf8')\n const compiled = ts.transpileModule(source, {\n fileName: filePath,\n compilerOptions: {\n module: ts.ModuleKind.ESNext,\n target: ts.ScriptTarget.ES2022,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n esModuleInterop: true,\n resolveJsonModule: true,\n jsx: ts.JsxEmit.ReactJSX,\n experimentalDecorators: true,\n emitDecoratorMetadata: false,\n useDefineForClassFields: false,\n },\n }).outputText\n const tempPath = `${filePath}.mercato-db-generate-${process.pid}-${temporaryModuleCounter++}.mjs`\n fs.writeFileSync(tempPath, compiled, 'utf8')\n try {\n return await import(pathToFileURL(tempPath).href)\n } finally {\n try {\n fs.unlinkSync(tempPath)\n } catch {\n // Ignore cleanup failures for temporary compiled modules.\n }\n }\n}\n\nasync function loadModuleEntities(entry: ModuleEntry, resolver: PackageResolver): Promise<any[]> {\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const isAppModule = entry.from === '@app'\n const shouldImportFromSource = isAppModule || resolver.isMonorepo()\n const bases = [\n path.join(roots.appBase, 'data'),\n path.join(roots.pkgBase, 'data'),\n path.join(roots.appBase, 'db'),\n path.join(roots.pkgBase, 'db'),\n ]\n const candidates = ['entities.ts', 'schema.ts']\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = path.join(base, f)\n if (fs.existsSync(p)) {\n const sub = path.basename(base)\n const fromApp = base.startsWith(roots.appBase)\n const importPath = fromApp || shouldImportFromSource\n ? pathToFileURL(p).href\n : `${imps.pkgBase}/${sub}/${f.replace(/\\.ts$/, '')}`\n try {\n const mod = fromApp || shouldImportFromSource\n ? await importWithTypeScriptFile(p)\n : await import(importPath)\n const entities = Object.values(mod).filter((v) => typeof v === 'function')\n if (entities.length) return entities as any[]\n } catch (err) {\n // For @app modules we try a TS loader fallback; otherwise propagate errors\n if (isAppModule) {\n if (process.env.MERCATO_CLI_DEBUG_IMPORTS === '1') {\n console.warn(`[db] failed to load app module entities from ${p}: ${(err as Error)?.message || String(err)}`)\n }\n continue\n }\n throw err\n }\n }\n }\n }\n return []\n}\n\nfunction getMigrationsPath(entry: ModuleEntry, resolver: PackageResolver): string {\n const roots = resolver.getModulePaths(entry)\n\n if (entry.from === '@app') {\n // @app modules: use src/ (user's TypeScript source)\n // Normalize to forward slashes for ESM compatibility on Windows\n return path.join(roots.appBase, 'migrations').replace(/\\\\/g, '/')\n }\n\n // Package modules: in standalone mode, use dist/ (compiled JS) since Node.js\n // can't run TypeScript from node_modules. In monorepo, use src/ (TypeScript).\n if (!resolver.isMonorepo()) {\n // Replace src/modules with dist/modules for standalone apps\n // Use regex to handle both forward and backslashes\n const distPath = roots.pkgBase.replace(/[/\\\\]src[/\\\\]modules[/\\\\]/, '/dist/modules/')\n return path.join(distPath, 'migrations').replace(/\\\\/g, '/')\n }\n\n // Normalize to forward slashes for ESM compatibility on Windows\n return path.join(roots.pkgBase, 'migrations').replace(/\\\\/g, '/')\n}\n\nexport interface DbOptions {\n quiet?: boolean\n}\n\nexport interface GreenfieldOptions extends DbOptions {\n yes: boolean\n}\n\nexport async function dbGenerate(resolver: PackageResolver, options: DbOptions = {}): Promise<void> {\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n\n const sslConfig = getSslConfig()\n const usedFileNames = new Set<string>()\n\n for (const entry of ordered) {\n // Clear the global @Entity() decorator registry before loading this module's\n // entities. MikroORM's migrator reads MetadataStorage at createMigration()\n // time, so without this clear, every module's migration would include every\n // previously-loaded module's tables (see issue #1911).\n MetadataStorage.clear()\n\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const entities = await loadModuleEntities(entry, resolver)\n if (!entities.length) {\n if (entry.from === '@app') {\n results.push(formatResult(modId, 'no entities discovered', ''))\n }\n continue\n }\n\n const migrationsPath = getMigrationsPath(entry, resolver)\n fs.mkdirSync(migrationsPath, { recursive: true })\n\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n const snapshotName = getMigrationSnapshotName(resolver)\n const createInitialMigration = shouldCreateInitialModuleMigration(migrationsPath, snapshotName)\n\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n dynamicImportProvider,\n entities,\n metadataProvider: ReflectMetadataProvider,\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n snapshotName,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n // acquireTimeoutMillis removed for v7 (pg.Pool doesn't support it; use connectionTimeoutMillis in driverOptions if needed)\n },\n driverOptions: sslConfig ? {\n ssl: sslConfig,\n } : undefined,\n })\n\n try {\n const diff = await orm.migrator.create(undefined, false, createInitialMigration)\n if (diff && diff.fileName) {\n try {\n const orig = resolveGeneratedMigrationPath(diff.fileName, migrationsPath)\n const base = path.basename(orig)\n const dir = path.dirname(orig)\n const ext = path.extname(base)\n const stem = base.replace(ext, '')\n const suffix = `_${modId}`\n let candidate = stem.endsWith(suffix) ? base : `${stem}${suffix}${ext}`\n let dedupe = 1\n\n while (usedFileNames.has(path.join(dir, candidate))) {\n candidate = `${stem}${suffix}_${dedupe++}${ext}`\n }\n\n const newPath = path.join(dir, candidate)\n let content = fs.readFileSync(orig, 'utf8')\n content = makeConstraintDropsIdempotent(content)\n content = content.replace(\n /export class (Migration\\d+)/,\n `export class $1_${modId.replace(/[^a-zA-Z0-9]/g, '_')}`\n )\n fs.writeFileSync(newPath, content, 'utf8')\n if (newPath !== orig) fs.unlinkSync(orig)\n usedFileNames.add(newPath)\n results.push(formatResult(modId, `generated ${path.basename(newPath)}`, ''))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n results.push(formatResult(modId, `generated ${path.basename(diff.fileName)} (rename failed: ${message})`, ''))\n }\n } else {\n results.push(formatResult(modId, 'no changes', ''))\n }\n } finally {\n await orm.close(true)\n }\n }\n\n console.log(results.join('\\n'))\n}\n\nexport async function dbMigrate(resolver: PackageResolver, options: DbOptions = {}): Promise<void> {\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n\n for (const entry of ordered) {\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const entities = await loadModuleEntities(entry, resolver)\n\n const migrationsPath = getMigrationsPath(entry, resolver)\n\n // Skip if no entities AND no migrations directory exists\n // (allows @app modules to run migrations even if entities can't be dynamically imported)\n if (!entities.length && !fs.existsSync(migrationsPath)) continue\n fs.mkdirSync(migrationsPath, { recursive: true })\n\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n\n // dbMigrate only runs existing migration files \u2014 entities are intentionally\n // omitted so MikroORM does not compare them against the snapshot and\n // auto-generate a phantom diff migration (that would duplicate tables\n // already created by committed migrations).\n const sslConfig = getSslConfig()\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n dynamicImportProvider,\n entities: [],\n metadataProvider: ReflectMetadataProvider,\n discovery: { warnWhenNoEntities: false },\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n snapshot: false,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n // acquireTimeoutMillis removed for v7 (pg.Pool doesn't support it; use connectionTimeoutMillis in driverOptions if needed)\n },\n driverOptions: sslConfig ? {\n ssl: sslConfig,\n } : undefined,\n })\n\n const migrator = orm.migrator as Migrator\n const pending = await migrator.getPending()\n if (!pending.length) {\n results.push(formatResult(modId, 'no pending migrations', ''))\n } else {\n const renderProgress = createProgressRenderer(pending.length)\n let applied = 0\n if (!QUIET_MODE) {\n process.stdout.write(` ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`)\n }\n for (const migration of pending) {\n const migrationName =\n typeof migration === 'string'\n ? migration\n : (migration as any).name ?? (migration as any).fileName\n await migrator.up(migrationName ? { migrations: [migrationName] } : undefined)\n applied += 1\n if (!QUIET_MODE) {\n process.stdout.write(`\\r ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`)\n }\n }\n if (!QUIET_MODE) process.stdout.write('\\n')\n results.push(\n formatResult(modId, `${pending.length} migration${pending.length === 1 ? '' : 's'} applied`, '')\n )\n }\n\n await orm.close(true)\n }\n\n console.log(results.join('\\n'))\n}\n\nexport async function dbGreenfield(resolver: PackageResolver, options: GreenfieldOptions): Promise<void> {\n if (!options.yes) {\n console.error('This command will DELETE all data. Use --yes to confirm.')\n process.exit(1)\n }\n\n console.log('Cleaning up migrations and snapshots for greenfield setup...')\n\n const modules = resolver.loadEnabledModules()\n const ordered = sortModules(modules)\n const results: string[] = []\n const outputDir = resolver.getOutputDir()\n\n for (const entry of ordered) {\n const modId = entry.id\n const migrationsPath = getMigrationsPath(entry, resolver)\n\n if (fs.existsSync(migrationsPath)) {\n // Remove all migration files\n const migrationFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => file.endsWith('.ts') && file.startsWith('Migration'))\n\n for (const file of migrationFiles) {\n fs.unlinkSync(path.join(migrationsPath, file))\n }\n\n // Remove snapshot files\n const snapshotFiles = fs\n .readdirSync(migrationsPath)\n .filter((file) => file.endsWith('.json') && file.includes('snapshot'))\n\n for (const file of snapshotFiles) {\n fs.unlinkSync(path.join(migrationsPath, file))\n }\n\n if (migrationFiles.length > 0 || snapshotFiles.length > 0) {\n results.push(\n formatResult(modId, `cleaned ${migrationFiles.length} migrations, ${snapshotFiles.length} snapshots`, '')\n )\n } else {\n results.push(formatResult(modId, 'already clean', ''))\n }\n } else {\n results.push(formatResult(modId, 'no migrations directory', ''))\n }\n\n // Clean up checksum files using glob pattern\n if (fs.existsSync(outputDir)) {\n const files = fs.readdirSync(outputDir)\n const checksumFiles = files.filter((file) => file.endsWith('.checksum'))\n\n for (const file of checksumFiles) {\n fs.unlinkSync(path.join(outputDir, file))\n }\n\n if (checksumFiles.length > 0) {\n results.push(formatResult(modId, `cleaned ${checksumFiles.length} checksum files`, ''))\n }\n }\n }\n\n console.log(results.join('\\n'))\n\n // Drop per-module MikroORM migration tables to ensure clean slate\n console.log('Dropping per-module migration tables...')\n try {\n const { Client } = await import('pg')\n const client = new Client({ connectionString: getClientUrl(), ssl: getSslConfig() })\n await client.connect()\n try {\n await client.query('BEGIN')\n for (const entry of ordered) {\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const tableName = `mikro_orm_migrations_${sanitizedModId}`\n validateTableName(tableName)\n await client.query(`DROP TABLE IF EXISTS \"${tableName}\"`)\n console.log(` ${modId}: dropped table ${tableName}`)\n }\n await client.query('COMMIT')\n } catch (e) {\n await client.query('ROLLBACK')\n throw e\n } finally {\n try {\n await client.end()\n } catch { }\n }\n } catch (e) {\n console.error('Failed to drop migration tables:', (e as any)?.message || e)\n throw e\n }\n\n // Drop all existing user tables to ensure fresh CREATE-only migrations\n console.log('Dropping ALL public tables for true greenfield...')\n try {\n const { Client } = await import('pg')\n const client = new Client({ connectionString: getClientUrl(), ssl: getSslConfig() })\n await client.connect()\n try {\n const res = await client.query(`SELECT tablename FROM pg_tables WHERE schemaname = current_schema()`)\n const tables: string[] = (res.rows || []).map((r: any) => String(r.tablename))\n if (tables.length) {\n await client.query('BEGIN')\n try {\n await client.query(\"SET session_replication_role = 'replica'\")\n for (const t of tables) {\n await client.query(`DROP TABLE IF EXISTS ${quotePostgresIdentifier(t)} CASCADE`)\n }\n await client.query(\"SET session_replication_role = 'origin'\")\n await client.query('COMMIT')\n console.log(` Dropped ${tables.length} tables.`)\n } catch (e) {\n await client.query('ROLLBACK')\n throw e\n }\n } else {\n console.log(' No tables found to drop.')\n }\n } finally {\n try {\n await client.end()\n } catch { }\n }\n } catch (e) {\n console.error('Failed to drop public tables:', (e as any)?.message || e)\n throw e\n }\n\n // Generate fresh migrations for all modules\n console.log('Generating fresh migrations for all modules...')\n await dbGenerate(resolver)\n\n // Apply migrations\n console.log('Applying migrations...')\n await dbMigrate(resolver)\n\n console.log('Greenfield reset complete! Fresh migrations generated and applied.')\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/generators/ast/imports.ts"],
|
|
4
|
-
"sourcesContent": ["import ts from 'typescript'\nimport {\n StructureKind,\n type ImportDeclarationStructure,\n type OptionalKind,\n type SourceFile,\n} from 'ts-morph'\n\nexport type GeneratedImportSpec = OptionalKind<ImportDeclarationStructure>\n\nfunction toImportSpec(statement: string): GeneratedImportSpec {\n const trimmed = statement.trim()\n const sourceFile = ts.createSourceFile('import.ts', trimmed, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const importDeclaration = sourceFile.statements.find(ts.isImportDeclaration)\n if (!importDeclaration) {\n throw new Error(`Expected import declaration, received: ${statement}`)\n }\n\n const moduleSpecifier = importDeclaration.moduleSpecifier\n if (!ts.isStringLiteral(moduleSpecifier)) {\n throw new Error(`Unsupported import declaration: ${statement}`)\n }\n\n const spec: GeneratedImportSpec = {\n kind: StructureKind.ImportDeclaration,\n moduleSpecifier: moduleSpecifier.text,\n }\n\n const clause = importDeclaration.importClause\n if (!clause) {\n return spec\n }\n\n spec.isTypeOnly = clause.isTypeOnly\n\n if (clause.name) {\n spec.defaultImport = clause.name.text\n }\n\n if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {\n spec.namespaceImport = clause.namedBindings.name.text\n }\n\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n spec.namedImports = clause.namedBindings.elements.map((element) => ({\n kind: StructureKind.ImportSpecifier,\n name: element.propertyName?.text ?? element.name.text,\n alias: element.propertyName ? element.name.text : undefined,\n isTypeOnly: element.isTypeOnly,\n }))\n }\n\n return spec\n}\n\nexport function addImportSpec(sourceFile: SourceFile, spec: GeneratedImportSpec): void {\n sourceFile.addImportDeclaration({\n kind: StructureKind.ImportDeclaration,\n ...spec,\n })\n}\n\nexport function addImportSpecs(sourceFile: SourceFile, specs: GeneratedImportSpec[]): void {\n for (const spec of specs) {\n addImportSpec(sourceFile, spec)\n }\n}\n\nexport function addImportStatement(sourceFile: SourceFile, statement: string): void {\n const trimmed = statement.trim()\n if (!trimmed) return\n addImportSpec(sourceFile, toImportSpec(trimmed))\n}\n\nexport function addImportStatements(sourceFile: SourceFile, statements: string[]): void {\n for (const statement of statements) {\n addImportStatement(sourceFile, statement)\n }\n}\n"],
|
|
4
|
+
"sourcesContent": ["import ts from 'typescript-js'\nimport {\n StructureKind,\n type ImportDeclarationStructure,\n type OptionalKind,\n type SourceFile,\n} from 'ts-morph'\n\nexport type GeneratedImportSpec = OptionalKind<ImportDeclarationStructure>\n\nfunction toImportSpec(statement: string): GeneratedImportSpec {\n const trimmed = statement.trim()\n const sourceFile = ts.createSourceFile('import.ts', trimmed, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS)\n const importDeclaration = sourceFile.statements.find(ts.isImportDeclaration)\n if (!importDeclaration) {\n throw new Error(`Expected import declaration, received: ${statement}`)\n }\n\n const moduleSpecifier = importDeclaration.moduleSpecifier\n if (!ts.isStringLiteral(moduleSpecifier)) {\n throw new Error(`Unsupported import declaration: ${statement}`)\n }\n\n const spec: GeneratedImportSpec = {\n kind: StructureKind.ImportDeclaration,\n moduleSpecifier: moduleSpecifier.text,\n }\n\n const clause = importDeclaration.importClause\n if (!clause) {\n return spec\n }\n\n spec.isTypeOnly = clause.isTypeOnly\n\n if (clause.name) {\n spec.defaultImport = clause.name.text\n }\n\n if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) {\n spec.namespaceImport = clause.namedBindings.name.text\n }\n\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n spec.namedImports = clause.namedBindings.elements.map((element) => ({\n kind: StructureKind.ImportSpecifier,\n name: element.propertyName?.text ?? element.name.text,\n alias: element.propertyName ? element.name.text : undefined,\n isTypeOnly: element.isTypeOnly,\n }))\n }\n\n return spec\n}\n\nexport function addImportSpec(sourceFile: SourceFile, spec: GeneratedImportSpec): void {\n sourceFile.addImportDeclaration({\n kind: StructureKind.ImportDeclaration,\n ...spec,\n })\n}\n\nexport function addImportSpecs(sourceFile: SourceFile, specs: GeneratedImportSpec[]): void {\n for (const spec of specs) {\n addImportSpec(sourceFile, spec)\n }\n}\n\nexport function addImportStatement(sourceFile: SourceFile, statement: string): void {\n const trimmed = statement.trim()\n if (!trimmed) return\n addImportSpec(sourceFile, toImportSpec(trimmed))\n}\n\nexport function addImportStatements(sourceFile: SourceFile, statements: string[]): void {\n for (const statement of statements) {\n addImportStatement(sourceFile, statement)\n }\n}\n"],
|
|
5
5
|
"mappings": "AAAA,OAAO,QAAQ;AACf;AAAA,EACE;AAAA,OAIK;AAIP,SAAS,aAAa,WAAwC;AAC5D,QAAM,UAAU,UAAU,KAAK;AAC/B,QAAM,aAAa,GAAG,iBAAiB,aAAa,SAAS,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,EAAE;AAC3G,QAAM,oBAAoB,WAAW,WAAW,KAAK,GAAG,mBAAmB;AAC3E,MAAI,CAAC,mBAAmB;AACtB,UAAM,IAAI,MAAM,0CAA0C,SAAS,EAAE;AAAA,EACvE;AAEA,QAAM,kBAAkB,kBAAkB;AAC1C,MAAI,CAAC,GAAG,gBAAgB,eAAe,GAAG;AACxC,UAAM,IAAI,MAAM,mCAAmC,SAAS,EAAE;AAAA,EAChE;AAEA,QAAM,OAA4B;AAAA,IAChC,MAAM,cAAc;AAAA,IACpB,iBAAiB,gBAAgB;AAAA,EACnC;AAEA,QAAM,SAAS,kBAAkB;AACjC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,OAAK,aAAa,OAAO;AAEzB,MAAI,OAAO,MAAM;AACf,SAAK,gBAAgB,OAAO,KAAK;AAAA,EACnC;AAEA,MAAI,OAAO,iBAAiB,GAAG,kBAAkB,OAAO,aAAa,GAAG;AACtE,SAAK,kBAAkB,OAAO,cAAc,KAAK;AAAA,EACnD;AAEA,MAAI,OAAO,iBAAiB,GAAG,eAAe,OAAO,aAAa,GAAG;AACnE,SAAK,eAAe,OAAO,cAAc,SAAS,IAAI,CAAC,aAAa;AAAA,MAClE,MAAM,cAAc;AAAA,MACpB,MAAM,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,MACjD,OAAO,QAAQ,eAAe,QAAQ,KAAK,OAAO;AAAA,MAClD,YAAY,QAAQ;AAAA,IACtB,EAAE;AAAA,EACJ;AAEA,SAAO;AACT;AAEO,SAAS,cAAc,YAAwB,MAAiC;AACrF,aAAW,qBAAqB;AAAA,IAC9B,MAAM,cAAc;AAAA,IACpB,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,eAAe,YAAwB,OAAoC;AACzF,aAAW,QAAQ,OAAO;AACxB,kBAAc,YAAY,IAAI;AAAA,EAChC;AACF;AAEO,SAAS,mBAAmB,YAAwB,WAAyB;AAClF,QAAM,UAAU,UAAU,KAAK;AAC/B,MAAI,CAAC,QAAS;AACd,gBAAc,YAAY,aAAa,OAAO,CAAC;AACjD;AAEO,SAAS,oBAAoB,YAAwB,YAA4B;AACtF,aAAW,aAAa,YAAY;AAClC,uBAAmB,YAAY,SAAS;AAAA,EAC1C;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/generators/entity-ids.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n calculateChecksum,\n readChecksumRecord,\n writeChecksumRecord,\n ensureDir,\n toVar,\n toSnake,\n rimrafDir,\n logGenerationResult,\n writeIfChanged,\n type GeneratorResult,\n createGeneratorResult,\n} from '../utils'\nimport { addAutoGeneratedComment, createGeneratedSourceFile, elementAccess, getSourceText, identifier, returnStatement } from './ast'\n\ntype GroupKey = '@app' | '@open-mercato/core' | string\ntype EntityFieldMap = Record<string, string[]>\n\nexport interface EntityIdsOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\n/**\n * Extract exported class names from a TypeScript source file without dynamic import.\n * This is used for @app modules since Node.js can't import TypeScript files directly.\n */\nfunction parseExportedClassNamesFromFile(filePath: string): string[] {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n const classNames: string[] = []\n\n sf.forEachChild((node) => {\n // Check for exported class declarations\n if (ts.isClassDeclaration(node) && node.name) {\n const hasExport = node.modifiers?.some(\n (m) => m.kind === ts.SyntaxKind.ExportKeyword\n )\n if (hasExport) {\n classNames.push(node.name.text)\n }\n }\n })\n\n return classNames\n}\n\nfunction unwrapObjectLiteralExpression(\n expression: ts.Expression | undefined,\n): ts.ObjectLiteralExpression | undefined {\n if (!expression) return undefined\n if (ts.isObjectLiteralExpression(expression)) return expression\n if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n if (ts.isParenthesizedExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n return undefined\n}\n\nfunction readPropertyInitializer(\n objectLiteral: ts.ObjectLiteralExpression,\n propertyName: string,\n): ts.Expression | undefined {\n for (const property of objectLiteral.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name === propertyName) {\n return property.initializer\n }\n }\n return undefined\n}\n\nfunction parseGeneratedModuleEntityNames(filePath: string, moduleId: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n const declaration = statement.declarationList.declarations.find((candidate) =>\n ts.isIdentifier(candidate.name) && candidate.name.text === 'E')\n if (!declaration) continue\n\n const eObject = unwrapObjectLiteralExpression(declaration.initializer)\n if (!eObject) continue\n\n const moduleObject = unwrapObjectLiteralExpression(readPropertyInitializer(eObject, moduleId))\n if (!moduleObject) return []\n\n const names: string[] = []\n for (const property of moduleObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name) names.push(name)\n }\n return names\n }\n\n return []\n}\n\nfunction parseGeneratedEntityFieldsFile(filePath: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n const fields: string[] = []\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n if (!ts.isStringLiteralLike(declaration.initializer)) continue\n fields.push(declaration.initializer.text)\n }\n }\n\n return Array.from(new Set(fields))\n}\n\nfunction resolveExistingFile(candidates: string[]): string | null {\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nfunction loadStandaloneGeneratedPackageEntities(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): { entityNames: string[]; entityFieldMap: EntityFieldMap } | null {\n if (resolver.isMonorepo() || !entry.from || entry.from === '@app') return null\n\n const packageRoot = resolver.getPackageRoot(entry.from)\n const generatedRoot = fs.existsSync(path.join(packageRoot, 'generated'))\n ? path.join(packageRoot, 'generated')\n : path.join(packageRoot, 'dist', 'generated')\n const idsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities.ids.generated.ts'),\n path.join(generatedRoot, 'entities.ids.generated.js'),\n ])\n if (!idsFile) return null\n const entityNames = parseGeneratedModuleEntityNames(idsFile, entry.id)\n\n if (entityNames.length === 0) return null\n\n const entityFieldMap: EntityFieldMap = {}\n for (const entityName of entityNames) {\n const fieldsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities', entityName, 'index.ts'),\n path.join(generatedRoot, 'entities', entityName, 'index.js'),\n ])\n if (!fieldsFile) continue\n const fields = parseGeneratedEntityFieldsFile(fieldsFile)\n entityFieldMap[entityName] = fields\n }\n\n return { entityNames, entityFieldMap }\n}\n\nfunction parseEntityFieldsFromFile(filePath: string, exportedClassNames: string[]): EntityFieldMap {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n\n const exported = new Set(exportedClassNames)\n const result: EntityFieldMap = {}\n\n function getDecoratorArgNameLiteral(dec: ts.Decorator | undefined): string | undefined {\n if (!dec) return undefined\n const expr = dec.expression\n if (!ts.isCallExpression(expr)) return undefined\n if (!expr.arguments.length) return undefined\n const first = expr.arguments[0]\n if (!ts.isObjectLiteralExpression(first)) return undefined\n for (const prop of first.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'name') {\n if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text\n }\n }\n return undefined\n }\n\n function normalizeDbName(propertyName: string, _decoratorName?: string, nameOverride?: string): string {\n if (nameOverride) return nameOverride\n return toSnake(propertyName)\n }\n\n sf.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n const clsName = node.name.text\n if (!exported.has(clsName)) return\n const entityKey = toSnake(clsName)\n const fields: string[] = []\n\n for (const member of node.members) {\n if (!ts.isPropertyDeclaration(member) || !member.name) continue\n const name = ts.isIdentifier(member.name)\n ? member.name.text\n : ts.isStringLiteral(member.name)\n ? member.name.text\n : undefined\n if (!name) continue\n if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue\n const decorators = ts.canHaveDecorators(member)\n ? ts.getDecorators(member) ?? []\n : []\n let dbName: string | undefined\n if (decorators && decorators.length) {\n for (const d of decorators) {\n const nameOverride = getDecoratorArgNameLiteral(d)\n dbName = normalizeDbName(name, undefined, nameOverride)\n if (dbName) break\n }\n }\n if (!dbName) dbName = normalizeDbName(name)\n fields.push(dbName)\n }\n result[entityKey] = Array.from(new Set(fields))\n })\n\n return result\n}\n\nfunction writeTrackedFile(\n filePath: string,\n content: string,\n result: GeneratorResult,\n): void {\n if (writeIfChanged(filePath, content)) {\n result.filesWritten.push(filePath)\n } else {\n result.filesUnchanged.push(filePath)\n }\n}\n\nfunction writePerEntityFieldFiles(\n outRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n fs.mkdirSync(outRoot, { recursive: true })\n const desiredEntities = new Set(Object.keys(fieldsByEntity))\n for (const [entity, fields] of Object.entries(fieldsByEntity)) {\n const entDir = path.join(outRoot, entity)\n fs.mkdirSync(entDir, { recursive: true })\n const sourceFile = createGeneratedSourceFile(`${entity}/index.ts`)\n for (const field of fields) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: toVar(field),\n initializer: JSON.stringify(field),\n },\n ],\n })\n }\n writeTrackedFile(path.join(entDir, 'index.ts'), getSourceText(sourceFile), result)\n }\n\n const existingEntries = fs.existsSync(outRoot) ? fs.readdirSync(outRoot, { withFileTypes: true }) : []\n for (const entry of existingEntries) {\n if (!entry.isDirectory()) continue\n if (desiredEntities.has(entry.name)) continue\n const staleDirectory = path.join(outRoot, entry.name)\n rimrafDir(staleDirectory)\n result.filesWritten.push(staleDirectory)\n }\n}\n\nfunction writeEntityFieldsRegistry(\n generatedRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n const entities = Object.keys(fieldsByEntity).sort((a, b) => a.localeCompare(b))\n const registry: Record<string, Record<string, string>> = {}\n for (const entity of entities) {\n registry[toVar(entity)] = {}\n for (const field of fieldsByEntity[entity] ?? []) {\n registry[toVar(entity)][toVar(field)] = field\n }\n }\n\n const sourceFile = createGeneratedSourceFile('entity-fields-registry.ts')\n addAutoGeneratedComment(sourceFile, 'entity-ids')\n sourceFile.insertText(sourceFile.getFullText().length, '// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility\\n')\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entityFieldsRegistry',\n type: 'Record<string, Record<string, string>>',\n initializer: JSON.stringify(registry, null, 2),\n },\n ],\n })\n sourceFile.addFunction({\n name: 'getEntityFields',\n isExported: true,\n parameters: [{ name: 'slug', type: 'string' }],\n returnType: 'Record<string, string> | undefined',\n statements: [returnStatement(elementAccess(identifier('entityFieldsRegistry'), identifier('slug')))],\n })\n const outPath = path.join(generatedRoot, 'entity-fields-registry.ts')\n writeTrackedFile(outPath, getSourceText(sourceFile), result)\n}\n\nexport async function generateEntityIds(options: EntityIdsOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.ids.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.ids.generated.checksum')\n\n const entries = resolver.loadEnabledModules()\n\n const consolidated: Record<string, Record<string, string>> = {}\n const grouped: Record<GroupKey, Record<string, Record<string, string>>> = {}\n const modulesDict: Record<string, string> = {}\n const groupedModulesDict: Record<GroupKey, Record<string, string>> = {}\n\n const fieldsByGroup: Record<GroupKey, Record<string, EntityFieldMap>> = {}\n\n for (const entry of entries) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const group: GroupKey = (entry.from as GroupKey) || '@open-mercato/core'\n\n const standaloneGeneratedPackageEntities = loadStandaloneGeneratedPackageEntities(resolver, entry)\n\n // Locate entities definition file (prefer app override)\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override', 'entities', 'schema']\n let importPath: string | null = null\n let filePath: string | null = null\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = resolveConventionFile(base, f)\n if (p) {\n const fromApp = base.startsWith(roots.appBase)\n const sub = path.basename(base) // 'data' | 'db'\n importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f}`\n filePath = p\n break\n }\n }\n if (importPath) break\n }\n\n // No entities file found -> still register module id\n if (!filePath && !standaloneGeneratedPackageEntities) {\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n\n const exportNames = filePath ? parseExportedClassNamesFromFile(filePath) : []\n\n const entityNames = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityNames\n : exportNames\n .map((k) => toSnake(k))\n .filter((k, idx, arr) => arr.indexOf(k) === idx)\n\n // Build dictionaries\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n\n consolidated[modId] = consolidated[modId] || {}\n grouped[group] = grouped[group] || {}\n grouped[group][modId] = grouped[group][modId] || {}\n\n for (const en of entityNames) {\n consolidated[modId][en] = `${modId}:${en}`\n grouped[group][modId][en] = `${modId}:${en}`\n }\n\n // Parse entity fields from TypeScript source\n const entityFieldMap = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityFieldMap\n : parseEntityFieldsFromFile(filePath!, exportNames)\n fieldsByGroup[group] = fieldsByGroup[group] || {}\n fieldsByGroup[group][modId] = entityFieldMap\n }\n\n // Write consolidated output\n const consolidatedSourceFile = createGeneratedSourceFile('entities.ids.generated.ts')\n addAutoGeneratedComment(consolidatedSourceFile, 'entity-ids')\n consolidatedSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(modulesDict, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(consolidated, null, 2)} as const` },\n ],\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const consolidatedSrc = getSourceText(consolidatedSourceFile)\n\n // Check if content has changed\n const newChecksum = calculateChecksum(consolidatedSrc)\n let shouldWrite = true\n\n const existingRecord = readChecksumRecord(checksumFile)\n if (existingRecord && existingRecord.content === newChecksum) {\n shouldWrite = false\n }\n\n if (shouldWrite) {\n ensureDir(outFile)\n fs.writeFileSync(outFile, consolidatedSrc)\n writeChecksumRecord(checksumFile, { content: newChecksum, structure: '' })\n result.filesWritten.push(outFile)\n if (!quiet) {\n logGenerationResult(path.relative(process.cwd(), outFile), true)\n }\n } else {\n result.filesUnchanged.push(outFile)\n }\n\n // Write per-group outputs\n const groups = Object.keys(grouped) as GroupKey[]\n for (const g of groups) {\n if (!resolver.isMonorepo() && g !== '@app') {\n continue\n }\n\n const pkgOutputDir = resolver.getPackageOutputDir(g)\n // Skip @app group since it writes to the same location as the consolidated output\n if (g === '@app' && pkgOutputDir === outputDir) {\n continue\n }\n const out = path.join(pkgOutputDir, 'entities.ids.generated.ts')\n\n const groupSourceFile = createGeneratedSourceFile(`${String(g)}/entities.ids.generated.ts`)\n addAutoGeneratedComment(groupSourceFile, 'entity-ids')\n groupSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(grouped[g] || {}, null, 2)} as const` },\n ],\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const src = getSourceText(groupSourceFile)\n writeTrackedFile(out, src, result)\n\n const fieldsRoot = path.join(pkgOutputDir, 'entities')\n const fieldsByModule = fieldsByGroup[g] || {}\n const combined: EntityFieldMap = {}\n for (const mId of Object.keys(fieldsByModule)) {\n const mMap = fieldsByModule[mId]\n for (const [entity, fields] of Object.entries(mMap)) {\n combined[entity] = Array.from(new Set([...(combined[entity] || []), ...fields]))\n }\n }\n writePerEntityFieldFiles(fieldsRoot, combined, result)\n\n // Generate static entity fields registry for Turbopack compatibility\n writeEntityFieldsRegistry(pkgOutputDir, combined, result)\n }\n\n // Write combined entity fields to root generated/ folder\n const combinedAll: EntityFieldMap = {}\n for (const groupFields of Object.values(fieldsByGroup)) {\n for (const mMap of Object.values(groupFields)) {\n for (const [entity, fields] of Object.entries(mMap)) {\n combinedAll[entity] = Array.from(new Set([...(combinedAll[entity] || []), ...fields]))\n }\n }\n }\n writePerEntityFieldFiles(path.join(outputDir, 'entities'), combinedAll, result)\n writeEntityFieldsRegistry(outputDir, combinedAll, result)\n\n return result\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
4
|
+
"sourcesContent": ["import fs from 'node:fs'\nimport path from 'node:path'\nimport ts from 'typescript-js'\nimport { VariableDeclarationKind } from 'ts-morph'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\nimport { MODULE_CODE_EXTENSIONS } from './scanner'\nimport {\n calculateChecksum,\n readChecksumRecord,\n writeChecksumRecord,\n ensureDir,\n toVar,\n toSnake,\n rimrafDir,\n logGenerationResult,\n writeIfChanged,\n type GeneratorResult,\n createGeneratorResult,\n} from '../utils'\nimport { addAutoGeneratedComment, createGeneratedSourceFile, elementAccess, getSourceText, identifier, returnStatement } from './ast'\n\ntype GroupKey = '@app' | '@open-mercato/core' | string\ntype EntityFieldMap = Record<string, string[]>\n\nexport interface EntityIdsOptions {\n resolver: PackageResolver\n quiet?: boolean\n}\n\n/**\n * Extract exported class names from a TypeScript source file without dynamic import.\n * This is used for @app modules since Node.js can't import TypeScript files directly.\n */\nfunction parseExportedClassNamesFromFile(filePath: string): string[] {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n const classNames: string[] = []\n\n sf.forEachChild((node) => {\n // Check for exported class declarations\n if (ts.isClassDeclaration(node) && node.name) {\n const hasExport = node.modifiers?.some(\n (m) => m.kind === ts.SyntaxKind.ExportKeyword\n )\n if (hasExport) {\n classNames.push(node.name.text)\n }\n }\n })\n\n return classNames\n}\n\nfunction unwrapObjectLiteralExpression(\n expression: ts.Expression | undefined,\n): ts.ObjectLiteralExpression | undefined {\n if (!expression) return undefined\n if (ts.isObjectLiteralExpression(expression)) return expression\n if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n if (ts.isParenthesizedExpression(expression)) {\n return unwrapObjectLiteralExpression(expression.expression)\n }\n return undefined\n}\n\nfunction readPropertyInitializer(\n objectLiteral: ts.ObjectLiteralExpression,\n propertyName: string,\n): ts.Expression | undefined {\n for (const property of objectLiteral.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name === propertyName) {\n return property.initializer\n }\n }\n return undefined\n}\n\nfunction parseGeneratedModuleEntityNames(filePath: string, moduleId: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n const declaration = statement.declarationList.declarations.find((candidate) =>\n ts.isIdentifier(candidate.name) && candidate.name.text === 'E')\n if (!declaration) continue\n\n const eObject = unwrapObjectLiteralExpression(declaration.initializer)\n if (!eObject) continue\n\n const moduleObject = unwrapObjectLiteralExpression(readPropertyInitializer(eObject, moduleId))\n if (!moduleObject) return []\n\n const names: string[] = []\n for (const property of moduleObject.properties) {\n if (!ts.isPropertyAssignment(property)) continue\n const name = ts.isIdentifier(property.name)\n ? property.name.text\n : ts.isStringLiteralLike(property.name)\n ? property.name.text\n : undefined\n if (name) names.push(name)\n }\n return names\n }\n\n return []\n}\n\nfunction parseGeneratedEntityFieldsFile(filePath: string): string[] {\n if (!fs.existsSync(filePath)) return []\n\n const source = fs.readFileSync(filePath, 'utf8')\n const scriptKind = filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n const sf = ts.createSourceFile(filePath, source, ts.ScriptTarget.ES2020, true, scriptKind)\n const fields: string[] = []\n\n for (const statement of sf.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name) || !declaration.initializer) continue\n if (!ts.isStringLiteralLike(declaration.initializer)) continue\n fields.push(declaration.initializer.text)\n }\n }\n\n return Array.from(new Set(fields))\n}\n\nfunction resolveExistingFile(candidates: string[]): string | null {\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n\nfunction loadStandaloneGeneratedPackageEntities(\n resolver: PackageResolver,\n entry: ModuleEntry,\n): { entityNames: string[]; entityFieldMap: EntityFieldMap } | null {\n if (resolver.isMonorepo() || !entry.from || entry.from === '@app') return null\n\n const packageRoot = resolver.getPackageRoot(entry.from)\n const generatedRoot = fs.existsSync(path.join(packageRoot, 'generated'))\n ? path.join(packageRoot, 'generated')\n : path.join(packageRoot, 'dist', 'generated')\n const idsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities.ids.generated.ts'),\n path.join(generatedRoot, 'entities.ids.generated.js'),\n ])\n if (!idsFile) return null\n const entityNames = parseGeneratedModuleEntityNames(idsFile, entry.id)\n\n if (entityNames.length === 0) return null\n\n const entityFieldMap: EntityFieldMap = {}\n for (const entityName of entityNames) {\n const fieldsFile = resolveExistingFile([\n path.join(generatedRoot, 'entities', entityName, 'index.ts'),\n path.join(generatedRoot, 'entities', entityName, 'index.js'),\n ])\n if (!fieldsFile) continue\n const fields = parseGeneratedEntityFieldsFile(fieldsFile)\n entityFieldMap[entityName] = fields\n }\n\n return { entityNames, entityFieldMap }\n}\n\nfunction parseEntityFieldsFromFile(filePath: string, exportedClassNames: string[]): EntityFieldMap {\n const src = fs.readFileSync(filePath, 'utf8')\n const sf = ts.createSourceFile(filePath, src, ts.ScriptTarget.ES2020, true, ts.ScriptKind.TS)\n\n const exported = new Set(exportedClassNames)\n const result: EntityFieldMap = {}\n\n function getDecoratorArgNameLiteral(dec: ts.Decorator | undefined): string | undefined {\n if (!dec) return undefined\n const expr = dec.expression\n if (!ts.isCallExpression(expr)) return undefined\n if (!expr.arguments.length) return undefined\n const first = expr.arguments[0]\n if (!ts.isObjectLiteralExpression(first)) return undefined\n for (const prop of first.properties) {\n if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && prop.name.text === 'name') {\n if (ts.isStringLiteral(prop.initializer)) return prop.initializer.text\n }\n }\n return undefined\n }\n\n function normalizeDbName(propertyName: string, _decoratorName?: string, nameOverride?: string): string {\n if (nameOverride) return nameOverride\n return toSnake(propertyName)\n }\n\n sf.forEachChild((node) => {\n if (!ts.isClassDeclaration(node) || !node.name) return\n const clsName = node.name.text\n if (!exported.has(clsName)) return\n const entityKey = toSnake(clsName)\n const fields: string[] = []\n\n for (const member of node.members) {\n if (!ts.isPropertyDeclaration(member) || !member.name) continue\n const name = ts.isIdentifier(member.name)\n ? member.name.text\n : ts.isStringLiteral(member.name)\n ? member.name.text\n : undefined\n if (!name) continue\n if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) continue\n const decorators = ts.canHaveDecorators(member)\n ? ts.getDecorators(member) ?? []\n : []\n let dbName: string | undefined\n if (decorators && decorators.length) {\n for (const d of decorators) {\n const nameOverride = getDecoratorArgNameLiteral(d)\n dbName = normalizeDbName(name, undefined, nameOverride)\n if (dbName) break\n }\n }\n if (!dbName) dbName = normalizeDbName(name)\n fields.push(dbName)\n }\n result[entityKey] = Array.from(new Set(fields))\n })\n\n return result\n}\n\nfunction writeTrackedFile(\n filePath: string,\n content: string,\n result: GeneratorResult,\n): void {\n if (writeIfChanged(filePath, content)) {\n result.filesWritten.push(filePath)\n } else {\n result.filesUnchanged.push(filePath)\n }\n}\n\nfunction writePerEntityFieldFiles(\n outRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n fs.mkdirSync(outRoot, { recursive: true })\n const desiredEntities = new Set(Object.keys(fieldsByEntity))\n for (const [entity, fields] of Object.entries(fieldsByEntity)) {\n const entDir = path.join(outRoot, entity)\n fs.mkdirSync(entDir, { recursive: true })\n const sourceFile = createGeneratedSourceFile(`${entity}/index.ts`)\n for (const field of fields) {\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: toVar(field),\n initializer: JSON.stringify(field),\n },\n ],\n })\n }\n writeTrackedFile(path.join(entDir, 'index.ts'), getSourceText(sourceFile), result)\n }\n\n const existingEntries = fs.existsSync(outRoot) ? fs.readdirSync(outRoot, { withFileTypes: true }) : []\n for (const entry of existingEntries) {\n if (!entry.isDirectory()) continue\n if (desiredEntities.has(entry.name)) continue\n const staleDirectory = path.join(outRoot, entry.name)\n rimrafDir(staleDirectory)\n result.filesWritten.push(staleDirectory)\n }\n}\n\nfunction writeEntityFieldsRegistry(\n generatedRoot: string,\n fieldsByEntity: EntityFieldMap,\n result: GeneratorResult,\n): void {\n const entities = Object.keys(fieldsByEntity).sort((a, b) => a.localeCompare(b))\n const registry: Record<string, Record<string, string>> = {}\n for (const entity of entities) {\n registry[toVar(entity)] = {}\n for (const field of fieldsByEntity[entity] ?? []) {\n registry[toVar(entity)][toVar(field)] = field\n }\n }\n\n const sourceFile = createGeneratedSourceFile('entity-fields-registry.ts')\n addAutoGeneratedComment(sourceFile, 'entity-ids')\n sourceFile.insertText(sourceFile.getFullText().length, '// Static registry for entity fields - eliminates dynamic imports for Turbopack compatibility\\n')\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: 'entityFieldsRegistry',\n type: 'Record<string, Record<string, string>>',\n initializer: JSON.stringify(registry, null, 2),\n },\n ],\n })\n sourceFile.addFunction({\n name: 'getEntityFields',\n isExported: true,\n parameters: [{ name: 'slug', type: 'string' }],\n returnType: 'Record<string, string> | undefined',\n statements: [returnStatement(elementAccess(identifier('entityFieldsRegistry'), identifier('slug')))],\n })\n const outPath = path.join(generatedRoot, 'entity-fields-registry.ts')\n writeTrackedFile(outPath, getSourceText(sourceFile), result)\n}\n\nexport async function generateEntityIds(options: EntityIdsOptions): Promise<GeneratorResult> {\n const { resolver, quiet = false } = options\n const result = createGeneratorResult()\n\n const outputDir = resolver.getOutputDir()\n const outFile = path.join(outputDir, 'entities.ids.generated.ts')\n const checksumFile = path.join(outputDir, 'entities.ids.generated.checksum')\n\n const entries = resolver.loadEnabledModules()\n\n const consolidated: Record<string, Record<string, string>> = {}\n const grouped: Record<GroupKey, Record<string, Record<string, string>>> = {}\n const modulesDict: Record<string, string> = {}\n const groupedModulesDict: Record<GroupKey, Record<string, string>> = {}\n\n const fieldsByGroup: Record<GroupKey, Record<string, EntityFieldMap>> = {}\n\n for (const entry of entries) {\n const modId = entry.id\n const roots = resolver.getModulePaths(entry)\n const imps = resolver.getModuleImportBase(entry)\n const group: GroupKey = (entry.from as GroupKey) || '@open-mercato/core'\n\n const standaloneGeneratedPackageEntities = loadStandaloneGeneratedPackageEntities(resolver, entry)\n\n // Locate entities definition file (prefer app override)\n const appData = path.join(roots.appBase, 'data')\n const pkgData = path.join(roots.pkgBase, 'data')\n const appDb = path.join(roots.appBase, 'db')\n const pkgDb = path.join(roots.pkgBase, 'db')\n const bases = [appData, pkgData, appDb, pkgDb]\n const candidates = ['entities.override', 'entities', 'schema']\n let importPath: string | null = null\n let filePath: string | null = null\n\n for (const base of bases) {\n for (const f of candidates) {\n const p = resolveConventionFile(base, f)\n if (p) {\n const fromApp = base.startsWith(roots.appBase)\n const sub = path.basename(base) // 'data' | 'db'\n importPath = `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f}`\n filePath = p\n break\n }\n }\n if (importPath) break\n }\n\n // No entities file found -> still register module id\n if (!filePath && !standaloneGeneratedPackageEntities) {\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n continue\n }\n\n const exportNames = filePath ? parseExportedClassNamesFromFile(filePath) : []\n\n const entityNames = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityNames\n : exportNames\n .map((k) => toSnake(k))\n .filter((k, idx, arr) => arr.indexOf(k) === idx)\n\n // Build dictionaries\n modulesDict[modId] = modId\n groupedModulesDict[group] = groupedModulesDict[group] || {}\n groupedModulesDict[group][modId] = modId\n\n consolidated[modId] = consolidated[modId] || {}\n grouped[group] = grouped[group] || {}\n grouped[group][modId] = grouped[group][modId] || {}\n\n for (const en of entityNames) {\n consolidated[modId][en] = `${modId}:${en}`\n grouped[group][modId][en] = `${modId}:${en}`\n }\n\n // Parse entity fields from TypeScript source\n const entityFieldMap = standaloneGeneratedPackageEntities\n ? standaloneGeneratedPackageEntities.entityFieldMap\n : parseEntityFieldsFromFile(filePath!, exportNames)\n fieldsByGroup[group] = fieldsByGroup[group] || {}\n fieldsByGroup[group][modId] = entityFieldMap\n }\n\n // Write consolidated output\n const consolidatedSourceFile = createGeneratedSourceFile('entities.ids.generated.ts')\n addAutoGeneratedComment(consolidatedSourceFile, 'entity-ids')\n consolidatedSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(modulesDict, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(consolidated, null, 2)} as const` },\n ],\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n consolidatedSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const consolidatedSrc = getSourceText(consolidatedSourceFile)\n\n // Check if content has changed\n const newChecksum = calculateChecksum(consolidatedSrc)\n let shouldWrite = true\n\n const existingRecord = readChecksumRecord(checksumFile)\n if (existingRecord && existingRecord.content === newChecksum) {\n shouldWrite = false\n }\n\n if (shouldWrite) {\n ensureDir(outFile)\n fs.writeFileSync(outFile, consolidatedSrc)\n writeChecksumRecord(checksumFile, { content: newChecksum, structure: '' })\n result.filesWritten.push(outFile)\n if (!quiet) {\n logGenerationResult(path.relative(process.cwd(), outFile), true)\n }\n } else {\n result.filesUnchanged.push(outFile)\n }\n\n // Write per-group outputs\n const groups = Object.keys(grouped) as GroupKey[]\n for (const g of groups) {\n if (!resolver.isMonorepo() && g !== '@app') {\n continue\n }\n\n const pkgOutputDir = resolver.getPackageOutputDir(g)\n // Skip @app group since it writes to the same location as the consolidated output\n if (g === '@app' && pkgOutputDir === outputDir) {\n continue\n }\n const out = path.join(pkgOutputDir, 'entities.ids.generated.ts')\n\n const groupSourceFile = createGeneratedSourceFile(`${String(g)}/entities.ids.generated.ts`)\n addAutoGeneratedComment(groupSourceFile, 'entity-ids')\n groupSourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n { name: 'M', initializer: `${JSON.stringify(groupedModulesDict[g] || {}, null, 2)} as const` },\n { name: 'E', initializer: `${JSON.stringify(grouped[g] || {}, null, 2)} as const` },\n ],\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownModuleId',\n isExported: true,\n type: 'keyof typeof M',\n })\n groupSourceFile.addTypeAlias({\n name: 'KnownEntities',\n isExported: true,\n type: 'typeof E',\n })\n const src = getSourceText(groupSourceFile)\n writeTrackedFile(out, src, result)\n\n const fieldsRoot = path.join(pkgOutputDir, 'entities')\n const fieldsByModule = fieldsByGroup[g] || {}\n const combined: EntityFieldMap = {}\n for (const mId of Object.keys(fieldsByModule)) {\n const mMap = fieldsByModule[mId]\n for (const [entity, fields] of Object.entries(mMap)) {\n combined[entity] = Array.from(new Set([...(combined[entity] || []), ...fields]))\n }\n }\n writePerEntityFieldFiles(fieldsRoot, combined, result)\n\n // Generate static entity fields registry for Turbopack compatibility\n writeEntityFieldsRegistry(pkgOutputDir, combined, result)\n }\n\n // Write combined entity fields to root generated/ folder\n const combinedAll: EntityFieldMap = {}\n for (const groupFields of Object.values(fieldsByGroup)) {\n for (const mMap of Object.values(groupFields)) {\n for (const [entity, fields] of Object.entries(mMap)) {\n combinedAll[entity] = Array.from(new Set([...(combinedAll[entity] || []), ...fields]))\n }\n }\n }\n writePerEntityFieldFiles(path.join(outputDir, 'entities'), combinedAll, result)\n writeEntityFieldsRegistry(outputDir, combinedAll, result)\n\n return result\n}\n\nfunction resolveConventionFile(baseDir: string, basename: string): string | null {\n for (const extension of MODULE_CODE_EXTENSIONS) {\n const candidate = path.join(baseDir, `${basename}${extension}`)\n if (fs.existsSync(candidate)) return candidate\n }\n return null\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { VariableDeclarationKind } from "ts-morph";
|
|
4
|
-
import ts from "typescript";
|
|
4
|
+
import ts from "typescript-js";
|
|
5
5
|
import { resolveStandaloneSourceMirrorBase, scanModuleDir, SCAN_CONFIGS } from "../scanner.js";
|
|
6
6
|
import {
|
|
7
7
|
arrayLiteral,
|