@lssm/app.cli-database 1.11.1 → 1.41.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/dist/cli.mjs +40 -1
- package/dist/commands/schema-compose.mjs +76 -0
- package/dist/commands/schema-generate.mjs +51 -0
- package/dist/index.mjs +2 -2
- package/dist/lib/schema-config.mjs +22 -0
- package/package.json +28 -17
- package/dist/cli.d.mts +0 -1
- package/dist/index.d.mts +0 -4
- package/dist/lib/client.d.mts +0 -7
- package/dist/lib/client.mjs +0 -17
- package/dist/lib/config.d.mts +0 -7
- package/dist/lib/types.d.mts +0 -13
package/dist/cli.mjs
CHANGED
|
@@ -4,6 +4,8 @@ import { runCheck } from "./commands/check.mjs";
|
|
|
4
4
|
import { runGenerate } from "./commands/generate.mjs";
|
|
5
5
|
import { runMigrate } from "./commands/migrate.mjs";
|
|
6
6
|
import { runSeed } from "./commands/seed.mjs";
|
|
7
|
+
import { runSchemaGenerate } from "./commands/schema-generate.mjs";
|
|
8
|
+
import { runSchemaCompose } from "./commands/schema-compose.mjs";
|
|
7
9
|
import mri from "minimist";
|
|
8
10
|
|
|
9
11
|
//#region src/cli.ts
|
|
@@ -28,11 +30,48 @@ async function main() {
|
|
|
28
30
|
case "seed":
|
|
29
31
|
await runSeed(argv);
|
|
30
32
|
break;
|
|
33
|
+
case "schema:generate":
|
|
34
|
+
await runSchemaGenerate(argv);
|
|
35
|
+
break;
|
|
36
|
+
case "schema:compose":
|
|
37
|
+
await runSchemaCompose(argv);
|
|
38
|
+
break;
|
|
31
39
|
default:
|
|
32
|
-
|
|
40
|
+
printUsage();
|
|
33
41
|
process.exit(1);
|
|
34
42
|
}
|
|
35
43
|
}
|
|
44
|
+
function printUsage() {
|
|
45
|
+
console.log(`
|
|
46
|
+
Usage: database <command> [options]
|
|
47
|
+
|
|
48
|
+
Commands:
|
|
49
|
+
import Import schema from external sources
|
|
50
|
+
check Check Prisma schema validity
|
|
51
|
+
generate Generate Prisma client
|
|
52
|
+
migrate:dev Run migrations in development
|
|
53
|
+
migrate:deploy Deploy migrations to production
|
|
54
|
+
migrate:status Check migration status
|
|
55
|
+
seed Seed the database
|
|
56
|
+
|
|
57
|
+
Schema Generation (spec-first):
|
|
58
|
+
schema:generate Generate Prisma schema from entity specs
|
|
59
|
+
--config <path> Schema config file (default: ./schema.config.ts)
|
|
60
|
+
--output <path> Output path (default: ./prisma/schema/generated.prisma)
|
|
61
|
+
--module <id> Generate only a specific module
|
|
62
|
+
|
|
63
|
+
schema:compose Compose multiple module schemas
|
|
64
|
+
--config <path> Schema config file (default: ./schema.config.ts)
|
|
65
|
+
--output <path> Output path (default: ./prisma/schema/composed.prisma)
|
|
66
|
+
--modules <list> Comma-separated module IDs to include
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
database schema:generate --config ./schema.config.ts
|
|
70
|
+
database schema:compose --modules "@lssm/lib.identity-rbac,@lssm/module.audit-trail"
|
|
71
|
+
database generate
|
|
72
|
+
database migrate:dev --name add_users_table
|
|
73
|
+
`);
|
|
74
|
+
}
|
|
36
75
|
main().catch((err) => {
|
|
37
76
|
console.error(err);
|
|
38
77
|
process.exit(1);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { loadSchemaConfig } from "../lib/schema-config.mjs";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/schema-compose.ts
|
|
6
|
+
/**
|
|
7
|
+
* Compose multiple module schemas into a single Prisma schema.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* database schema:compose --config ./schema.config.ts
|
|
11
|
+
* database schema:compose --modules "@lssm/lib.identity-rbac,@lssm/module.audit-trail"
|
|
12
|
+
*/
|
|
13
|
+
async function runSchemaCompose(argv) {
|
|
14
|
+
console.log("🔗 Composing module schemas...\n");
|
|
15
|
+
const configPath = argv.config ?? "./schema.config.ts";
|
|
16
|
+
const config = await loadSchemaConfig(configPath);
|
|
17
|
+
if (!config) {
|
|
18
|
+
console.error(`❌ Could not load schema config from ${configPath}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
let modules = config.modules;
|
|
22
|
+
if (argv.modules) {
|
|
23
|
+
const moduleIds = argv.modules.split(",").map((m) => m.trim());
|
|
24
|
+
modules = config.modules.filter((m) => moduleIds.includes(m.moduleId));
|
|
25
|
+
}
|
|
26
|
+
if (modules.length === 0) {
|
|
27
|
+
console.error("❌ No modules found to compose");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
console.log(`📦 Composing ${modules.length} module(s):`);
|
|
31
|
+
modules.forEach((m) => {
|
|
32
|
+
console.log(` - ${m.moduleId}`);
|
|
33
|
+
m.entities.forEach((e) => {
|
|
34
|
+
console.log(` • ${e.name} (${Object.keys(e.fields).length} fields)`);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
console.log("");
|
|
38
|
+
const allEnums = /* @__PURE__ */ new Set();
|
|
39
|
+
modules.forEach((m) => {
|
|
40
|
+
m.enums?.forEach((e) => allEnums.add(e.name));
|
|
41
|
+
m.entities.forEach((entity) => {
|
|
42
|
+
entity.enums?.forEach((e) => allEnums.add(e.name));
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
if (allEnums.size > 0) {
|
|
46
|
+
console.log(`📋 Enums discovered: ${Array.from(allEnums).join(", ")}`);
|
|
47
|
+
console.log("");
|
|
48
|
+
}
|
|
49
|
+
const { composeModuleSchemas } = await import("@lssm/lib.schema");
|
|
50
|
+
const prismaSchema = composeModuleSchemas(modules, {
|
|
51
|
+
provider: config.provider ?? "postgresql",
|
|
52
|
+
clientOutput: config.clientOutput,
|
|
53
|
+
includePothos: config.includePothos ?? true,
|
|
54
|
+
pothosOutput: config.pothosOutput
|
|
55
|
+
});
|
|
56
|
+
const outputPath = argv.output ?? config.outputPath ?? "./prisma/schema/composed.prisma";
|
|
57
|
+
const outputDir = path.dirname(outputPath);
|
|
58
|
+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
59
|
+
fs.writeFileSync(outputPath, prismaSchema, "utf-8");
|
|
60
|
+
const entityCount = modules.reduce((acc, m) => acc + m.entities.length, 0);
|
|
61
|
+
const fieldCount = modules.reduce((acc, m) => acc + m.entities.reduce((eAcc, e) => eAcc + Object.keys(e.fields).length, 0), 0);
|
|
62
|
+
console.log("✅ Schema composition complete!");
|
|
63
|
+
console.log("");
|
|
64
|
+
console.log(` 📄 Output: ${outputPath}`);
|
|
65
|
+
console.log(` 📦 Modules: ${modules.length}`);
|
|
66
|
+
console.log(` 🏗️ Entities: ${entityCount}`);
|
|
67
|
+
console.log(` 📝 Fields: ${fieldCount}`);
|
|
68
|
+
console.log(` 📋 Enums: ${allEnums.size}`);
|
|
69
|
+
console.log("");
|
|
70
|
+
console.log("Next steps:");
|
|
71
|
+
console.log(" 1. Run: database generate");
|
|
72
|
+
console.log(" 2. Run: database migrate:dev --name <migration-name>");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { runSchemaCompose };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { loadSchemaConfig } from "../lib/schema-config.mjs";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/schema-generate.ts
|
|
6
|
+
/**
|
|
7
|
+
* Generate Prisma schema from ContractSpec entity definitions.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* database schema:generate --config ./schema.config.ts --output ./prisma/schema
|
|
11
|
+
* database schema:generate --module @lssm/lib.identity-rbac
|
|
12
|
+
*/
|
|
13
|
+
async function runSchemaGenerate(argv) {
|
|
14
|
+
console.log("📝 Generating Prisma schema from entity specs...\n");
|
|
15
|
+
const configPath = argv.config ?? "./schema.config.ts";
|
|
16
|
+
const config = await loadSchemaConfig(configPath);
|
|
17
|
+
if (!config) {
|
|
18
|
+
console.error(`❌ Could not load schema config from ${configPath}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const modules = argv.module ? config.modules.filter((m) => m.moduleId === argv.module) : config.modules;
|
|
22
|
+
if (modules.length === 0) {
|
|
23
|
+
console.error("❌ No modules found to generate");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
console.log(`📦 Processing ${modules.length} module(s):`);
|
|
27
|
+
modules.forEach((m) => {
|
|
28
|
+
console.log(` - ${m.moduleId} (${m.entities.length} entities)`);
|
|
29
|
+
});
|
|
30
|
+
console.log("");
|
|
31
|
+
const { composeModuleSchemas } = await import("@lssm/lib.schema");
|
|
32
|
+
const prismaSchema = composeModuleSchemas(modules, {
|
|
33
|
+
provider: config.provider ?? "postgresql",
|
|
34
|
+
clientOutput: config.clientOutput,
|
|
35
|
+
includePothos: config.includePothos ?? true,
|
|
36
|
+
pothosOutput: config.pothosOutput
|
|
37
|
+
});
|
|
38
|
+
const outputPath = argv.output ?? config.outputPath ?? "./prisma/schema/generated.prisma";
|
|
39
|
+
const outputDir = path.dirname(outputPath);
|
|
40
|
+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
41
|
+
fs.writeFileSync(outputPath, prismaSchema, "utf-8");
|
|
42
|
+
console.log(`✅ Generated Prisma schema: ${outputPath}`);
|
|
43
|
+
console.log("");
|
|
44
|
+
console.log("Next steps:");
|
|
45
|
+
console.log(" 1. Review the generated schema");
|
|
46
|
+
console.log(" 2. Run: database generate");
|
|
47
|
+
console.log(" 3. Run: database migrate:dev");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { runSchemaGenerate };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineSchemaConfig, loadSchemaConfig } from "./lib/schema-config.mjs";
|
|
2
2
|
import { defineMergedPrismaConfig } from "./lib/config.mjs";
|
|
3
3
|
|
|
4
|
-
export {
|
|
4
|
+
export { defineMergedPrismaConfig, defineSchemaConfig, loadSchemaConfig };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/lib/schema-config.ts
|
|
2
|
+
/**
|
|
3
|
+
* Define a schema configuration.
|
|
4
|
+
*/
|
|
5
|
+
function defineSchemaConfig(config) {
|
|
6
|
+
return config;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Load schema configuration from a file.
|
|
10
|
+
*/
|
|
11
|
+
async function loadSchemaConfig(configPath) {
|
|
12
|
+
try {
|
|
13
|
+
const module = await (configPath.startsWith("/") ? import(configPath) : import(`${process.cwd()}/${configPath}`));
|
|
14
|
+
return module.default ?? module.config ?? module;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error(`Failed to load schema config from ${configPath}:`, error);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { defineSchemaConfig, loadSchemaConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lssm/app.cli-database",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"database": "dist/cli.js"
|
|
@@ -8,28 +8,34 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"clean": "rm -rf dist",
|
|
10
10
|
"publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
|
|
11
|
+
"publish:pkg:canary": "bun publish:pkg --tag canary",
|
|
11
12
|
"build": "tsdown",
|
|
12
13
|
"dev": "bun run build --watch",
|
|
13
14
|
"lint": "bun run lint:fix",
|
|
14
15
|
"lint:fix": "eslint src --fix",
|
|
15
16
|
"lint:check": "eslint src",
|
|
16
|
-
"prisma:import": "
|
|
17
|
-
"prisma:check": "
|
|
18
|
-
"dbs:generate": "
|
|
19
|
-
"dbs:migrate": "
|
|
20
|
-
"dbs:deploy": "
|
|
21
|
-
"dbs:status": "
|
|
22
|
-
"dbs:seed": "
|
|
17
|
+
"prisma:import": "database import",
|
|
18
|
+
"prisma:check": "database check",
|
|
19
|
+
"dbs:generate": "database generate",
|
|
20
|
+
"dbs:migrate": "database migrate:dev",
|
|
21
|
+
"dbs:deploy": "database migrate:deploy",
|
|
22
|
+
"dbs:status": "database migrate:status",
|
|
23
|
+
"dbs:seed": "database seed",
|
|
24
|
+
"schema:generate": "database schema:generate",
|
|
25
|
+
"schema:compose": "database schema:compose"
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
25
|
-
"@
|
|
26
|
-
"@prisma/
|
|
27
|
-
"prisma": "^7.0
|
|
28
|
-
"
|
|
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",
|
|
32
|
+
"minimist": "^1.2.8",
|
|
33
|
+
"execa": "^9.6.1"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
|
-
"@lssm/tool.tsdown": "
|
|
32
|
-
"
|
|
36
|
+
"@lssm/tool.tsdown": "1.41.1",
|
|
37
|
+
"@types/minimist": "^1.2.5",
|
|
38
|
+
"tsdown": "^0.17.4"
|
|
33
39
|
},
|
|
34
40
|
"main": "./dist/index.mjs",
|
|
35
41
|
"module": "./dist/index.mjs",
|
|
@@ -39,11 +45,16 @@
|
|
|
39
45
|
"README.md"
|
|
40
46
|
],
|
|
41
47
|
"exports": {
|
|
42
|
-
".": "./
|
|
43
|
-
"./cli": "./
|
|
48
|
+
".": "./src/index.ts",
|
|
49
|
+
"./cli": "./src/cli.ts",
|
|
44
50
|
"./*": "./*"
|
|
45
51
|
},
|
|
46
52
|
"publishConfig": {
|
|
47
|
-
"access": "public"
|
|
53
|
+
"access": "public",
|
|
54
|
+
"exports": {
|
|
55
|
+
".": "./dist/index.mjs",
|
|
56
|
+
"./cli": "./dist/cli.mjs",
|
|
57
|
+
"./*": "./*"
|
|
58
|
+
}
|
|
48
59
|
}
|
|
49
60
|
}
|
package/dist/cli.d.mts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { };
|
package/dist/index.d.mts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { createPrismaClientFromEnv, getSingletonClient } from "./lib/client.mjs";
|
|
2
|
-
import { ImportLock, ImportLockEntry } from "./lib/types.mjs";
|
|
3
|
-
import { MergedPrismaConfig, defineMergedPrismaConfig } from "./lib/config.mjs";
|
|
4
|
-
export { ImportLock, ImportLockEntry, MergedPrismaConfig, createPrismaClientFromEnv, defineMergedPrismaConfig, getSingletonClient };
|
package/dist/lib/client.d.mts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { PrismaClient } from "@prisma/client";
|
|
2
|
-
|
|
3
|
-
//#region src/lib/client.d.ts
|
|
4
|
-
declare function createPrismaClientFromEnv(envVar: string, fallback?: string): PrismaClient;
|
|
5
|
-
declare function getSingletonClient(envVar?: string): PrismaClient;
|
|
6
|
-
//#endregion
|
|
7
|
-
export { createPrismaClientFromEnv, getSingletonClient };
|
package/dist/lib/client.mjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { PrismaClient } from "@prisma/client";
|
|
2
|
-
import { PrismaPg } from "@prisma/adapter-pg";
|
|
3
|
-
|
|
4
|
-
//#region src/lib/client.ts
|
|
5
|
-
const g = global;
|
|
6
|
-
function createPrismaClientFromEnv(envVar, fallback) {
|
|
7
|
-
const raw = process.env[envVar] || (fallback ? process.env[fallback] : void 0);
|
|
8
|
-
if (!raw) throw new Error(`Missing database URL env: ${envVar}${fallback ? ` (or ${fallback})` : ""}`);
|
|
9
|
-
return new PrismaClient({ adapter: new PrismaPg({ connectionString: `${raw}`.replaceAll("sslmode=require", "sslmode=disable") }) });
|
|
10
|
-
}
|
|
11
|
-
function getSingletonClient(envVar = "DATABASE_URL") {
|
|
12
|
-
if (!g.__lssm_db) g.__lssm_db = createPrismaClientFromEnv(envVar);
|
|
13
|
-
return g.__lssm_db;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
export { createPrismaClientFromEnv, getSingletonClient };
|
package/dist/lib/config.d.mts
DELETED
package/dist/lib/types.d.mts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
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 };
|