@open-mercato/cli 0.4.2-canary-c02407ff85

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.
Files changed (51) hide show
  1. package/bin/mercato +21 -0
  2. package/build.mjs +78 -0
  3. package/dist/bin.js +51 -0
  4. package/dist/bin.js.map +7 -0
  5. package/dist/index.js +5 -0
  6. package/dist/index.js.map +7 -0
  7. package/dist/lib/db/commands.js +350 -0
  8. package/dist/lib/db/commands.js.map +7 -0
  9. package/dist/lib/db/index.js +7 -0
  10. package/dist/lib/db/index.js.map +7 -0
  11. package/dist/lib/generators/entity-ids.js +257 -0
  12. package/dist/lib/generators/entity-ids.js.map +7 -0
  13. package/dist/lib/generators/index.js +12 -0
  14. package/dist/lib/generators/index.js.map +7 -0
  15. package/dist/lib/generators/module-di.js +73 -0
  16. package/dist/lib/generators/module-di.js.map +7 -0
  17. package/dist/lib/generators/module-entities.js +104 -0
  18. package/dist/lib/generators/module-entities.js.map +7 -0
  19. package/dist/lib/generators/module-registry.js +1081 -0
  20. package/dist/lib/generators/module-registry.js.map +7 -0
  21. package/dist/lib/resolver.js +205 -0
  22. package/dist/lib/resolver.js.map +7 -0
  23. package/dist/lib/utils.js +161 -0
  24. package/dist/lib/utils.js.map +7 -0
  25. package/dist/mercato.js +1045 -0
  26. package/dist/mercato.js.map +7 -0
  27. package/dist/registry.js +7 -0
  28. package/dist/registry.js.map +7 -0
  29. package/jest.config.cjs +19 -0
  30. package/package.json +71 -0
  31. package/src/__tests__/mercato.test.ts +90 -0
  32. package/src/bin.ts +74 -0
  33. package/src/index.ts +2 -0
  34. package/src/lib/__tests__/resolver.test.ts +101 -0
  35. package/src/lib/__tests__/utils.test.ts +270 -0
  36. package/src/lib/db/__tests__/commands.test.ts +131 -0
  37. package/src/lib/db/commands.ts +431 -0
  38. package/src/lib/db/index.ts +1 -0
  39. package/src/lib/generators/__tests__/generators.test.ts +197 -0
  40. package/src/lib/generators/entity-ids.ts +336 -0
  41. package/src/lib/generators/index.ts +4 -0
  42. package/src/lib/generators/module-di.ts +89 -0
  43. package/src/lib/generators/module-entities.ts +124 -0
  44. package/src/lib/generators/module-registry.ts +1222 -0
  45. package/src/lib/resolver.ts +308 -0
  46. package/src/lib/utils.ts +200 -0
  47. package/src/mercato.ts +1106 -0
  48. package/src/registry.ts +2 -0
  49. package/tsconfig.build.json +4 -0
  50. package/tsconfig.json +12 -0
  51. package/watch.mjs +6 -0
