@lssm/app.cli-database 1.41.1 → 1.42.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Chaman Ventures, SASU
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # @lssm/app.cli-database
2
2
 
3
+ Website: https://contractspec.lssm.tech/
4
+
5
+
3
6
  Prisma wrapper and CLI tools for managing database schemas, migrations, and seeding within the LSSM monorepo.
4
7
 
5
8
  ## Purpose
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.mjs CHANGED
@@ -78,4 +78,5 @@ main().catch((err) => {
78
78
  });
79
79
 
80
80
  //#endregion
81
- export { };
81
+ export { };
82
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport mri from 'minimist';\nimport { runImport } from './commands/import.js';\nimport { runCheck } from './commands/check.js';\nimport { runGenerate } from './commands/generate.js';\nimport { runMigrate } from './commands/migrate.js';\nimport { runSeed } from './commands/seed.js';\nimport { runSchemaGenerate } from './commands/schema-generate.js';\nimport { runSchemaCompose } from './commands/schema-compose.js';\n\nasync function main() {\n const argv = mri(process.argv.slice(2));\n const [cmd] = argv._ as string[];\n\n switch (cmd) {\n case 'import':\n await runImport(argv);\n break;\n case 'check':\n await runCheck(argv);\n break;\n case 'generate':\n await runGenerate(argv);\n break;\n case 'migrate:dev':\n case 'migrate:deploy':\n case 'migrate:status':\n await runMigrate(cmd, argv);\n break;\n case 'seed':\n await runSeed(argv);\n break;\n case 'schema:generate':\n await runSchemaGenerate(argv);\n break;\n case 'schema:compose':\n await runSchemaCompose(argv);\n break;\n default:\n printUsage();\n process.exit(1);\n }\n}\n\nfunction printUsage() {\n console.log(`\nUsage: database <command> [options]\n\nCommands:\n import Import schema from external sources\n check Check Prisma schema validity\n generate Generate Prisma client\n migrate:dev Run migrations in development\n migrate:deploy Deploy migrations to production\n migrate:status Check migration status\n seed Seed the database\n\nSchema Generation (spec-first):\n schema:generate Generate Prisma schema from entity specs\n --config <path> Schema config file (default: ./schema.config.ts)\n --output <path> Output path (default: ./prisma/schema/generated.prisma)\n --module <id> Generate only a specific module\n\n schema:compose Compose multiple module schemas\n --config <path> Schema config file (default: ./schema.config.ts)\n --output <path> Output path (default: ./prisma/schema/composed.prisma)\n --modules <list> Comma-separated module IDs to include\n\nExamples:\n database schema:generate --config ./schema.config.ts\n database schema:compose --modules \"@lssm/lib.identity-rbac,@lssm/module.audit-trail\"\n database generate\n database migrate:dev --name add_users_table\n`);\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;AAUA,eAAe,OAAO;CACpB,MAAM,OAAO,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;CACvC,MAAM,CAAC,OAAO,KAAK;AAEnB,SAAQ,KAAR;EACE,KAAK;AACH,SAAM,UAAU,KAAK;AACrB;EACF,KAAK;AACH,SAAM,SAAS,KAAK;AACpB;EACF,KAAK;AACH,SAAM,YAAY,KAAK;AACvB;EACF,KAAK;EACL,KAAK;EACL,KAAK;AACH,SAAM,WAAW,KAAK,KAAK;AAC3B;EACF,KAAK;AACH,SAAM,QAAQ,KAAK;AACnB;EACF,KAAK;AACH,SAAM,kBAAkB,KAAK;AAC7B;EACF,KAAK;AACH,SAAM,iBAAiB,KAAK;AAC5B;EACF;AACE,eAAY;AACZ,WAAQ,KAAK,EAAE;;;AAIrB,SAAS,aAAa;AACpB,SAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BZ;;AAGF,MAAM,CAAC,OAAO,QAAQ;AACpB,SAAQ,MAAM,IAAI;AAClB,SAAQ,KAAK,EAAE;EACf"}
@@ -31,4 +31,5 @@ async function runCheck(argv) {
31
31
  }
32
32
 
33
33
  //#endregion
34
- export { runCheck };
34
+ export { runCheck };
35
+ //# sourceMappingURL=check.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.mjs","names":[],"sources":["../../src/commands/check.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { type ImportLock } from '../lib/types.js';\n\nfunction sha256(content: string) {\n return crypto.createHash('sha256').update(content).digest('hex');\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function runCheck(argv: any) {\n const target = (argv.target as string) || process.cwd();\n const lockPath = path.join(\n target,\n 'prisma',\n 'schema',\n 'imported',\n 'imported.lock.json'\n );\n if (!fs.existsSync(lockPath)) {\n console.error('No imported.lock.json found. Run: database import');\n process.exit(1);\n }\n const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8')) as ImportLock;\n let ok = true;\n for (const e of lock.entries) {\n if (!fs.existsSync(e.sourcePath)) {\n console.error(`Missing source: ${e.sourcePath}`);\n ok = false;\n continue;\n }\n const raw = fs.readFileSync(e.sourcePath, 'utf8');\n const digest = sha256(raw);\n if (digest !== e.sha256) {\n console.error(`Drift detected for ${e.moduleName} (${e.sourcePath})`);\n ok = false;\n }\n }\n if (!ok) {\n process.exit(2);\n }\n console.log('Imported schemas are in sync with lock.');\n}\n"],"mappings":";;;;;AAKA,SAAS,OAAO,SAAiB;AAC/B,QAAO,OAAO,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM;;AAIlE,eAAsB,SAAS,MAAW;CACxC,MAAM,SAAU,KAAK,UAAqB,QAAQ,KAAK;CACvD,MAAM,WAAW,KAAK,KACpB,QACA,UACA,UACA,YACA,qBACD;AACD,KAAI,CAAC,GAAG,WAAW,SAAS,EAAE;AAC5B,UAAQ,MAAM,oDAAoD;AAClE,UAAQ,KAAK,EAAE;;CAEjB,MAAM,OAAO,KAAK,MAAM,GAAG,aAAa,UAAU,OAAO,CAAC;CAC1D,IAAI,KAAK;AACT,MAAK,MAAM,KAAK,KAAK,SAAS;AAC5B,MAAI,CAAC,GAAG,WAAW,EAAE,WAAW,EAAE;AAChC,WAAQ,MAAM,mBAAmB,EAAE,aAAa;AAChD,QAAK;AACL;;AAIF,MADe,OADH,GAAG,aAAa,EAAE,YAAY,OAAO,CACvB,KACX,EAAE,QAAQ;AACvB,WAAQ,MAAM,sBAAsB,EAAE,WAAW,IAAI,EAAE,WAAW,GAAG;AACrE,QAAK;;;AAGT,KAAI,CAAC,GACH,SAAQ,KAAK,EAAE;AAEjB,SAAQ,IAAI,0CAA0C"}
@@ -1,9 +1,10 @@
1
1
  import { execa } from "execa";
2
2
 
3
3
  //#region src/commands/generate.ts
4
- async function runGenerate(argv) {
4
+ async function runGenerate(_argv) {
5
5
  await execa("prisma", ["generate"], { stdio: "inherit" });
6
6
  }
7
7
 
8
8
  //#endregion
9
- export { runGenerate };
9
+ export { runGenerate };
10
+ //# sourceMappingURL=generate.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.mjs","names":[],"sources":["../../src/commands/generate.ts"],"sourcesContent":["import { execa } from 'execa';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function runGenerate(_argv: any) {\n await execa('prisma', ['generate'], { stdio: 'inherit' });\n}\n"],"mappings":";;;AAGA,eAAsB,YAAY,OAAY;AAC5C,OAAM,MAAM,UAAU,CAAC,WAAW,EAAE,EAAE,OAAO,WAAW,CAAC"}
@@ -33,7 +33,7 @@ async function runImport(argv) {
33
33
  if (Array.isArray(match) && typeof match[1] === "string") {
34
34
  const arr = match[1] || "";
35
35
  const mods = [];
36
- const re = /['\"]([^'\"]+)['\"]/g;
36
+ const re = /['"]([^'"]+)['"]/g;
37
37
  let m;
38
38
  while (m = re.exec(arr)) {
39
39
  const val = m[1] ?? "";
@@ -92,4 +92,5 @@ async function runImport(argv) {
92
92
  }
93
93
 
94
94
  //#endregion
95
- export { runImport };
95
+ export { runImport };
96
+ //# sourceMappingURL=import.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.mjs","names":["arr: string","mods: string[]","m: RegExpExecArray | null","modules: string[]","entries: ImportLockEntry[]","lock: ImportLock"],"sources":["../../src/commands/import.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { pathToFileURL } from 'node:url';\nimport { type ImportLock, type ImportLockEntry } from '../lib/types.js';\n\nfunction sha256(content: string) {\n return crypto.createHash('sha256').update(content).digest('hex');\n}\n\nfunction stripDatasourceAndGenerators(schema: string): string {\n // naive strip: remove blocks beginning with 'datasource ' or 'generator '\n return schema\n .replace(/datasource\\s+\\w+\\s*\\{[\\s\\S]*?\\}/g, '')\n .replace(/generator\\s+\\w+\\s*\\{[\\s\\S]*?\\}/g, '')\n .trim();\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function runImport(argv: any) {\n const target = (argv.target as string) || process.cwd();\n const modulesArg = (argv.modules as string) || '';\n async function loadModulesFromMergerConfig(): Promise<string[] | null> {\n const candidates = [\n path.join(target, 'prisma-merger.config.ts'),\n path.join(target, 'prisma-merger.config.mts'),\n path.join(target, 'prisma-merger.config.js'),\n path.join(target, 'prisma-merger.config.mjs'),\n path.join(target, 'prisma-merger.config.cjs'),\n path.join(target, 'prisma-merger.config.json'),\n ];\n for (const file of candidates) {\n if (!fs.existsSync(file)) continue;\n if (file.endsWith('.json')) {\n const json = JSON.parse(fs.readFileSync(file, 'utf8')) as {\n modules?: string[];\n };\n if (Array.isArray(json.modules) && json.modules.length > 0)\n return json.modules;\n } else if (file.endsWith('.ts') || file.endsWith('.mts')) {\n // Parse TS config without executing it\n const raw = fs.readFileSync(file, 'utf8');\n const match = raw.match(/modules\\s*:\\s*\\[([\\s\\S]*?)\\]/m);\n if (Array.isArray(match) && typeof match[1] === 'string') {\n const arr: string = match[1] || '';\n const mods: string[] = [];\n const re = /['\"]([^'\"]+)['\"]/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(arr))) {\n const val = m[1] ?? '';\n if (val) mods.push(val);\n }\n if (mods.length > 0) return mods;\n }\n } else {\n const mod = await import(pathToFileURL(file).href);\n const cfg = mod.default || mod;\n if (Array.isArray(cfg.modules) && cfg.modules.length > 0)\n return cfg.modules as string[];\n }\n }\n return null;\n }\n\n let modules: string[] = modulesArg\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n if (modules.length === 0) {\n const fromCfg = await loadModulesFromMergerConfig();\n if (fromCfg) modules = fromCfg;\n }\n if (modules.length === 0) {\n console.error(\n 'No modules specified. Provide --modules or define prisma-merger.config.ts { modules: [...] }'\n );\n process.exit(1);\n }\n\n const importedDir = path.join(target, 'prisma', 'schema', 'imported');\n fs.mkdirSync(importedDir, { recursive: true });\n\n const entries: ImportLockEntry[] = [];\n\n for (const mod of modules) {\n const pkgPath = require.resolve(path.join(mod, 'package.json'));\n const modRoot = path.dirname(pkgPath);\n const schemaPath = path.join(modRoot, 'prisma', 'schema.prisma');\n if (!fs.existsSync(schemaPath)) {\n console.error(`Module ${mod} missing prisma/schema.prisma`);\n process.exit(1);\n }\n const raw = fs.readFileSync(schemaPath, 'utf8');\n const stripped = stripDatasourceAndGenerators(raw);\n const outDir = path.join(\n importedDir,\n path.basename(mod).replace(/^@/, '').replace(/\\//g, '_')\n );\n fs.mkdirSync(outDir, { recursive: true });\n const outFile = path.join(outDir, 'models.prisma');\n fs.writeFileSync(outFile, stripped, 'utf8');\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n entries.push({\n moduleName: mod,\n version: pkg.version || '0.0.0',\n sourcePath: schemaPath,\n sha256: sha256(raw),\n });\n }\n\n const lock: ImportLock = { updatedAt: new Date().toISOString(), entries };\n fs.writeFileSync(\n path.join(importedDir, 'imported.lock.json'),\n JSON.stringify(lock, null, 2)\n );\n console.log(`Imported ${entries.length} modules into ${importedDir}`);\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { execa } from "execa";
2
2
 
3
3
  //#region src/commands/migrate.ts
4
- async function runMigrate(cmd, argv) {
4
+ async function runMigrate(cmd, _argv) {
5
5
  if (cmd === "migrate:dev") {
6
6
  await execa("prisma", ["migrate", "dev"], { stdio: "inherit" });
7
7
  return;
@@ -17,4 +17,5 @@ async function runMigrate(cmd, argv) {
17
17
  }
18
18
 
19
19
  //#endregion
20
- export { runMigrate };
20
+ export { runMigrate };
21
+ //# sourceMappingURL=migrate.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.mjs","names":[],"sources":["../../src/commands/migrate.ts"],"sourcesContent":["import { execa } from 'execa';\n\nexport async function runMigrate(cmd: string, _argv: unknown) {\n if (cmd === 'migrate:dev') {\n await execa('prisma', ['migrate', 'dev'], { stdio: 'inherit' });\n return;\n }\n if (cmd === 'migrate:deploy') {\n await execa('prisma', ['migrate', 'deploy'], { stdio: 'inherit' });\n return;\n }\n if (cmd === 'migrate:status') {\n await execa('prisma', ['migrate', 'status'], { stdio: 'inherit' });\n return;\n }\n}\n"],"mappings":";;;AAEA,eAAsB,WAAW,KAAa,OAAgB;AAC5D,KAAI,QAAQ,eAAe;AACzB,QAAM,MAAM,UAAU,CAAC,WAAW,MAAM,EAAE,EAAE,OAAO,WAAW,CAAC;AAC/D;;AAEF,KAAI,QAAQ,kBAAkB;AAC5B,QAAM,MAAM,UAAU,CAAC,WAAW,SAAS,EAAE,EAAE,OAAO,WAAW,CAAC;AAClE;;AAEF,KAAI,QAAQ,kBAAkB;AAC5B,QAAM,MAAM,UAAU,CAAC,WAAW,SAAS,EAAE,EAAE,OAAO,WAAW,CAAC;AAClE"}
@@ -73,4 +73,5 @@ async function runSchemaCompose(argv) {
73
73
  }
74
74
 
75
75
  //#endregion
76
- export { runSchemaCompose };
76
+ export { runSchemaCompose };
77
+ //# sourceMappingURL=schema-compose.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-compose.mjs","names":["config: SchemaConfig | null"],"sources":["../../src/commands/schema-compose.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { loadSchemaConfig, type SchemaConfig } from '../lib/schema-config.js';\n\nexport interface SchemaComposeArgs {\n config?: string;\n output?: string;\n modules?: string;\n}\n\n/**\n * Compose multiple module schemas into a single Prisma schema.\n *\n * Usage:\n * database schema:compose --config ./schema.config.ts\n * database schema:compose --modules \"@lssm/lib.identity-rbac,@lssm/module.audit-trail\"\n */\nexport async function runSchemaCompose(argv: SchemaComposeArgs) {\n console.log('🔗 Composing module schemas...\\n');\n\n const configPath = argv.config ?? './schema.config.ts';\n const config: SchemaConfig | null = await loadSchemaConfig(configPath);\n\n if (!config) {\n console.error(`❌ Could not load schema config from ${configPath}`);\n process.exit(1);\n }\n\n // Filter modules if specified via CLI\n let modules = config.modules;\n if (argv.modules) {\n const moduleIds = argv.modules.split(',').map((m) => m.trim());\n modules = config.modules.filter((m) => moduleIds.includes(m.moduleId));\n }\n\n if (modules.length === 0) {\n console.error('❌ No modules found to compose');\n process.exit(1);\n }\n\n console.log(`📦 Composing ${modules.length} module(s):`);\n modules.forEach((m) => {\n console.log(` - ${m.moduleId}`);\n m.entities.forEach((e) => {\n console.log(` • ${e.name} (${Object.keys(e.fields).length} fields)`);\n });\n });\n console.log('');\n\n // Collect all enums\n const allEnums = new Set<string>();\n modules.forEach((m) => {\n m.enums?.forEach((e) => allEnums.add(e.name));\n m.entities.forEach((entity) => {\n entity.enums?.forEach((e) => allEnums.add(e.name));\n });\n });\n\n if (allEnums.size > 0) {\n console.log(`📋 Enums discovered: ${Array.from(allEnums).join(', ')}`);\n console.log('');\n }\n\n // Dynamically import the generator\n const { composeModuleSchemas } = await import('@lssm/lib.schema');\n\n // Generate the combined schema\n const prismaSchema = composeModuleSchemas(modules, {\n provider: config.provider ?? 'postgresql',\n clientOutput: config.clientOutput,\n includePothos: config.includePothos ?? true,\n pothosOutput: config.pothosOutput,\n });\n\n // Determine output path\n const outputPath =\n argv.output ?? config.outputPath ?? './prisma/schema/composed.prisma';\n const outputDir = path.dirname(outputPath);\n\n // Ensure output directory exists\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write the composed schema\n fs.writeFileSync(outputPath, prismaSchema, 'utf-8');\n\n // Generate summary\n const entityCount = modules.reduce((acc, m) => acc + m.entities.length, 0);\n const fieldCount = modules.reduce(\n (acc, m) =>\n acc +\n m.entities.reduce((eAcc, e) => eAcc + Object.keys(e.fields).length, 0),\n 0\n );\n\n console.log('✅ Schema composition complete!');\n console.log('');\n console.log(` 📄 Output: ${outputPath}`);\n console.log(` 📦 Modules: ${modules.length}`);\n console.log(` 🏗️ Entities: ${entityCount}`);\n console.log(` 📝 Fields: ${fieldCount}`);\n console.log(` 📋 Enums: ${allEnums.size}`);\n console.log('');\n console.log('Next steps:');\n console.log(' 1. Run: database generate');\n console.log(' 2. Run: database migrate:dev --name <migration-name>');\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,eAAsB,iBAAiB,MAAyB;AAC9D,SAAQ,IAAI,mCAAmC;CAE/C,MAAM,aAAa,KAAK,UAAU;CAClC,MAAMA,SAA8B,MAAM,iBAAiB,WAAW;AAEtE,KAAI,CAAC,QAAQ;AACX,UAAQ,MAAM,uCAAuC,aAAa;AAClE,UAAQ,KAAK,EAAE;;CAIjB,IAAI,UAAU,OAAO;AACrB,KAAI,KAAK,SAAS;EAChB,MAAM,YAAY,KAAK,QAAQ,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC;AAC9D,YAAU,OAAO,QAAQ,QAAQ,MAAM,UAAU,SAAS,EAAE,SAAS,CAAC;;AAGxE,KAAI,QAAQ,WAAW,GAAG;AACxB,UAAQ,MAAM,gCAAgC;AAC9C,UAAQ,KAAK,EAAE;;AAGjB,SAAQ,IAAI,gBAAgB,QAAQ,OAAO,aAAa;AACxD,SAAQ,SAAS,MAAM;AACrB,UAAQ,IAAI,QAAQ,EAAE,WAAW;AACjC,IAAE,SAAS,SAAS,MAAM;AACxB,WAAQ,IAAI,UAAU,EAAE,KAAK,IAAI,OAAO,KAAK,EAAE,OAAO,CAAC,OAAO,UAAU;IACxE;GACF;AACF,SAAQ,IAAI,GAAG;CAGf,MAAM,2BAAW,IAAI,KAAa;AAClC,SAAQ,SAAS,MAAM;AACrB,IAAE,OAAO,SAAS,MAAM,SAAS,IAAI,EAAE,KAAK,CAAC;AAC7C,IAAE,SAAS,SAAS,WAAW;AAC7B,UAAO,OAAO,SAAS,MAAM,SAAS,IAAI,EAAE,KAAK,CAAC;IAClD;GACF;AAEF,KAAI,SAAS,OAAO,GAAG;AACrB,UAAQ,IAAI,wBAAwB,MAAM,KAAK,SAAS,CAAC,KAAK,KAAK,GAAG;AACtE,UAAQ,IAAI,GAAG;;CAIjB,MAAM,EAAE,yBAAyB,MAAM,OAAO;CAG9C,MAAM,eAAe,qBAAqB,SAAS;EACjD,UAAU,OAAO,YAAY;EAC7B,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB;EACvC,cAAc,OAAO;EACtB,CAAC;CAGF,MAAM,aACJ,KAAK,UAAU,OAAO,cAAc;CACtC,MAAM,YAAY,KAAK,QAAQ,WAAW;AAG1C,KAAI,CAAC,GAAG,WAAW,UAAU,CAC3B,IAAG,UAAU,WAAW,EAAE,WAAW,MAAM,CAAC;AAI9C,IAAG,cAAc,YAAY,cAAc,QAAQ;CAGnD,MAAM,cAAc,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,SAAS,QAAQ,EAAE;CAC1E,MAAM,aAAa,QAAQ,QACxB,KAAK,MACJ,MACA,EAAE,SAAS,QAAQ,MAAM,MAAM,OAAO,OAAO,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,EACxE,EACD;AAED,SAAQ,IAAI,iCAAiC;AAC7C,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,iBAAiB,aAAa;AAC1C,SAAQ,IAAI,kBAAkB,QAAQ,SAAS;AAC/C,SAAQ,IAAI,qBAAqB,cAAc;AAC/C,SAAQ,IAAI,iBAAiB,aAAa;AAC1C,SAAQ,IAAI,gBAAgB,SAAS,OAAO;AAC5C,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;AAC1B,SAAQ,IAAI,8BAA8B;AAC1C,SAAQ,IAAI,yDAAyD"}
@@ -48,4 +48,5 @@ async function runSchemaGenerate(argv) {
48
48
  }
49
49
 
50
50
  //#endregion
51
- export { runSchemaGenerate };
51
+ export { runSchemaGenerate };
52
+ //# sourceMappingURL=schema-generate.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-generate.mjs","names":["config: SchemaConfig | null"],"sources":["../../src/commands/schema-generate.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { loadSchemaConfig, type SchemaConfig } from '../lib/schema-config.js';\n\nexport interface SchemaGenerateArgs {\n config?: string;\n output?: string;\n module?: string;\n}\n\n/**\n * Generate Prisma schema from ContractSpec entity definitions.\n *\n * Usage:\n * database schema:generate --config ./schema.config.ts --output ./prisma/schema\n * database schema:generate --module @lssm/lib.identity-rbac\n */\nexport async function runSchemaGenerate(argv: SchemaGenerateArgs) {\n console.log('📝 Generating Prisma schema from entity specs...\\n');\n\n const configPath = argv.config ?? './schema.config.ts';\n const config: SchemaConfig | null = await loadSchemaConfig(configPath);\n\n if (!config) {\n console.error(`❌ Could not load schema config from ${configPath}`);\n process.exit(1);\n }\n\n // Filter modules if specified\n const modules = argv.module\n ? config.modules.filter((m) => m.moduleId === argv.module)\n : config.modules;\n\n if (modules.length === 0) {\n console.error('❌ No modules found to generate');\n process.exit(1);\n }\n\n console.log(`📦 Processing ${modules.length} module(s):`);\n modules.forEach((m) => {\n console.log(` - ${m.moduleId} (${m.entities.length} entities)`);\n });\n console.log('');\n\n // Dynamically import the generator\n const { composeModuleSchemas } = await import('@lssm/lib.schema');\n\n // Generate the combined schema\n const prismaSchema = composeModuleSchemas(modules, {\n provider: config.provider ?? 'postgresql',\n clientOutput: config.clientOutput,\n includePothos: config.includePothos ?? true,\n pothosOutput: config.pothosOutput,\n });\n\n // Determine output path\n const outputPath =\n argv.output ?? config.outputPath ?? './prisma/schema/generated.prisma';\n const outputDir = path.dirname(outputPath);\n\n // Ensure output directory exists\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write the generated schema\n fs.writeFileSync(outputPath, prismaSchema, 'utf-8');\n\n console.log(`✅ Generated Prisma schema: ${outputPath}`);\n console.log('');\n console.log('Next steps:');\n console.log(' 1. Review the generated schema');\n console.log(' 2. Run: database generate');\n console.log(' 3. Run: database migrate:dev');\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,eAAsB,kBAAkB,MAA0B;AAChE,SAAQ,IAAI,qDAAqD;CAEjE,MAAM,aAAa,KAAK,UAAU;CAClC,MAAMA,SAA8B,MAAM,iBAAiB,WAAW;AAEtE,KAAI,CAAC,QAAQ;AACX,UAAQ,MAAM,uCAAuC,aAAa;AAClE,UAAQ,KAAK,EAAE;;CAIjB,MAAM,UAAU,KAAK,SACjB,OAAO,QAAQ,QAAQ,MAAM,EAAE,aAAa,KAAK,OAAO,GACxD,OAAO;AAEX,KAAI,QAAQ,WAAW,GAAG;AACxB,UAAQ,MAAM,iCAAiC;AAC/C,UAAQ,KAAK,EAAE;;AAGjB,SAAQ,IAAI,iBAAiB,QAAQ,OAAO,aAAa;AACzD,SAAQ,SAAS,MAAM;AACrB,UAAQ,IAAI,QAAQ,EAAE,SAAS,IAAI,EAAE,SAAS,OAAO,YAAY;GACjE;AACF,SAAQ,IAAI,GAAG;CAGf,MAAM,EAAE,yBAAyB,MAAM,OAAO;CAG9C,MAAM,eAAe,qBAAqB,SAAS;EACjD,UAAU,OAAO,YAAY;EAC7B,cAAc,OAAO;EACrB,eAAe,OAAO,iBAAiB;EACvC,cAAc,OAAO;EACtB,CAAC;CAGF,MAAM,aACJ,KAAK,UAAU,OAAO,cAAc;CACtC,MAAM,YAAY,KAAK,QAAQ,WAAW;AAG1C,KAAI,CAAC,GAAG,WAAW,UAAU,CAC3B,IAAG,UAAU,WAAW,EAAE,WAAW,MAAM,CAAC;AAI9C,IAAG,cAAc,YAAY,cAAc,QAAQ;AAEnD,SAAQ,IAAI,8BAA8B,aAAa;AACvD,SAAQ,IAAI,GAAG;AACf,SAAQ,IAAI,cAAc;AAC1B,SAAQ,IAAI,mCAAmC;AAC/C,SAAQ,IAAI,8BAA8B;AAC1C,SAAQ,IAAI,iCAAiC"}
@@ -1,7 +1,7 @@
1
1
  import { execa } from "execa";
2
2
 
3
3
  //#region src/commands/seed.ts
4
- async function runSeed(argv) {
4
+ async function runSeed(_argv) {
5
5
  try {
6
6
  await execa("prisma", ["db", "seed"], { stdio: "inherit" });
7
7
  } catch (e) {
@@ -11,4 +11,5 @@ async function runSeed(argv) {
11
11
  }
12
12
 
13
13
  //#endregion
14
- export { runSeed };
14
+ export { runSeed };
15
+ //# sourceMappingURL=seed.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.mjs","names":[],"sources":["../../src/commands/seed.ts"],"sourcesContent":["import { execa } from 'execa';\n\nexport async function runSeed(_argv: unknown) {\n // Delegate to prisma db seed if configured, else no-op\n try {\n await execa('prisma', ['db', 'seed'], { stdio: 'inherit' });\n } catch (e) {\n console.warn('No prisma seed configured or seed failed.');\n throw e;\n }\n}\n"],"mappings":";;;AAEA,eAAsB,QAAQ,OAAgB;AAE5C,KAAI;AACF,QAAM,MAAM,UAAU,CAAC,MAAM,OAAO,EAAE,EAAE,OAAO,WAAW,CAAC;UACpD,GAAG;AACV,UAAQ,KAAK,4CAA4C;AACzD,QAAM"}
@@ -0,0 +1,4 @@
1
+ import { ImportLock, ImportLockEntry } from "./lib/types.mjs";
2
+ import { MergedPrismaConfig, defineMergedPrismaConfig } from "./lib/config.mjs";
3
+ import { ModuleSchemaContribution, SchemaConfig, defineSchemaConfig, loadSchemaConfig } from "./lib/schema-config.mjs";
4
+ export { ImportLock, ImportLockEntry, MergedPrismaConfig, ModuleSchemaContribution, SchemaConfig, defineMergedPrismaConfig, defineSchemaConfig, loadSchemaConfig };
@@ -0,0 +1,8 @@
1
+ //#region src/lib/config.d.ts
2
+ interface MergedPrismaConfig {
3
+ modules: string[];
4
+ }
5
+ declare function defineMergedPrismaConfig(config: MergedPrismaConfig): MergedPrismaConfig;
6
+ //#endregion
7
+ export { MergedPrismaConfig, defineMergedPrismaConfig };
8
+ //# sourceMappingURL=config.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.mts","names":[],"sources":["../../src/lib/config.ts"],"sourcesContent":[],"mappings":";UAAiB,kBAAA;EAAA,OAAA,EAAA,MAAA,EAAA;AAIjB;iBAAgB,wBAAA,SACN,qBACP"}
@@ -4,4 +4,5 @@ function defineMergedPrismaConfig(config) {
4
4
  }
5
5
 
6
6
  //#endregion
7
- export { defineMergedPrismaConfig };
7
+ export { defineMergedPrismaConfig };
8
+ //# sourceMappingURL=config.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.mjs","names":[],"sources":["../../src/lib/config.ts"],"sourcesContent":["export interface MergedPrismaConfig {\n modules: string[];\n}\n\nexport function defineMergedPrismaConfig(\n config: MergedPrismaConfig\n): MergedPrismaConfig {\n return config;\n}\n"],"mappings":";AAIA,SAAgB,yBACd,QACoB;AACpB,QAAO"}
@@ -0,0 +1,32 @@
1
+ import { ModuleSchemaContribution } from "@lssm/lib.schema";
2
+
3
+ //#region src/lib/schema-config.d.ts
4
+
5
+ /**
6
+ * Configuration for schema generation and composition.
7
+ */
8
+ interface SchemaConfig {
9
+ /** Module schema contributions to include */
10
+ modules: ModuleSchemaContribution[];
11
+ /** Prisma datasource provider (default: 'postgresql') */
12
+ provider?: 'postgresql' | 'mysql' | 'sqlite' | 'mongodb' | 'sqlserver';
13
+ /** Output path for generated Prisma schema */
14
+ outputPath?: string;
15
+ /** Prisma client output directory */
16
+ clientOutput?: string;
17
+ /** Include Pothos generator (default: true) */
18
+ includePothos?: boolean;
19
+ /** Pothos output path */
20
+ pothosOutput?: string;
21
+ }
22
+ /**
23
+ * Define a schema configuration.
24
+ */
25
+ declare function defineSchemaConfig(config: SchemaConfig): SchemaConfig;
26
+ /**
27
+ * Load schema configuration from a file.
28
+ */
29
+ declare function loadSchemaConfig(configPath: string): Promise<SchemaConfig | null>;
30
+ //#endregion
31
+ export { type ModuleSchemaContribution, SchemaConfig, defineSchemaConfig, loadSchemaConfig };
32
+ //# sourceMappingURL=schema-config.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-config.d.mts","names":[],"sources":["../../src/lib/schema-config.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAkBgB,UAlBC,YAAA,CAkBiB;EAOZ;WAvBX;;;;;;;;;;;;;;;iBAgBK,kBAAA,SAA2B,eAAe;;;;iBAOpC,gBAAA,sBAEnB,QAAQ"}
@@ -19,4 +19,5 @@ async function loadSchemaConfig(configPath) {
19
19
  }
20
20
 
21
21
  //#endregion
22
- export { defineSchemaConfig, loadSchemaConfig };
22
+ export { defineSchemaConfig, loadSchemaConfig };
23
+ //# sourceMappingURL=schema-config.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-config.mjs","names":[],"sources":["../../src/lib/schema-config.ts"],"sourcesContent":["import type { ModuleSchemaContribution } from '@lssm/lib.schema';\n\n/**\n * Configuration for schema generation and composition.\n */\nexport interface SchemaConfig {\n /** Module schema contributions to include */\n modules: ModuleSchemaContribution[];\n /** Prisma datasource provider (default: 'postgresql') */\n provider?: 'postgresql' | 'mysql' | 'sqlite' | 'mongodb' | 'sqlserver';\n /** Output path for generated Prisma schema */\n outputPath?: string;\n /** Prisma client output directory */\n clientOutput?: string;\n /** Include Pothos generator (default: true) */\n includePothos?: boolean;\n /** Pothos output path */\n pothosOutput?: string;\n}\n\n/**\n * Define a schema configuration.\n */\nexport function defineSchemaConfig(config: SchemaConfig): SchemaConfig {\n return config;\n}\n\n/**\n * Load schema configuration from a file.\n */\nexport async function loadSchemaConfig(\n configPath: string\n): Promise<SchemaConfig | null> {\n try {\n // Try to import as ESM module\n const absolutePath = configPath.startsWith('/')\n ? configPath\n : `${process.cwd()}/${configPath}`;\n\n const module = await import(absolutePath);\n return module.default ?? module.config ?? module;\n } catch (error) {\n console.error(`Failed to load schema config from ${configPath}:`, error);\n return null;\n }\n}\n\n/**\n * Re-export types for convenience.\n */\nexport type { ModuleSchemaContribution };\n"],"mappings":";;;;AAuBA,SAAgB,mBAAmB,QAAoC;AACrE,QAAO;;;;;AAMT,eAAsB,iBACpB,YAC8B;AAC9B,KAAI;EAMF,MAAM,SAAS,OAJM,WAAW,WAAW,IAAI,UAC3C,qBACA,GAAG,QAAQ,KAAK,CAAC,GAAG;AAGxB,SAAO,OAAO,WAAW,OAAO,UAAU;UACnC,OAAO;AACd,UAAQ,MAAM,qCAAqC,WAAW,IAAI,MAAM;AACxE,SAAO"}
@@ -0,0 +1,14 @@
1
+ //#region src/lib/types.d.ts
2
+ interface ImportLockEntry {
3
+ moduleName: string;
4
+ version: string;
5
+ sourcePath: string;
6
+ sha256: string;
7
+ }
8
+ interface ImportLock {
9
+ updatedAt: string;
10
+ entries: ImportLockEntry[];
11
+ }
12
+ //#endregion
13
+ export { ImportLock, ImportLockEntry };
14
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../src/lib/types.ts"],"sourcesContent":[],"mappings":";UAAiB,eAAA;EAAA,UAAA,EAAA,MAAe;EAOf,OAAA,EAAA,MAAU;;;;UAAV,UAAA;;WAEN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/app.cli-database",
3
- "version": "1.41.1",
3
+ "version": "1.42.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "database": "dist/cli.js"
@@ -25,17 +25,18 @@
25
25
  "schema:compose": "database schema:compose"
26
26
  },
27
27
  "dependencies": {
28
- "@lssm/lib.schema": "1.41.1",
29
- "@prisma/adapter-pg": "^7.1.0",
30
- "@prisma/client": "^7.1.0",
31
- "prisma": "^7.1.0",
28
+ "@lssm/lib.schema": "1.42.1",
29
+ "@prisma/adapter-pg": "^7.2.0",
30
+ "@prisma/client": "^7.2.0",
31
+ "prisma": "^7.2.0",
32
32
  "minimist": "^1.2.8",
33
33
  "execa": "^9.6.1"
34
34
  },
35
35
  "devDependencies": {
36
- "@lssm/tool.tsdown": "1.41.1",
36
+ "@lssm/tool.typescript": "1.42.1",
37
+ "@lssm/tool.tsdown": "1.42.1",
37
38
  "@types/minimist": "^1.2.5",
38
- "tsdown": "^0.17.4"
39
+ "tsdown": "^0.18.3"
39
40
  },
40
41
  "main": "./dist/index.mjs",
41
42
  "module": "./dist/index.mjs",
@@ -45,8 +46,8 @@
45
46
  "README.md"
46
47
  ],
47
48
  "exports": {
48
- ".": "./src/index.ts",
49
- "./cli": "./src/cli.ts",
49
+ ".": "./dist/index.mjs",
50
+ "./cli": "./dist/cli.mjs",
50
51
  "./*": "./*"
51
52
  },
52
53
  "publishConfig": {
@@ -55,6 +56,13 @@
55
56
  ".": "./dist/index.mjs",
56
57
  "./cli": "./dist/cli.mjs",
57
58
  "./*": "./*"
58
- }
59
+ },
60
+ "registry": "https://registry.npmjs.org/"
61
+ },
62
+ "license": "MIT",
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "https://github.com/lssm-tech/contractspec.git",
66
+ "directory": "packages/apps/cli-database"
59
67
  }
60
68
  }