package/bin/mercato ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Stub loader for the mercato CLI
4
+ // This file exists so yarn can create bin symlinks before the package is built.
5
+ // It dynamically loads the actual CLI from dist/bin.js
6
+
7
+ import { existsSync } from 'node:fs';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ const distBin = join(__dirname, '..', 'dist', 'bin.js');
13
+
14
+ if (!existsSync(distBin)) {
15
+ console.error('Error: CLI not built. Run "yarn build:packages" first.');
16
+ console.error(`Expected: ${distBin}`);
17
+ process.exit(1);
18
+ }
19
+
20
+ // Import the actual CLI
21
+ await import(distBin);
package/build.mjs ADDED
@@ -0,0 +1,78 @@
1
+ import * as esbuild from 'esbuild'
2
+ import { glob } from 'glob'
3
+ import { readFileSync, writeFileSync, chmodSync, existsSync } from 'node:fs'
4
+ import { dirname, join } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url))
8
+
9
+ const entryPoints = await glob(join(__dirname, 'src/**/*.ts'), { ignore: ['**/__tests__/**', '**/*.test.ts'] })
10
+
11
+ // Plugin to add .js extension to relative imports
12
+ const addJsExtension = {
13
+ name: 'add-js-extension',
14
+ setup(build) {
15
+ build.onEnd(async (result) => {
16
+ if (result.errors.length > 0) return
17
+ const outputFiles = await glob(join(__dirname, 'dist/**/*.js'))
18
+ for (const file of outputFiles) {
19
+ const fileDir = dirname(file)
20
+ let content = readFileSync(file, 'utf-8')
21
+ // Add .js to relative imports that don't have an extension
22
+ content = content.replace(
23
+ /from\s+["'](\.[^"']+)["']/g,
24
+ (match, path) => {
25
+ // Skip paths that already have an extension (including .ts for generated code templates)
26
+ if (path.endsWith('.js') || path.endsWith('.json') || path.endsWith('.ts')) return match
27
+ // Skip paths containing template literal placeholders (code generation templates)
28
+ if (path.includes('${')) return match
29
+ // Check if it's a directory with index.js
30
+ const resolvedPath = join(fileDir, path)
31
+ if (existsSync(resolvedPath) && existsSync(join(resolvedPath, 'index.js'))) {
32
+ return `from "${path}/index.js"`
33
+ }
34
+ return `from "${path}.js"`
35
+ }
36
+ )
37
+ content = content.replace(
38
+ /import\s*\(\s*["'](\.[^"']+)["']\s*\)/g,
39
+ (match, path) => {
40
+ // Skip paths that already have an extension (including .ts for generated code templates)
41
+ if (path.endsWith('.js') || path.endsWith('.json') || path.endsWith('.ts')) return match
42
+ // Skip paths containing template literal placeholders (code generation templates)
43
+ if (path.includes('${')) return match
44
+ // Check if it's a directory with index.js
45
+ const resolvedPath = join(fileDir, path)
46
+ if (existsSync(resolvedPath) && existsSync(join(resolvedPath, 'index.js'))) {
47
+ return `import("${path}/index.js")`
48
+ }
49
+ return `import("${path}.js")`
50
+ }
51
+ )
52
+ writeFileSync(file, content)
53
+ }
54
+ })
55
+ }
56
+ }
57
+
58
+ const outdir = join(__dirname, 'dist')
59
+
60
+ await esbuild.build({
61
+ entryPoints,
62
+ outdir,
63
+ outbase: join(__dirname, 'src'),
64
+ format: 'esm',
65
+ platform: 'node',
66
+ target: 'node18',
67
+ sourcemap: true,
68
+ bundle: false,
69
+ plugins: [addJsExtension],
70
+ })
71
+
72
+ // Make bin.js executable with shebang
73
+ const binPath = join(__dirname, 'dist/bin.js')
74
+ const binContent = readFileSync(binPath, 'utf-8')
75
+ writeFileSync(binPath, '#!/usr/bin/env node\n' + binContent)
76
+ chmodSync(binPath, 0o755)
77
+
78
+ console.log('CLI built successfully')
package/dist/bin.js ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "./mercato.js";
3
+ const BOOTSTRAP_FREE_COMMANDS = ["generate", "db", "init", "help", "--help", "-h"];
4
+ function needsBootstrap(argv) {
5
+ const [, , first] = argv;
6
+ if (!first) return false;
7
+ return !BOOTSTRAP_FREE_COMMANDS.includes(first);
8
+ }
9
+ async function tryBootstrap() {
10
+ try {
11
+ const { bootstrapFromAppRoot } = await import("@open-mercato/shared/lib/bootstrap/dynamicLoader");
12
+ const { registerCliModules } = await import("./mercato.js");
13
+ const { createResolver } = await import("./lib/resolver.js");
14
+ const resolver = createResolver();
15
+ const appDir = resolver.getAppDir();
16
+ const data = await bootstrapFromAppRoot(appDir);
17
+ registerCliModules(data.modules);
18
+ return true;
19
+ } catch (err) {
20
+ const message = err instanceof Error ? err.message : String(err);
21
+ if (message.includes("Cannot find module") && (message.includes("/generated/") || message.includes(".generated") || message.includes(".mercato"))) {
22
+ return false;
23
+ }
24
+ throw err;
25
+ }
26
+ }
27
+ async function main() {
28
+ const requiresBootstrap = needsBootstrap(process.argv);
29
+ if (requiresBootstrap) {
30
+ const bootstrapSucceeded = await tryBootstrap();
31
+ if (!bootstrapSucceeded) {
32
+ console.error("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
33
+ console.error("\u2551 Generated files not found! \u2551");
34
+ console.error("\u2551 \u2551");
35
+ console.error("\u2551 The CLI requires generated files to discover modules. \u2551");
36
+ console.error("\u2551 Please run the following command first: \u2551");
37
+ console.error("\u2551 \u2551");
38
+ console.error("\u2551 yarn mercato generate \u2551");
39
+ console.error("\u2551 \u2551");
40
+ console.error("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
41
+ process.exit(1);
42
+ }
43
+ }
44
+ const code = await run(process.argv);
45
+ process.exit(code ?? 0);
46
+ }
47
+ main().catch((e) => {
48
+ console.error(e);
49
+ process.exit(1);
50
+ });
51
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/bin.ts"],
4
+ "sourcesContent": ["/**\n * CLI binary entry point for @open-mercato/cli package.\n *\n * Called from within a Next.js app directory as: yarn mercato <command>\n * Uses dynamic app resolution to find generated files at .mercato/generated/\n */\nimport { run } from './mercato.js'\n\n// Commands that can run without bootstrap (without generated files)\n// - generate: creates the generated files\n// - db: uses resolver directly to find modules and migrations\n// - init: runs yarn commands to set up the app\n// - help: just shows help text\nconst BOOTSTRAP_FREE_COMMANDS = ['generate', 'db', 'init', 'help', '--help', '-h']\n\nfunction needsBootstrap(argv: string[]): boolean {\n const [, , first] = argv\n if (!first) return false // help screen\n return !BOOTSTRAP_FREE_COMMANDS.includes(first)\n}\n\nasync function tryBootstrap(): Promise<boolean> {\n try {\n const { bootstrapFromAppRoot } = await import('@open-mercato/shared/lib/bootstrap/dynamicLoader')\n const { registerCliModules } = await import('./mercato.js')\n // Use the CLI resolver to find the app directory (handles monorepo detection)\n const { createResolver } = await import('./lib/resolver.js')\n const resolver = createResolver()\n const appDir = resolver.getAppDir()\n const data = await bootstrapFromAppRoot(appDir)\n // Register CLI modules directly to avoid module resolution issues\n registerCliModules(data.modules)\n return true\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n // Check if the error is about missing generated files\n if (\n message.includes('Cannot find module') &&\n (message.includes('/generated/') || message.includes('.generated') || message.includes('.mercato'))\n ) {\n return false\n }\n // Re-throw other errors\n throw err\n }\n}\n\nasync function main(): Promise<void> {\n const requiresBootstrap = needsBootstrap(process.argv)\n\n if (requiresBootstrap) {\n const bootstrapSucceeded = await tryBootstrap()\n if (!bootstrapSucceeded) {\n console.error('\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557')\n console.error('\u2551 Generated files not found! \u2551')\n console.error('\u2551 \u2551')\n console.error('\u2551 The CLI requires generated files to discover modules. \u2551')\n console.error('\u2551 Please run the following command first: \u2551')\n console.error('\u2551 \u2551')\n console.error('\u2551 yarn mercato generate \u2551')\n console.error('\u2551 \u2551')\n console.error('\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D')\n process.exit(1)\n }\n }\n\n const code = await run(process.argv)\n process.exit(code ?? 0)\n}\n\nmain().catch((e) => {\n console.error(e)\n process.exit(1)\n})\n"],
5
+ "mappings": "AAMA,SAAS,WAAW;AAOpB,MAAM,0BAA0B,CAAC,YAAY,MAAM,QAAQ,QAAQ,UAAU,IAAI;AAEjF,SAAS,eAAe,MAAyB;AAC/C,QAAM,CAAC,EAAE,EAAE,KAAK,IAAI;AACpB,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,CAAC,wBAAwB,SAAS,KAAK;AAChD;AAEA,eAAe,eAAiC;AAC9C,MAAI;AACF,UAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,kDAAkD;AAChG,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,cAAc;AAE1D,UAAM,EAAE,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAC3D,UAAM,WAAW,eAAe;AAChC,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,OAAO,MAAM,qBAAqB,MAAM;AAE9C,uBAAmB,KAAK,OAAO;AAC/B,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE/D,QACE,QAAQ,SAAS,oBAAoB,MACpC,QAAQ,SAAS,aAAa,KAAK,QAAQ,SAAS,YAAY,KAAK,QAAQ,SAAS,UAAU,IACjG;AACA,aAAO;AAAA,IACT;AAEA,UAAM;AAAA,EACR;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,oBAAoB,eAAe,QAAQ,IAAI;AAErD,MAAI,mBAAmB;AACrB,UAAM,qBAAqB,MAAM,aAAa;AAC9C,QAAI,CAAC,oBAAoB;AACvB,cAAQ,MAAM,gaAAuE;AACrF,cAAQ,MAAM,iFAAuE;AACrF,cAAQ,MAAM,iFAAuE;AACrF,cAAQ,MAAM,gFAAsE;AACpF,cAAQ,MAAM,gFAAsE;AACpF,cAAQ,MAAM,iFAAuE;AACrF,cAAQ,MAAM,gFAAsE;AACpF,cAAQ,MAAM,iFAAuE;AACrF,cAAQ,MAAM,gaAAuE;AACrF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,IAAI,QAAQ,IAAI;AACnC,UAAQ,KAAK,QAAQ,CAAC;AACxB;AAEA,KAAK,EAAE,MAAM,CAAC,MAAM;AAClB,UAAQ,MAAM,CAAC;AACf,UAAQ,KAAK,CAAC;AAChB,CAAC;",
6
+ "names": []
7
+ }
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { run } from "./mercato.js";
2
+ export {
3
+ run as runMercatoCli
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["export { run as runMercatoCli } from './mercato'\n\n"],
5
+ "mappings": "AAAA,SAAgB,WAAqB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,350 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { MikroORM } from "@mikro-orm/core";
4
+ import { PostgreSqlDriver } from "@mikro-orm/postgresql";
5
+ const QUIET_MODE = process.env.OM_CLI_QUIET === "1" || process.env.MERCATO_QUIET === "1";
6
+ const PROGRESS_EMOJI = "";
7
+ function formatResult(modId, message, emoji = "\u2022") {
8
+ return `${emoji} ${modId}: ${message}`;
9
+ }
10
+ function createProgressRenderer(total) {
11
+ const width = 20;
12
+ const normalizedTotal = total > 0 ? total : 1;
13
+ return (current) => {
14
+ const clamped = Math.min(Math.max(current, 0), normalizedTotal);
15
+ const filled = Math.round(clamped / normalizedTotal * width);
16
+ const bar = `${"=".repeat(filled)}${".".repeat(Math.max(width - filled, 0))}`;
17
+ return `[${bar}] ${clamped}/${normalizedTotal}`;
18
+ };
19
+ }
20
+ function createMinimalLogger() {
21
+ return {
22
+ log: () => {
23
+ },
24
+ error: (_namespace, message) => console.error(message),
25
+ warn: (_namespace, message) => {
26
+ if (!QUIET_MODE) console.warn(message);
27
+ },
28
+ logQuery: () => {
29
+ },
30
+ setDebugMode: () => {
31
+ },
32
+ isEnabled: () => false
33
+ };
34
+ }
35
+ function getClientUrl() {
36
+ const url = process.env.DATABASE_URL;
37
+ if (!url) throw new Error("DATABASE_URL is not set");
38
+ return url;
39
+ }
40
+ function sortModules(mods) {
41
+ return mods.slice().sort((a, b) => a.id.localeCompare(b.id));
42
+ }
43
+ function sanitizeModuleId(modId) {
44
+ return modId.replace(/[^a-z0-9_]/gi, "_");
45
+ }
46
+ function validateTableName(tableName) {
47
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
48
+ throw new Error(`Invalid table name: ${tableName}. Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`);
49
+ }
50
+ }
51
+ async function loadModuleEntities(entry, resolver) {
52
+ const roots = resolver.getModulePaths(entry);
53
+ const imps = resolver.getModuleImportBase(entry);
54
+ const isAppModule = entry.from === "@app";
55
+ const bases = [
56
+ path.join(roots.appBase, "data"),
57
+ path.join(roots.pkgBase, "data"),
58
+ path.join(roots.appBase, "db"),
59
+ path.join(roots.pkgBase, "db")
60
+ ];
61
+ const candidates = ["entities.ts", "schema.ts"];
62
+ for (const base of bases) {
63
+ for (const f of candidates) {
64
+ const p = path.join(base, f);
65
+ if (fs.existsSync(p)) {
66
+ const sub = path.basename(base);
67
+ const fromApp = base.startsWith(roots.appBase);
68
+ const importPath = isAppModule && fromApp ? `file://${p.replace(/\.ts$/, ".js")}` : `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\.ts$/, "")}`;
69
+ try {
70
+ const mod = await import(importPath);
71
+ const entities = Object.values(mod).filter((v) => typeof v === "function");
72
+ if (entities.length) return entities;
73
+ } catch (err) {
74
+ if (isAppModule) continue;
75
+ throw err;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ return [];
81
+ }
82
+ function getMigrationsPath(entry, resolver) {
83
+ const from = entry.from || "@open-mercato/core";
84
+ let pkgModRoot;
85
+ if (from === "@open-mercato/core") {
86
+ pkgModRoot = path.join(resolver.getRootDir(), "packages/core/src/modules", entry.id);
87
+ } else if (/^@open-mercato\//.test(from)) {
88
+ const segs = from.split("/");
89
+ if (segs.length > 1 && segs[1]) {
90
+ pkgModRoot = path.join(resolver.getRootDir(), `packages/${segs[1]}/src/modules`, entry.id);
91
+ } else {
92
+ pkgModRoot = path.join(resolver.getRootDir(), "packages/core/src/modules", entry.id);
93
+ }
94
+ } else if (from === "@app") {
95
+ pkgModRoot = path.join(resolver.getAppDir(), "src/modules", entry.id);
96
+ } else {
97
+ pkgModRoot = path.join(resolver.getRootDir(), "packages/core/src/modules", entry.id);
98
+ }
99
+ return path.join(pkgModRoot, "migrations");
100
+ }
101
+ async function dbGenerate(resolver, options = {}) {
102
+ const modules = resolver.loadEnabledModules();
103
+ const ordered = sortModules(modules);
104
+ const results = [];
105
+ for (const entry of ordered) {
106
+ const modId = entry.id;
107
+ const sanitizedModId = sanitizeModuleId(modId);
108
+ const entities = await loadModuleEntities(entry, resolver);
109
+ if (!entities.length) continue;
110
+ const migrationsPath = getMigrationsPath(entry, resolver);
111
+ fs.mkdirSync(migrationsPath, { recursive: true });
112
+ const tableName = `mikro_orm_migrations_${sanitizedModId}`;
113
+ validateTableName(tableName);
114
+ const orm = await MikroORM.init({
115
+ driver: PostgreSqlDriver,
116
+ clientUrl: getClientUrl(),
117
+ loggerFactory: () => createMinimalLogger(),
118
+ entities,
119
+ migrations: {
120
+ path: migrationsPath,
121
+ glob: "!(*.d).{ts,js}",
122
+ tableName,
123
+ dropTables: false
124
+ },
125
+ schemaGenerator: {
126
+ disableForeignKeys: true
127
+ },
128
+ pool: {
129
+ min: 1,
130
+ max: 3,
131
+ idleTimeoutMillis: 3e4,
132
+ acquireTimeoutMillis: 6e4,
133
+ destroyTimeoutMillis: 3e4
134
+ }
135
+ });
136
+ const migrator = orm.getMigrator();
137
+ const diff = await migrator.createMigration();
138
+ if (diff && diff.fileName) {
139
+ try {
140
+ const orig = diff.fileName;
141
+ const base = path.basename(orig);
142
+ const dir = path.dirname(orig);
143
+ const ext = path.extname(base);
144
+ const stem = base.replace(ext, "");
145
+ const suffix = `_${modId}`;
146
+ const newBase = stem.endsWith(suffix) ? base : `${stem}${suffix}${ext}`;
147
+ const newPath = path.join(dir, newBase);
148
+ let content = fs.readFileSync(orig, "utf8");
149
+ content = content.replace(
150
+ /export class (Migration\d+)/,
151
+ `export class $1_${modId.replace(/[^a-zA-Z0-9]/g, "_")}`
152
+ );
153
+ fs.writeFileSync(newPath, content, "utf8");
154
+ if (newPath !== orig) fs.unlinkSync(orig);
155
+ results.push(formatResult(modId, `generated ${newBase}`, ""));
156
+ } catch {
157
+ results.push(formatResult(modId, `generated ${path.basename(diff.fileName)} (rename failed)`, ""));
158
+ }
159
+ } else {
160
+ results.push(formatResult(modId, "no changes", ""));
161
+ }
162
+ await orm.close(true);
163
+ }
164
+ console.log(results.join("\n"));
165
+ }
166
+ async function dbMigrate(resolver, options = {}) {
167
+ const modules = resolver.loadEnabledModules();
168
+ const ordered = sortModules(modules);
169
+ const results = [];
170
+ for (const entry of ordered) {
171
+ const modId = entry.id;
172
+ const sanitizedModId = sanitizeModuleId(modId);
173
+ const entities = await loadModuleEntities(entry, resolver);
174
+ const migrationsPath = getMigrationsPath(entry, resolver);
175
+ if (!entities.length && !fs.existsSync(migrationsPath)) continue;
176
+ fs.mkdirSync(migrationsPath, { recursive: true });
177
+ const tableName = `mikro_orm_migrations_${sanitizedModId}`;
178
+ validateTableName(tableName);
179
+ const orm = await MikroORM.init({
180
+ driver: PostgreSqlDriver,
181
+ clientUrl: getClientUrl(),
182
+ loggerFactory: () => createMinimalLogger(),
183
+ entities: entities.length ? entities : [],
184
+ discovery: { warnWhenNoEntities: false },
185
+ migrations: {
186
+ path: migrationsPath,
187
+ glob: "!(*.d).{ts,js}",
188
+ tableName,
189
+ dropTables: false
190
+ },
191
+ schemaGenerator: {
192
+ disableForeignKeys: true
193
+ },
194
+ pool: {
195
+ min: 1,
196
+ max: 3,
197
+ idleTimeoutMillis: 3e4,
198
+ acquireTimeoutMillis: 6e4,
199
+ destroyTimeoutMillis: 3e4
200
+ }
201
+ });
202
+ const migrator = orm.getMigrator();
203
+ const pending = await migrator.getPendingMigrations();
204
+ if (!pending.length) {
205
+ results.push(formatResult(modId, "no pending migrations", ""));
206
+ } else {
207
+ const renderProgress = createProgressRenderer(pending.length);
208
+ let applied = 0;
209
+ if (!QUIET_MODE) {
210
+ process.stdout.write(` ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`);
211
+ }
212
+ for (const migration of pending) {
213
+ const migrationName = typeof migration === "string" ? migration : migration.name ?? migration.fileName;
214
+ await migrator.up(migrationName ? { migrations: [migrationName] } : void 0);
215
+ applied += 1;
216
+ if (!QUIET_MODE) {
217
+ process.stdout.write(`\r ${PROGRESS_EMOJI} ${modId}: ${renderProgress(applied)}`);
218
+ }
219
+ }
220
+ if (!QUIET_MODE) process.stdout.write("\n");
221
+ results.push(
222
+ formatResult(modId, `${pending.length} migration${pending.length === 1 ? "" : "s"} applied`, "")
223
+ );
224
+ }
225
+ await orm.close(true);
226
+ }
227
+ console.log(results.join("\n"));
228
+ }
229
+ async function dbGreenfield(resolver, options) {
230
+ if (!options.yes) {
231
+ console.error("This command will DELETE all data. Use --yes to confirm.");
232
+ process.exit(1);
233
+ }
234
+ console.log("Cleaning up migrations and snapshots for greenfield setup...");
235
+ const modules = resolver.loadEnabledModules();
236
+ const ordered = sortModules(modules);
237
+ const results = [];
238
+ const outputDir = resolver.getOutputDir();
239
+ for (const entry of ordered) {
240
+ const modId = entry.id;
241
+ const migrationsPath = getMigrationsPath(entry, resolver);
242
+ if (fs.existsSync(migrationsPath)) {
243
+ const migrationFiles = fs.readdirSync(migrationsPath).filter((file) => file.endsWith(".ts") && file.startsWith("Migration"));
244
+ for (const file of migrationFiles) {
245
+ fs.unlinkSync(path.join(migrationsPath, file));
246
+ }
247
+ const snapshotFiles = fs.readdirSync(migrationsPath).filter((file) => file.endsWith(".json") && file.includes("snapshot"));
248
+ for (const file of snapshotFiles) {
249
+ fs.unlinkSync(path.join(migrationsPath, file));
250
+ }
251
+ if (migrationFiles.length > 0 || snapshotFiles.length > 0) {
252
+ results.push(
253
+ formatResult(modId, `cleaned ${migrationFiles.length} migrations, ${snapshotFiles.length} snapshots`, "")
254
+ );
255
+ } else {
256
+ results.push(formatResult(modId, "already clean", ""));
257
+ }
258
+ } else {
259
+ results.push(formatResult(modId, "no migrations directory", ""));
260
+ }
261
+ if (fs.existsSync(outputDir)) {
262
+ const files = fs.readdirSync(outputDir);
263
+ const checksumFiles = files.filter((file) => file.endsWith(".checksum"));
264
+ for (const file of checksumFiles) {
265
+ fs.unlinkSync(path.join(outputDir, file));
266
+ }
267
+ if (checksumFiles.length > 0) {
268
+ results.push(formatResult(modId, `cleaned ${checksumFiles.length} checksum files`, ""));
269
+ }
270
+ }
271
+ }
272
+ console.log(results.join("\n"));
273
+ console.log("Dropping per-module migration tables...");
274
+ try {
275
+ const { Client } = await import("pg");
276
+ const client = new Client({ connectionString: getClientUrl() });
277
+ await client.connect();
278
+ try {
279
+ await client.query("BEGIN");
280
+ for (const entry of ordered) {
281
+ const modId = entry.id;
282
+ const sanitizedModId = sanitizeModuleId(modId);
283
+ const tableName = `mikro_orm_migrations_${sanitizedModId}`;
284
+ validateTableName(tableName);
285
+ await client.query(`DROP TABLE IF EXISTS "${tableName}"`);
286
+ console.log(` ${modId}: dropped table ${tableName}`);
287
+ }
288
+ await client.query("COMMIT");
289
+ } catch (e) {
290
+ await client.query("ROLLBACK");
291
+ throw e;
292
+ } finally {
293
+ try {
294
+ await client.end();
295
+ } catch {
296
+ }
297
+ }
298
+ } catch (e) {
299
+ console.error("Failed to drop migration tables:", e?.message || e);
300
+ throw e;
301
+ }
302
+ console.log("Dropping ALL public tables for true greenfield...");
303
+ try {
304
+ const { Client } = await import("pg");
305
+ const client = new Client({ connectionString: getClientUrl() });
306
+ await client.connect();
307
+ try {
308
+ const res = await client.query(`SELECT tablename FROM pg_tables WHERE schemaname = 'public'`);
309
+ const tables = (res.rows || []).map((r) => String(r.tablename));
310
+ if (tables.length) {
311
+ await client.query("BEGIN");
312
+ try {
313
+ await client.query("SET session_replication_role = 'replica'");
314
+ for (const t of tables) {
315
+ await client.query(`DROP TABLE IF EXISTS "${t}" CASCADE`);
316
+ }
317
+ await client.query("SET session_replication_role = 'origin'");
318
+ await client.query("COMMIT");
319
+ console.log(` Dropped ${tables.length} tables.`);
320
+ } catch (e) {
321
+ await client.query("ROLLBACK");
322
+ throw e;
323
+ }
324
+ } else {
325
+ console.log(" No tables found to drop.");
326
+ }
327
+ } finally {
328
+ try {
329
+ await client.end();
330
+ } catch {
331
+ }
332
+ }
333
+ } catch (e) {
334
+ console.error("Failed to drop public tables:", e?.message || e);
335
+ throw e;
336
+ }
337
+ console.log("Generating fresh migrations for all modules...");
338
+ await dbGenerate(resolver);
339
+ console.log("Applying migrations...");
340
+ await dbMigrate(resolver);
341
+ console.log("Greenfield reset complete! Fresh migrations generated and applied.");
342
+ }
343
+ export {
344
+ dbGenerate,
345
+ dbGreenfield,
346
+ dbMigrate,
347
+ sanitizeModuleId,
348
+ validateTableName
349
+ };
350
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/db/commands.ts"],
4
+ "sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\nimport { MikroORM, type Logger } from '@mikro-orm/core'\nimport { Migrator } from '@mikro-orm/migrations'\nimport { PostgreSqlDriver } from '@mikro-orm/postgresql'\nimport type { PackageResolver, ModuleEntry } from '../resolver'\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 * 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\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 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 // For @app modules, use file:// URL since @/ alias doesn't work in Node.js runtime\n const importPath = (isAppModule && fromApp)\n ? `file://${p.replace(/\\.ts$/, '.js')}`\n : `${fromApp ? imps.appBase : imps.pkgBase}/${sub}/${f.replace(/\\.ts$/, '')}`\n try {\n const mod = 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 with TypeScript files, they can't be directly imported\n // Skip and let MikroORM handle entities through discovery\n if (isAppModule) continue\n throw err\n }\n }\n }\n }\n return []\n}\n\nfunction getMigrationsPath(entry: ModuleEntry, resolver: PackageResolver): string {\n const from = entry.from || '@open-mercato/core'\n let pkgModRoot: string\n\n if (from === '@open-mercato/core') {\n pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)\n } else if (/^@open-mercato\\//.test(from)) {\n const segs = from.split('/')\n if (segs.length > 1 && segs[1]) {\n pkgModRoot = path.join(resolver.getRootDir(), `packages/${segs[1]}/src/modules`, entry.id)\n } else {\n pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)\n }\n } else if (from === '@app') {\n // For @app modules, use the app directory not the monorepo root\n pkgModRoot = path.join(resolver.getAppDir(), 'src/modules', entry.id)\n } else {\n pkgModRoot = path.join(resolver.getRootDir(), 'packages/core/src/modules', entry.id)\n }\n\n return path.join(pkgModRoot, 'migrations')\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 for (const entry of ordered) {\n const modId = entry.id\n const sanitizedModId = sanitizeModuleId(modId)\n const entities = await loadModuleEntities(entry, resolver)\n if (!entities.length) continue\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\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n entities,\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n acquireTimeoutMillis: 60000,\n destroyTimeoutMillis: 30000,\n },\n })\n\n const migrator = orm.getMigrator() as Migrator\n const diff = await migrator.createMigration()\n if (diff && diff.fileName) {\n try {\n const orig = diff.fileName\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 const newBase = stem.endsWith(suffix) ? base : `${stem}${suffix}${ext}`\n const newPath = path.join(dir, newBase)\n let content = fs.readFileSync(orig, 'utf8')\n // Rename class to ensure uniqueness as well\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 results.push(formatResult(modId, `generated ${newBase}`, ''))\n } catch {\n results.push(formatResult(modId, `generated ${path.basename(diff.fileName)} (rename failed)`, ''))\n }\n } else {\n results.push(formatResult(modId, 'no changes', ''))\n }\n\n await orm.close(true)\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 // For @app modules, entities may be empty since TypeScript files can't be imported at runtime\n // Use discovery.warnWhenNoEntities: false to allow running migrations without entities\n const orm = await MikroORM.init<PostgreSqlDriver>({\n driver: PostgreSqlDriver,\n clientUrl: getClientUrl(),\n loggerFactory: () => createMinimalLogger(),\n entities: entities.length ? entities : [],\n discovery: { warnWhenNoEntities: false },\n migrations: {\n path: migrationsPath,\n glob: '!(*.d).{ts,js}',\n tableName,\n dropTables: false,\n },\n schemaGenerator: {\n disableForeignKeys: true,\n },\n pool: {\n min: 1,\n max: 3,\n idleTimeoutMillis: 30000,\n acquireTimeoutMillis: 60000,\n destroyTimeoutMillis: 30000,\n },\n })\n\n const migrator = orm.getMigrator() as Migrator\n const pending = await migrator.getPendingMigrations()\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() })\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() })\n await client.connect()\n try {\n const res = await client.query(`SELECT tablename FROM pg_tables WHERE schemaname = 'public'`)\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 \"${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
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ import { dbGenerate, dbMigrate, dbGreenfield } from "./commands.js";
2
+ export {
3
+ dbGenerate,
4
+ dbGreenfield,
5
+ dbMigrate
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/db/index.ts"],
4
+ "sourcesContent": ["export { dbGenerate, dbMigrate, dbGreenfield, type DbOptions, type GreenfieldOptions } from './commands'\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,WAAW,oBAA4D;",
6
+ "names": []
7
+ }