@better-media/cli 0.6.0 → 0.8.0
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/index.js +213 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -178,6 +178,207 @@ import {
|
|
|
178
178
|
compileMigrationOperationsSql,
|
|
179
179
|
applyOperationsToMetadata
|
|
180
180
|
} from "@better-media/core";
|
|
181
|
+
|
|
182
|
+
// src/generators/drizzle-schema.ts
|
|
183
|
+
function dialectToProvider(dialect) {
|
|
184
|
+
if (dialect === "postgres") return "pg";
|
|
185
|
+
if (dialect === "mysql") return "mysql";
|
|
186
|
+
return "sqlite";
|
|
187
|
+
}
|
|
188
|
+
function camelToSnake(str) {
|
|
189
|
+
return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
190
|
+
}
|
|
191
|
+
function snakeToCamel(str) {
|
|
192
|
+
return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
193
|
+
}
|
|
194
|
+
function modelVarName(modelName) {
|
|
195
|
+
return snakeToCamel(modelName);
|
|
196
|
+
}
|
|
197
|
+
function indexName(tableName, fields) {
|
|
198
|
+
return `idx_${tableName}_${fields.map(camelToSnake).join("_")}`;
|
|
199
|
+
}
|
|
200
|
+
function pgColFn(fieldName, field) {
|
|
201
|
+
const col = camelToSnake(fieldName);
|
|
202
|
+
switch (field.type) {
|
|
203
|
+
case "number":
|
|
204
|
+
return `integer("${col}")`;
|
|
205
|
+
case "boolean":
|
|
206
|
+
return `boolean("${col}")`;
|
|
207
|
+
case "date":
|
|
208
|
+
return `timestamp("${col}", { mode: "date" })`;
|
|
209
|
+
case "json":
|
|
210
|
+
return `jsonb("${col}")`;
|
|
211
|
+
default:
|
|
212
|
+
return `text("${col}")`;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function mysqlColFn(fieldName, field) {
|
|
216
|
+
const col = camelToSnake(fieldName);
|
|
217
|
+
switch (field.type) {
|
|
218
|
+
case "number":
|
|
219
|
+
return `int("${col}")`;
|
|
220
|
+
case "boolean":
|
|
221
|
+
return `boolean("${col}")`;
|
|
222
|
+
case "date":
|
|
223
|
+
return `datetime("${col}", { mode: "date" })`;
|
|
224
|
+
case "json":
|
|
225
|
+
return `json("${col}")`;
|
|
226
|
+
default:
|
|
227
|
+
return `text("${col}")`;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function sqliteColFn(fieldName, field) {
|
|
231
|
+
const col = camelToSnake(fieldName);
|
|
232
|
+
switch (field.type) {
|
|
233
|
+
case "number":
|
|
234
|
+
return `integer("${col}")`;
|
|
235
|
+
case "boolean":
|
|
236
|
+
return `integer("${col}", { mode: "boolean" })`;
|
|
237
|
+
case "date":
|
|
238
|
+
return `integer("${col}", { mode: "timestamp" })`;
|
|
239
|
+
case "json":
|
|
240
|
+
return `text("${col}", { mode: "json" })`;
|
|
241
|
+
default:
|
|
242
|
+
return `text("${col}")`;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function getColFn(fieldName, field, provider) {
|
|
246
|
+
switch (provider) {
|
|
247
|
+
case "pg":
|
|
248
|
+
return pgColFn(fieldName, field);
|
|
249
|
+
case "mysql":
|
|
250
|
+
return mysqlColFn(fieldName, field);
|
|
251
|
+
case "sqlite":
|
|
252
|
+
return sqliteColFn(fieldName, field);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function buildColChain(fieldName, field, provider) {
|
|
256
|
+
let chain = getColFn(fieldName, field, provider);
|
|
257
|
+
if (field.primaryKey) chain += ".primaryKey()";
|
|
258
|
+
if (field.required && !field.primaryKey) chain += ".notNull()";
|
|
259
|
+
if (field.unique && !field.primaryKey) chain += ".unique()";
|
|
260
|
+
if (field.references) {
|
|
261
|
+
const refVar = modelVarName(field.references.model);
|
|
262
|
+
const onDelete = field.references.onDelete ?? "cascade";
|
|
263
|
+
chain += `.references(() => ${refVar}.${field.references.field}, { onDelete: "${onDelete}" })`;
|
|
264
|
+
}
|
|
265
|
+
return chain;
|
|
266
|
+
}
|
|
267
|
+
function collectImports(schema2, provider) {
|
|
268
|
+
const names = /* @__PURE__ */ new Set();
|
|
269
|
+
switch (provider) {
|
|
270
|
+
case "pg":
|
|
271
|
+
names.add("pgTable");
|
|
272
|
+
break;
|
|
273
|
+
case "mysql":
|
|
274
|
+
names.add("mysqlTable");
|
|
275
|
+
break;
|
|
276
|
+
case "sqlite":
|
|
277
|
+
names.add("sqliteTable");
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
for (const model of Object.values(schema2)) {
|
|
281
|
+
for (const field of Object.values(model.fields)) {
|
|
282
|
+
switch (provider) {
|
|
283
|
+
case "pg":
|
|
284
|
+
if (field.type === "number") names.add("integer");
|
|
285
|
+
else if (field.type === "boolean") names.add("boolean");
|
|
286
|
+
else if (field.type === "date") names.add("timestamp");
|
|
287
|
+
else if (field.type === "json") names.add("jsonb");
|
|
288
|
+
else names.add("text");
|
|
289
|
+
break;
|
|
290
|
+
case "mysql":
|
|
291
|
+
if (field.type === "number") names.add("int");
|
|
292
|
+
else if (field.type === "boolean") names.add("boolean");
|
|
293
|
+
else if (field.type === "date") names.add("datetime");
|
|
294
|
+
else if (field.type === "json") names.add("json");
|
|
295
|
+
else names.add("text");
|
|
296
|
+
break;
|
|
297
|
+
case "sqlite":
|
|
298
|
+
if (field.type === "string" || field.type === "json") names.add("text");
|
|
299
|
+
else names.add("integer");
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (model.indexes && model.indexes.length > 0) {
|
|
304
|
+
for (const idx of model.indexes) {
|
|
305
|
+
if (idx.unique && idx.fields.length > 1) names.add("uniqueIndex");
|
|
306
|
+
else if (!idx.unique) names.add("index");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const modulePath = provider === "pg" ? "drizzle-orm/pg-core" : provider === "mysql" ? "drizzle-orm/mysql-core" : "drizzle-orm/sqlite-core";
|
|
311
|
+
return { modulePath, names: [...names].sort() };
|
|
312
|
+
}
|
|
313
|
+
function topoSort(schema2) {
|
|
314
|
+
const deps = {};
|
|
315
|
+
for (const [name, model] of Object.entries(schema2)) {
|
|
316
|
+
deps[name] = /* @__PURE__ */ new Set();
|
|
317
|
+
for (const field of Object.values(model.fields)) {
|
|
318
|
+
if (field.references) deps[name].add(field.references.model);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const sorted = [];
|
|
322
|
+
const visited = /* @__PURE__ */ new Set();
|
|
323
|
+
function visit(name) {
|
|
324
|
+
if (visited.has(name)) return;
|
|
325
|
+
visited.add(name);
|
|
326
|
+
for (const dep of deps[name] ?? []) visit(dep);
|
|
327
|
+
sorted.push(name);
|
|
328
|
+
}
|
|
329
|
+
for (const name of Object.keys(schema2)) visit(name);
|
|
330
|
+
return sorted;
|
|
331
|
+
}
|
|
332
|
+
function tableFactoryName(provider) {
|
|
333
|
+
return provider === "pg" ? "pgTable" : provider === "mysql" ? "mysqlTable" : "sqliteTable";
|
|
334
|
+
}
|
|
335
|
+
function generateTable(modelName, model, provider) {
|
|
336
|
+
const varName = modelVarName(modelName);
|
|
337
|
+
const factory = tableFactoryName(provider);
|
|
338
|
+
const lines = [];
|
|
339
|
+
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
340
|
+
lines.push(` ${fieldName}: ${buildColChain(fieldName, field, provider)},`);
|
|
341
|
+
}
|
|
342
|
+
const compositeIndexes = model.indexes?.filter(
|
|
343
|
+
(idx) => idx.fields.length > 1 || idx.fields.length === 1 && !idx.unique
|
|
344
|
+
) ?? [];
|
|
345
|
+
if (compositeIndexes.length === 0) {
|
|
346
|
+
return `export const ${varName} = ${factory}("${modelName}", {
|
|
347
|
+
${lines.join("\n")}
|
|
348
|
+
});`;
|
|
349
|
+
}
|
|
350
|
+
const idxLines = compositeIndexes.map((idx) => {
|
|
351
|
+
const cols = idx.fields.map((f) => `t.${f}`).join(", ");
|
|
352
|
+
const name = indexName(modelName, idx.fields);
|
|
353
|
+
return idx.unique ? ` uniqueIndex("${name}").on(${cols}),` : ` index("${name}").on(${cols}),`;
|
|
354
|
+
});
|
|
355
|
+
return `export const ${varName} = ${factory}("${modelName}", {
|
|
356
|
+
${lines.join("\n")}
|
|
357
|
+
}, (t) => [
|
|
358
|
+
${idxLines.join("\n")}
|
|
359
|
+
]);`;
|
|
360
|
+
}
|
|
361
|
+
function generateDrizzleSchema(schema2, dialect) {
|
|
362
|
+
const provider = dialectToProvider(dialect);
|
|
363
|
+
const { modulePath, names } = collectImports(schema2, provider);
|
|
364
|
+
const order = topoSort(schema2);
|
|
365
|
+
const header = [
|
|
366
|
+
`// Auto-generated by @better-media/cli \u2014 do not edit directly.`,
|
|
367
|
+
`// Run "npx better-media generate --dialect ${dialect}" to regenerate.`,
|
|
368
|
+
`// After editing, run "npx drizzle-kit generate" then "npx drizzle-kit migrate".`,
|
|
369
|
+
``,
|
|
370
|
+
`import { ${names.join(", ")} } from "${modulePath}";`,
|
|
371
|
+
``
|
|
372
|
+
].join("\n");
|
|
373
|
+
const tables = order.map((name) => {
|
|
374
|
+
const model = schema2[name];
|
|
375
|
+
if (!model) return "";
|
|
376
|
+
return generateTable(name, model, provider);
|
|
377
|
+
}).filter(Boolean).join("\n\n");
|
|
378
|
+
return header + tables + "\n";
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// src/generators/index.ts
|
|
181
382
|
function resolveMigrationsDir(cwd, outPath, options) {
|
|
182
383
|
const opts = options;
|
|
183
384
|
if (opts?.migrationsDir && typeof opts.migrationsDir === "string") {
|
|
@@ -254,9 +455,18 @@ var builtInGenerators = {
|
|
|
254
455
|
'[media] Prisma schema generator is not implemented yet. Run "npx better-media generate" with Kysely, then apply via Prisma migrate/push.'
|
|
255
456
|
);
|
|
256
457
|
},
|
|
257
|
-
async drizzle() {
|
|
258
|
-
|
|
259
|
-
|
|
458
|
+
async drizzle({ cwd, outPath, dialect }) {
|
|
459
|
+
const provider = dialectToProvider(dialect);
|
|
460
|
+
const code = generateDrizzleSchema(schema, dialect);
|
|
461
|
+
const defaultTs = path2.join(path2.dirname(outPath), `drizzle-schema.${provider}.ts`);
|
|
462
|
+
const resolvedOut = outPath.endsWith(".ts") ? outPath : defaultTs;
|
|
463
|
+
await fs2.ensureDir(path2.dirname(resolvedOut));
|
|
464
|
+
await fs2.writeFile(resolvedOut, code, "utf8");
|
|
465
|
+
console.log(
|
|
466
|
+
chalk.green(`[media] Generated Drizzle schema at ${path2.relative(cwd, resolvedOut)}`)
|
|
467
|
+
);
|
|
468
|
+
console.log(
|
|
469
|
+
chalk.gray(`[media] Next: run "npx drizzle-kit generate" then "npx drizzle-kit migrate"`)
|
|
260
470
|
);
|
|
261
471
|
}
|
|
262
472
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/project-config.ts","../src/commands/generate.ts","../src/generators/index.ts","../src/commands/init.ts","../src/commands/migrate.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { loadProjectConfig } from \"./project-config\";\nimport { registerGenerateCommand } from \"./commands/generate\";\nimport { registerInitCommand } from \"./commands/init\";\nimport { registerMigrateCommand } from \"./commands/migrate\";\n\nconst program = new Command();\n\nprogram.name(\"media\").description(\"CLI for Better Media framework\").version(\"1.0.0\");\n\nregisterInitCommand(program);\n\nregisterGenerateCommand(program);\nregisterMigrateCommand(program);\n\nprogram\n .command(\"config\")\n .description(\"Validate and print resolved module exports (debug)\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .action(async (opts: { cwd: string; config?: string }) => {\n const cwd = path.resolve(opts.cwd);\n const loaded = await loadProjectConfig({ cwd, configPath: opts.config });\n console.log(\n chalk.gray(\"[media] Resolved config:\"),\n JSON.stringify(\n {\n configPath: loaded.configPath,\n adapterHint: loaded.adapterHint,\n dialect: loaded.config.dialect,\n schemaOutput: loaded.config.schemaOutput,\n migrationsDir: loaded.config.migrationsDir,\n },\n null,\n 2\n )\n );\n });\n\nprogram.parse(process.argv);\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { randomUUID } from \"node:crypto\";\nimport type { GetAdapterOptions } from \"@better-media/core\";\nimport ts from \"typescript\";\n\nexport type AdapterHint = \"kysely\" | \"prisma\" | \"drizzle\" | \"unknown\";\n\nexport type ProjectConfig = GetAdapterOptions & {\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport type LoadedProjectConfig = {\n configPath: string;\n adapterHint: AdapterHint;\n config: ProjectConfig;\n};\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await fs.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function detectAdapterHint(cwd: string): Promise<AdapterHint> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const raw = await fs.readFile(pkgPath, \"utf8\");\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n };\n const deps = {\n ...(pkg.dependencies ?? {}),\n ...(pkg.devDependencies ?? {}),\n ...(pkg.peerDependencies ?? {}),\n };\n if (\"kysely\" in deps) return \"kysely\";\n if (\"prisma\" in deps || \"@prisma/client\" in deps) return \"prisma\";\n if (\"drizzle-orm\" in deps) return \"drizzle\";\n return \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction normalizeModuleExport(mod: unknown): unknown {\n if (!mod) return mod;\n const m = mod as Record<string, unknown>;\n return (m.default ?? mod) as unknown;\n}\n\nasync function importJsModule(absPath: string): Promise<unknown> {\n const url = pathToFileURL(absPath).href;\n const mod = await import(url);\n return normalizeModuleExport(mod);\n}\n\nasync function requireTsModule(absPath: string): Promise<unknown> {\n const require = createRequire(import.meta.url);\n\n try {\n const tsNode = require(\"ts-node\") as {\n register: (opts?: {\n transpileOnly?: boolean;\n compilerOptions?: Record<string, unknown>;\n }) => void;\n };\n tsNode.register({\n transpileOnly: true,\n compilerOptions: { module: \"CommonJS\", moduleResolution: \"Node\" },\n });\n } catch {\n // ignore (we'll surface a clearer error below if require fails)\n }\n\n const mod = require(absPath) as unknown;\n return normalizeModuleExport(mod);\n}\n\nasync function importTsModule(absPath: string): Promise<unknown> {\n const source = await fs.readFile(absPath, \"utf8\");\n const transpiled = ts.transpileModule(source, {\n compilerOptions: {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n esModuleInterop: true,\n resolveJsonModule: true,\n },\n fileName: absPath,\n });\n\n // Emit beside source so relative imports keep working.\n const tempPath = path.join(path.dirname(absPath), `.media-config-${randomUUID()}.mjs`);\n await fs.writeFile(tempPath, transpiled.outputText, \"utf8\");\n\n try {\n const mod = await import(pathToFileURL(tempPath).href);\n return normalizeModuleExport(mod);\n } finally {\n await fs.unlink(tempPath).catch(() => undefined);\n }\n}\n\nfunction assertValidConfig(\n value: unknown,\n configPath: string\n): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\") {\n throw new Error(`[media] Config \"${configPath}\" must export an object.`);\n }\n}\n\nconst CONFIG_CANDIDATES = [\n \"media.config.ts\",\n \"media.config.js\",\n \"better-media.config.ts\",\n \"better-media.config.js\",\n] as const;\n\nexport async function loadProjectConfig(options?: {\n cwd?: string;\n configPath?: string;\n}): Promise<LoadedProjectConfig> {\n const cwd = path.resolve(options?.cwd ?? process.cwd());\n\n let configPath = options?.configPath ? path.resolve(cwd, options.configPath) : undefined;\n\n if (configPath && !(await fileExists(configPath))) {\n throw new Error(`[media] Config file not found: ${path.relative(cwd, configPath)}`);\n }\n\n if (!configPath) {\n for (const candidate of CONFIG_CANDIDATES) {\n const abs = path.join(cwd, candidate);\n\n if (await fileExists(abs)) {\n configPath = abs;\n break;\n }\n }\n if (!configPath) {\n throw new Error(\n `[media] No configuration file found. Add one of: ${CONFIG_CANDIDATES.map(\n (c) => `\"${c}\"`\n ).join(\", \")}, or pass --config <path>.`\n );\n }\n }\n\n if (!configPath) {\n throw new Error(\n `[media] No configuration file found. Add one of: ${CONFIG_CANDIDATES.map(\n (c) => `\"${c}\"`\n ).join(\", \")}, or pass --config <path>.`\n );\n }\n\n const adapterHint = await detectAdapterHint(cwd);\n const ext = path.extname(configPath);\n\n let rawConfig: unknown;\n try {\n rawConfig =\n ext === \".ts\" ? await requireTsModule(configPath) : await importJsModule(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (ext === \".ts\") {\n try {\n rawConfig = await importTsModule(configPath);\n } catch {\n throw new Error(\n `[media] Failed to load \"${path.basename(\n configPath\n )}\". For TypeScript configs, install \"ts-node\" in your app or use a .js config. Original error: ${msg}`\n );\n }\n } else {\n throw err;\n }\n }\n\n assertValidConfig(rawConfig, configPath);\n\n const cfg = rawConfig as Record<string, unknown>;\n const dialect = typeof cfg.dialect === \"string\" ? (cfg.dialect as string) : undefined;\n const schemaOutput =\n typeof cfg.schemaOutput === \"string\" ? (cfg.schemaOutput as string) : undefined;\n const migrationsDir =\n typeof cfg.migrationsDir === \"string\" ? (cfg.migrationsDir as string) : undefined;\n\n return {\n configPath,\n adapterHint,\n config: {\n database: cfg.database as ProjectConfig[\"database\"],\n createDatabase: cfg.createDatabase as ProjectConfig[\"createDatabase\"],\n dialect,\n schemaOutput,\n migrationsDir,\n },\n };\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { getAdapter, type SqlDialect } from \"@better-media/core\";\nimport { loadProjectConfig } from \"../project-config\";\nimport { generateSchema } from \"../generators\";\n\n/** Default path whose directory is the migrations root (filename unused for output). */\nfunction getDefaultSchemaOutput(): string {\n return \"better-media-migrations/migration.sql\";\n}\n\nexport function registerGenerateCommand(program: Command): void {\n program\n .command(\"generate\")\n .description(\"Generate Better Media database schema for the configured adapter\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .option(\n \"--dialect <dialect>\",\n \"SQL dialect (postgres|mysql|sqlite|mssql). Defaults from adapter/config.\",\n undefined\n )\n .action(async (opts: { cwd: string; config?: string; dialect?: SqlDialect }) => {\n const cwd = path.resolve(opts.cwd);\n const loaded = await loadProjectConfig({ cwd, configPath: opts.config });\n const adapter = await getAdapter(loaded.config);\n\n const dialectFromAdapter =\n typeof (adapter as unknown as { __getDialect?: () => SqlDialect }).__getDialect ===\n \"function\"\n ? (adapter as unknown as { __getDialect: () => SqlDialect }).__getDialect()\n : undefined;\n const dialect =\n opts.dialect ??\n (loaded.config.dialect as SqlDialect | undefined) ??\n dialectFromAdapter ??\n \"postgres\";\n\n const outPath = path.resolve(cwd, loaded.config.schemaOutput ?? getDefaultSchemaOutput());\n await generateSchema({\n cwd,\n adapter,\n outPath,\n dialect,\n options: loaded.config,\n });\n });\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport chalk from \"chalk\";\nimport {\n schema,\n getMigrations,\n MigrationPlanner,\n compileMigrationOperationsSql,\n type SqlDialect,\n type MigrationOptions,\n type TableMetadata,\n applyOperationsToMetadata,\n} from \"@better-media/core\";\nimport type { DatabaseAdapter } from \"@better-media/core\";\n\ntype CustomSchemaResult = {\n code: string;\n fileName?: string;\n path?: string;\n overwrite?: boolean;\n};\n\ntype AdapterWithExtras = DatabaseAdapter & {\n id?: string;\n createSchema?: (options: unknown, file?: string) => Promise<CustomSchemaResult>;\n};\n\ntype GenerateFn = (args: {\n cwd: string;\n adapter: DatabaseAdapter;\n outPath: string;\n dialect: SqlDialect;\n options?: unknown;\n}) => Promise<void>;\n\ntype MigrateFn = (args: {\n adapter: DatabaseAdapter;\n mode: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n}) => Promise<void>;\n\nfunction resolveMigrationsDir(cwd: string, outPath: string, options: unknown): string {\n const opts = options as { migrationsDir?: string } | undefined;\n if (opts?.migrationsDir && typeof opts.migrationsDir === \"string\") {\n return path.resolve(cwd, opts.migrationsDir);\n }\n return path.dirname(outPath);\n}\n\n/** Subfolders named with numeric timestamps (ms) contain `migration.sql` + `snapshot.json` per run. */\nconst TIMESTAMP_DIR = /^\\d{10,20}$/;\n\nasync function findLatestTimestampRunDir(migrationsDir: string): Promise<string | undefined> {\n if (!(await fs.pathExists(migrationsDir))) return undefined;\n const entries = await fs.readdir(migrationsDir, { withFileTypes: true });\n const names = entries\n .filter((e) => e.isDirectory() && TIMESTAMP_DIR.test(e.name))\n .map((e) => e.name);\n const latest = names[0];\n return latest ? path.join(migrationsDir, latest) : undefined;\n}\n\nasync function resolveSnapshotReadPath(migrationsDir: string): Promise<string | undefined> {\n const latestRun = await findLatestTimestampRunDir(migrationsDir);\n const nested = latestRun ? path.join(latestRun, \"snapshot.json\") : undefined;\n if (nested && (await fs.pathExists(nested))) return nested;\n const legacyRoot = path.join(migrationsDir, \"snapshot.json\");\n if (await fs.pathExists(legacyRoot)) return legacyRoot;\n return undefined;\n}\n\nconst builtInGenerators: Record<string, GenerateFn> = {\n async kysely({ cwd, outPath, dialect, adapter, options }) {\n const migrationsDir = resolveMigrationsDir(cwd, outPath, options);\n await fs.ensureDir(migrationsDir);\n\n let currentTables: TableMetadata[] = [];\n let snapshotLoaded = false;\n\n const snapshotReadPath = await resolveSnapshotReadPath(migrationsDir);\n if (snapshotReadPath) {\n try {\n currentTables = await fs.readJson(snapshotReadPath);\n snapshotLoaded = true;\n } catch {\n console.warn(\n chalk.yellow(\n `[media] Failed to load snapshot at ${snapshotReadPath}, falling back to DB introspection.`\n )\n );\n }\n }\n\n if (!snapshotLoaded) {\n if (typeof (adapter as { __getMetadata?: unknown }).__getMetadata === \"function\") {\n currentTables = await (\n adapter as unknown as { __getMetadata: () => Promise<TableMetadata[]> }\n ).__getMetadata();\n }\n }\n\n const planner = new MigrationPlanner(dialect);\n const plannedOperations = planner.plan(schema, currentTables);\n\n if (plannedOperations.length === 0) {\n console.log(\n chalk.blue(`[media] No changes detected. Database/Snapshot is already up to date.`)\n );\n return;\n }\n\n const sql = compileMigrationOperationsSql({ operations: plannedOperations, dialect });\n\n const nextMetadata = applyOperationsToMetadata(currentTables, plannedOperations, dialect);\n const runTs = Date.now();\n const runDir = path.join(migrationsDir, String(runTs));\n await fs.ensureDir(runDir);\n\n const snapshotWritePath = path.join(runDir, \"snapshot.json\");\n await fs.writeJson(snapshotWritePath, nextMetadata, { spaces: 2 });\n\n const migrationFile = path.join(runDir, \"migration.sql\");\n await fs.writeFile(migrationFile, sql, \"utf8\");\n console.log(chalk.green(`[media] Generated migration at ${path.relative(cwd, migrationFile)}`));\n },\n async postgres(args) {\n const kysely = builtInGenerators.kysely;\n if (!kysely) throw new Error(\"Kysely generator not found\");\n await kysely(args);\n },\n async prisma() {\n throw new Error(\n '[media] Prisma schema generator is not implemented yet. Run \"npx better-media generate\" with Kysely, then apply via Prisma migrate/push.'\n );\n },\n async drizzle() {\n throw new Error(\n '[media] Drizzle schema generator is not implemented yet. Run \"npx better-media generate\" with Kysely, then apply via Drizzle migrate/push.'\n );\n },\n};\n\nconst builtInMigrators: Record<string, MigrateFn> = {\n async kysely({ mode, dialect, adapter }) {\n const hasPlannedMigration =\n typeof (adapter as { __getMetadata?: unknown }).__getMetadata === \"function\" &&\n typeof (adapter as { __executeMigration?: unknown }).__executeMigration === \"function\";\n\n if (!hasPlannedMigration) {\n throw new Error(\n `[media] This adapter does not support direct CLI migrations. ` +\n `Use \"media generate\" and apply via your ORM migration tool.`\n );\n }\n const planned = await getMigrations(adapter, { mode, dialect });\n await planned.runMigrations();\n },\n async postgres(args) {\n const kysely = builtInMigrators.kysely;\n if (!kysely) throw new Error(\"Kysely migrator not found\");\n await kysely(args);\n },\n async prisma() {\n throw new Error(\n '[media] The migrate command only works with the built-in Kysely adapter. For Prisma, run \"npx better-media generate\" and apply with Prisma migrate/push.'\n );\n },\n async drizzle() {\n throw new Error(\n '[media] The migrate command only works with the built-in Kysely adapter. For Drizzle, run \"npx better-media generate\" and apply with Drizzle migrate/push.'\n );\n },\n};\n\nexport async function generateSchema(args: {\n cwd: string;\n adapter: DatabaseAdapter;\n outPath: string;\n dialect: SqlDialect;\n options?: unknown;\n}): Promise<void> {\n const adapterEx = args.adapter as AdapterWithExtras;\n const id = adapterEx.id;\n\n if (id && id in builtInGenerators) {\n await builtInGenerators[id]!(args);\n return;\n }\n\n if (typeof adapterEx.createSchema === \"function\") {\n const generated = await adapterEx.createSchema(args.options, args.outPath);\n const targetPath = generated.fileName ?? generated.path ?? args.outPath;\n const overwrite = generated.overwrite ?? true;\n if (!overwrite && (await fs.pathExists(targetPath))) {\n throw new Error(`[media] Refusing to overwrite existing file: ${targetPath}`);\n }\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, generated.code, \"utf8\");\n console.log(chalk.green(`[media] Generated schema at ${path.relative(args.cwd, targetPath)}`));\n return;\n }\n\n throw new Error(\n `[media] ${id ?? \"adapter\"} is not supported. If it is a custom adapter, implement createSchema(options, file).`\n );\n}\n\nexport async function migrateWithAdapter(args: {\n adapter: DatabaseAdapter;\n mode: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n}): Promise<void> {\n const adapterEx = args.adapter as AdapterWithExtras;\n const id = adapterEx.id;\n\n if (id && id in builtInMigrators) {\n await builtInMigrators[id]!(args);\n return;\n }\n\n if (\n typeof (args.adapter as { __getMetadata?: unknown }).__getMetadata === \"function\" &&\n typeof (args.adapter as { __executeMigration?: unknown }).__executeMigration === \"function\"\n ) {\n const kysely = builtInMigrators.kysely;\n if (!kysely) throw new Error(\"Kysely migrator not found\");\n await kysely(args);\n return;\n }\n\n throw new Error(`[media] Direct migrations are not supported for adapter \"${id ?? \"unknown\"}\".`);\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport fs from \"fs-extra\";\n\ntype DetectedFramework = \"express\" | \"nestjs\" | \"unknown\";\n\nfunction detectFramework(pkg: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}): DetectedFramework {\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n if (\"@nestjs/core\" in deps || \"@nestjs/common\" in deps) return \"nestjs\";\n if (\"express\" in deps) return \"express\";\n return \"unknown\";\n}\n\nfunction inferExtension(cwd: string, framework: DetectedFramework, pkgType?: string): \"ts\" | \"js\" {\n if (framework === \"nestjs\") return \"ts\";\n if (pkgType === \"module\") return \"js\";\n return \"ts\";\n}\n\nfunction buildConfigContent(ext: \"ts\" | \"js\"): string {\n const importPool = ext === \"ts\" ? 'import { Pool } from \"pg\";' : 'import { Pool } from \"pg\";';\n return `${importPool}\n\nexport const mediaOptions = {\n database: new Pool({\n connectionString:\n process.env.DATABASE_URL ?? \"postgres://postgres:postgres@localhost:5432/better_media\",\n }),\n dialect: \"postgres\",\n migrationsDir: \"better-media\",\n};\n\nexport default mediaOptions;\n`;\n}\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Generate media.config.ts/js based on detected framework\")\n .option(\"-C, --cwd <path>\", \"Working directory\", process.cwd())\n .option(\"-f, --force\", \"Overwrite existing config file\", false)\n .action(async (opts: { cwd: string; force?: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const pkgPath = path.join(cwd, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) {\n throw new Error(`[media] No package.json found in ${cwd}`);\n }\n\n const pkg = (await fs.readJson(pkgPath)) as {\n type?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const framework = detectFramework(pkg);\n const ext = inferExtension(cwd, framework, pkg.type);\n const configFile = path.join(cwd, `media.config.${ext}`);\n\n if ((await fs.pathExists(configFile)) && !opts.force) {\n throw new Error(\n `[media] ${path.basename(configFile)} already exists. Re-run with --force to overwrite.`\n );\n }\n\n const content = buildConfigContent(ext);\n await fs.writeFile(configFile, content, \"utf8\");\n\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n if (!(\"pg\" in deps)) {\n console.warn('[media] Added config uses \"pg\". Install it with: pnpm add pg');\n }\n\n console.log(\n `[media] Created ${path.basename(configFile)} (${framework === \"unknown\" ? \"generic\" : framework} template)`\n );\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { existsSync } from \"node:fs\";\nimport { createInterface } from \"node:readline/promises\";\nimport {\n getAdapter,\n getMigrations,\n type MigrationOptions,\n type SqlDialect,\n} from \"@better-media/core\";\nimport { loadProjectConfig } from \"../project-config\";\nimport { migrateWithAdapter } from \"../generators\";\n\nexport function registerMigrateCommand(program: Command): void {\n program\n .command(\"migrate\")\n .description(\"Apply Better Media schema directly to the database (Kysely adapter only)\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .option(\"--mode <mode>\", \"Migration mode (safe|diff|force)\", \"diff\")\n .option(\"-y, --yes\", \"Automatically accept and run migrations without prompting\", false)\n .option(\n \"--dialect <dialect>\",\n \"SQL dialect override (postgres|mysql|sqlite|mssql). Defaults from adapter/config.\",\n undefined\n )\n .action(async (opts: unknown) => {\n const parsed = opts as {\n cwd?: string;\n config?: string;\n mode?: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n y?: boolean;\n yes?: boolean;\n };\n const options = {\n cwd: parsed.cwd ?? process.cwd(),\n config: parsed.config,\n mode: parsed.mode ?? \"diff\",\n dialect: parsed.dialect,\n y: Boolean(parsed.y),\n yes: Boolean(parsed.yes),\n };\n if (![\"safe\", \"diff\", \"force\"].includes(options.mode)) {\n throw new Error(`[media] Invalid --mode \"${String(options.mode)}\". Use safe|diff|force.`);\n }\n if (options.dialect && ![\"postgres\", \"mysql\", \"sqlite\", \"mssql\"].includes(options.dialect)) {\n throw new Error(\n `[media] Invalid --dialect \"${String(options.dialect)}\". Use postgres|mysql|sqlite|mssql.`\n );\n }\n\n const cwd = path.resolve(options.cwd);\n if (!existsSync(cwd)) {\n console.error(`[media] The directory \"${cwd}\" does not exist.`);\n process.exit(1);\n }\n\n const loaded = await loadProjectConfig({ cwd, configPath: options.config });\n const adapter = await getAdapter(loaded.config);\n\n const dialectFromAdapter =\n typeof (adapter as unknown as { __getDialect?: () => SqlDialect }).__getDialect ===\n \"function\"\n ? (adapter as unknown as { __getDialect: () => SqlDialect }).__getDialect()\n : undefined;\n const dialect =\n options.dialect ?? (loaded.config.dialect as SqlDialect | undefined) ?? dialectFromAdapter;\n\n const planned = await getMigrations(adapter, { mode: options.mode, dialect });\n if (!planned.operations.length) {\n console.log(\"No migrations needed.\");\n process.exit(0);\n }\n\n console.log(\"[media] The migration will affect the following:\");\n for (const table of [...planned.toBeCreated, ...planned.toBeAdded]) {\n console.log(\n \"->\",\n chalk.magenta(table.fields.join(\", \")),\n chalk.white(\"fields on\"),\n chalk.yellow(table.table),\n chalk.white(\"table.\")\n );\n }\n\n let shouldMigrate = options.yes ?? false;\n if (!shouldMigrate) {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await rl.question(\"Are you sure you want to run these migrations? (y/N) \");\n rl.close();\n shouldMigrate = /^y(es)?$/i.test(answer.trim());\n }\n\n if (!shouldMigrate) {\n console.log(\"Migration cancelled.\");\n process.exit(0);\n }\n\n try {\n await migrateWithAdapter({ adapter, mode: options.mode, dialect });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (loaded.adapterHint === \"prisma\" || loaded.adapterHint === \"drizzle\") {\n console.error(message);\n process.exit(0);\n }\n throw error;\n }\n console.log(\"Migration completed successfully.\");\n });\n}\n"],"mappings":"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","names":["chalk","path","process","require","path","process","path","fs","program","process","path","path","process","fs","program","chalk","path","process","getAdapter","getMigrations","program","process","path","getAdapter","getMigrations","chalk","process","path","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/project-config.ts","../src/commands/generate.ts","../src/generators/index.ts","../src/generators/drizzle-schema.ts","../src/commands/init.ts","../src/commands/migrate.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { loadProjectConfig } from \"./project-config\";\nimport { registerGenerateCommand } from \"./commands/generate\";\nimport { registerInitCommand } from \"./commands/init\";\nimport { registerMigrateCommand } from \"./commands/migrate\";\n\nconst program = new Command();\n\nprogram.name(\"media\").description(\"CLI for Better Media framework\").version(\"1.0.0\");\n\nregisterInitCommand(program);\n\nregisterGenerateCommand(program);\nregisterMigrateCommand(program);\n\nprogram\n .command(\"config\")\n .description(\"Validate and print resolved module exports (debug)\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .action(async (opts: { cwd: string; config?: string }) => {\n const cwd = path.resolve(opts.cwd);\n const loaded = await loadProjectConfig({ cwd, configPath: opts.config });\n console.log(\n chalk.gray(\"[media] Resolved config:\"),\n JSON.stringify(\n {\n configPath: loaded.configPath,\n adapterHint: loaded.adapterHint,\n dialect: loaded.config.dialect,\n schemaOutput: loaded.config.schemaOutput,\n migrationsDir: loaded.config.migrationsDir,\n },\n null,\n 2\n )\n );\n });\n\nprogram.parse(process.argv);\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createRequire } from \"node:module\";\nimport { randomUUID } from \"node:crypto\";\nimport type { GetAdapterOptions } from \"@better-media/core\";\nimport ts from \"typescript\";\n\nexport type AdapterHint = \"kysely\" | \"prisma\" | \"drizzle\" | \"unknown\";\n\nexport type ProjectConfig = GetAdapterOptions & {\n dialect?: string;\n schemaOutput?: string;\n migrationsDir?: string;\n};\n\nexport type LoadedProjectConfig = {\n configPath: string;\n adapterHint: AdapterHint;\n config: ProjectConfig;\n};\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await fs.access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function detectAdapterHint(cwd: string): Promise<AdapterHint> {\n try {\n const pkgPath = path.join(cwd, \"package.json\");\n const raw = await fs.readFile(pkgPath, \"utf8\");\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n };\n const deps = {\n ...(pkg.dependencies ?? {}),\n ...(pkg.devDependencies ?? {}),\n ...(pkg.peerDependencies ?? {}),\n };\n if (\"kysely\" in deps) return \"kysely\";\n if (\"prisma\" in deps || \"@prisma/client\" in deps) return \"prisma\";\n if (\"drizzle-orm\" in deps) return \"drizzle\";\n return \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction normalizeModuleExport(mod: unknown): unknown {\n if (!mod) return mod;\n const m = mod as Record<string, unknown>;\n return (m.default ?? mod) as unknown;\n}\n\nasync function importJsModule(absPath: string): Promise<unknown> {\n const url = pathToFileURL(absPath).href;\n const mod = await import(url);\n return normalizeModuleExport(mod);\n}\n\nasync function requireTsModule(absPath: string): Promise<unknown> {\n const require = createRequire(import.meta.url);\n\n try {\n const tsNode = require(\"ts-node\") as {\n register: (opts?: {\n transpileOnly?: boolean;\n compilerOptions?: Record<string, unknown>;\n }) => void;\n };\n tsNode.register({\n transpileOnly: true,\n compilerOptions: { module: \"CommonJS\", moduleResolution: \"Node\" },\n });\n } catch {\n // ignore (we'll surface a clearer error below if require fails)\n }\n\n const mod = require(absPath) as unknown;\n return normalizeModuleExport(mod);\n}\n\nasync function importTsModule(absPath: string): Promise<unknown> {\n const source = await fs.readFile(absPath, \"utf8\");\n const transpiled = ts.transpileModule(source, {\n compilerOptions: {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n esModuleInterop: true,\n resolveJsonModule: true,\n },\n fileName: absPath,\n });\n\n // Emit beside source so relative imports keep working.\n const tempPath = path.join(path.dirname(absPath), `.media-config-${randomUUID()}.mjs`);\n await fs.writeFile(tempPath, transpiled.outputText, \"utf8\");\n\n try {\n const mod = await import(pathToFileURL(tempPath).href);\n return normalizeModuleExport(mod);\n } finally {\n await fs.unlink(tempPath).catch(() => undefined);\n }\n}\n\nfunction assertValidConfig(\n value: unknown,\n configPath: string\n): asserts value is Record<string, unknown> {\n if (!value || typeof value !== \"object\") {\n throw new Error(`[media] Config \"${configPath}\" must export an object.`);\n }\n}\n\nconst CONFIG_CANDIDATES = [\n \"media.config.ts\",\n \"media.config.js\",\n \"better-media.config.ts\",\n \"better-media.config.js\",\n] as const;\n\nexport async function loadProjectConfig(options?: {\n cwd?: string;\n configPath?: string;\n}): Promise<LoadedProjectConfig> {\n const cwd = path.resolve(options?.cwd ?? process.cwd());\n\n let configPath = options?.configPath ? path.resolve(cwd, options.configPath) : undefined;\n\n if (configPath && !(await fileExists(configPath))) {\n throw new Error(`[media] Config file not found: ${path.relative(cwd, configPath)}`);\n }\n\n if (!configPath) {\n for (const candidate of CONFIG_CANDIDATES) {\n const abs = path.join(cwd, candidate);\n\n if (await fileExists(abs)) {\n configPath = abs;\n break;\n }\n }\n if (!configPath) {\n throw new Error(\n `[media] No configuration file found. Add one of: ${CONFIG_CANDIDATES.map(\n (c) => `\"${c}\"`\n ).join(\", \")}, or pass --config <path>.`\n );\n }\n }\n\n if (!configPath) {\n throw new Error(\n `[media] No configuration file found. Add one of: ${CONFIG_CANDIDATES.map(\n (c) => `\"${c}\"`\n ).join(\", \")}, or pass --config <path>.`\n );\n }\n\n const adapterHint = await detectAdapterHint(cwd);\n const ext = path.extname(configPath);\n\n let rawConfig: unknown;\n try {\n rawConfig =\n ext === \".ts\" ? await requireTsModule(configPath) : await importJsModule(configPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (ext === \".ts\") {\n try {\n rawConfig = await importTsModule(configPath);\n } catch {\n throw new Error(\n `[media] Failed to load \"${path.basename(\n configPath\n )}\". For TypeScript configs, install \"ts-node\" in your app or use a .js config. Original error: ${msg}`\n );\n }\n } else {\n throw err;\n }\n }\n\n assertValidConfig(rawConfig, configPath);\n\n const cfg = rawConfig as Record<string, unknown>;\n const dialect = typeof cfg.dialect === \"string\" ? (cfg.dialect as string) : undefined;\n const schemaOutput =\n typeof cfg.schemaOutput === \"string\" ? (cfg.schemaOutput as string) : undefined;\n const migrationsDir =\n typeof cfg.migrationsDir === \"string\" ? (cfg.migrationsDir as string) : undefined;\n\n return {\n configPath,\n adapterHint,\n config: {\n database: cfg.database as ProjectConfig[\"database\"],\n createDatabase: cfg.createDatabase as ProjectConfig[\"createDatabase\"],\n dialect,\n schemaOutput,\n migrationsDir,\n },\n };\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { getAdapter, type SqlDialect } from \"@better-media/core\";\nimport { loadProjectConfig } from \"../project-config\";\nimport { generateSchema } from \"../generators\";\n\n/** Default path whose directory is the migrations root (filename unused for output). */\nfunction getDefaultSchemaOutput(): string {\n return \"better-media-migrations/migration.sql\";\n}\n\nexport function registerGenerateCommand(program: Command): void {\n program\n .command(\"generate\")\n .description(\"Generate Better Media database schema for the configured adapter\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .option(\n \"--dialect <dialect>\",\n \"SQL dialect (postgres|mysql|sqlite|mssql). Defaults from adapter/config.\",\n undefined\n )\n .action(async (opts: { cwd: string; config?: string; dialect?: SqlDialect }) => {\n const cwd = path.resolve(opts.cwd);\n const loaded = await loadProjectConfig({ cwd, configPath: opts.config });\n const adapter = await getAdapter(loaded.config);\n\n const dialectFromAdapter =\n typeof (adapter as unknown as { __getDialect?: () => SqlDialect }).__getDialect ===\n \"function\"\n ? (adapter as unknown as { __getDialect: () => SqlDialect }).__getDialect()\n : undefined;\n const dialect =\n opts.dialect ??\n (loaded.config.dialect as SqlDialect | undefined) ??\n dialectFromAdapter ??\n \"postgres\";\n\n const outPath = path.resolve(cwd, loaded.config.schemaOutput ?? getDefaultSchemaOutput());\n await generateSchema({\n cwd,\n adapter,\n outPath,\n dialect,\n options: loaded.config,\n });\n });\n}\n","import path from \"node:path\";\nimport fs from \"fs-extra\";\nimport chalk from \"chalk\";\nimport {\n schema,\n getMigrations,\n MigrationPlanner,\n compileMigrationOperationsSql,\n type SqlDialect,\n type MigrationOptions,\n type TableMetadata,\n applyOperationsToMetadata,\n} from \"@better-media/core\";\nimport type { DatabaseAdapter } from \"@better-media/core\";\nimport { generateDrizzleSchema, dialectToProvider } from \"./drizzle-schema\";\n\ntype CustomSchemaResult = {\n code: string;\n fileName?: string;\n path?: string;\n overwrite?: boolean;\n};\n\ntype AdapterWithExtras = DatabaseAdapter & {\n id?: string;\n createSchema?: (options: unknown, file?: string) => Promise<CustomSchemaResult>;\n};\n\ntype GenerateFn = (args: {\n cwd: string;\n adapter: DatabaseAdapter;\n outPath: string;\n dialect: SqlDialect;\n options?: unknown;\n}) => Promise<void>;\n\ntype MigrateFn = (args: {\n adapter: DatabaseAdapter;\n mode: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n}) => Promise<void>;\n\nfunction resolveMigrationsDir(cwd: string, outPath: string, options: unknown): string {\n const opts = options as { migrationsDir?: string } | undefined;\n if (opts?.migrationsDir && typeof opts.migrationsDir === \"string\") {\n return path.resolve(cwd, opts.migrationsDir);\n }\n return path.dirname(outPath);\n}\n\n/** Subfolders named with numeric timestamps (ms) contain `migration.sql` + `snapshot.json` per run. */\nconst TIMESTAMP_DIR = /^\\d{10,20}$/;\n\nasync function findLatestTimestampRunDir(migrationsDir: string): Promise<string | undefined> {\n if (!(await fs.pathExists(migrationsDir))) return undefined;\n const entries = await fs.readdir(migrationsDir, { withFileTypes: true });\n const names = entries\n .filter((e) => e.isDirectory() && TIMESTAMP_DIR.test(e.name))\n .map((e) => e.name);\n const latest = names[0];\n return latest ? path.join(migrationsDir, latest) : undefined;\n}\n\nasync function resolveSnapshotReadPath(migrationsDir: string): Promise<string | undefined> {\n const latestRun = await findLatestTimestampRunDir(migrationsDir);\n const nested = latestRun ? path.join(latestRun, \"snapshot.json\") : undefined;\n if (nested && (await fs.pathExists(nested))) return nested;\n const legacyRoot = path.join(migrationsDir, \"snapshot.json\");\n if (await fs.pathExists(legacyRoot)) return legacyRoot;\n return undefined;\n}\n\nconst builtInGenerators: Record<string, GenerateFn> = {\n async kysely({ cwd, outPath, dialect, adapter, options }) {\n const migrationsDir = resolveMigrationsDir(cwd, outPath, options);\n await fs.ensureDir(migrationsDir);\n\n let currentTables: TableMetadata[] = [];\n let snapshotLoaded = false;\n\n const snapshotReadPath = await resolveSnapshotReadPath(migrationsDir);\n if (snapshotReadPath) {\n try {\n currentTables = await fs.readJson(snapshotReadPath);\n snapshotLoaded = true;\n } catch {\n console.warn(\n chalk.yellow(\n `[media] Failed to load snapshot at ${snapshotReadPath}, falling back to DB introspection.`\n )\n );\n }\n }\n\n if (!snapshotLoaded) {\n if (typeof (adapter as { __getMetadata?: unknown }).__getMetadata === \"function\") {\n currentTables = await (\n adapter as unknown as { __getMetadata: () => Promise<TableMetadata[]> }\n ).__getMetadata();\n }\n }\n\n const planner = new MigrationPlanner(dialect);\n const plannedOperations = planner.plan(schema, currentTables);\n\n if (plannedOperations.length === 0) {\n console.log(\n chalk.blue(`[media] No changes detected. Database/Snapshot is already up to date.`)\n );\n return;\n }\n\n const sql = compileMigrationOperationsSql({ operations: plannedOperations, dialect });\n\n const nextMetadata = applyOperationsToMetadata(currentTables, plannedOperations, dialect);\n const runTs = Date.now();\n const runDir = path.join(migrationsDir, String(runTs));\n await fs.ensureDir(runDir);\n\n const snapshotWritePath = path.join(runDir, \"snapshot.json\");\n await fs.writeJson(snapshotWritePath, nextMetadata, { spaces: 2 });\n\n const migrationFile = path.join(runDir, \"migration.sql\");\n await fs.writeFile(migrationFile, sql, \"utf8\");\n console.log(chalk.green(`[media] Generated migration at ${path.relative(cwd, migrationFile)}`));\n },\n async postgres(args) {\n const kysely = builtInGenerators.kysely;\n if (!kysely) throw new Error(\"Kysely generator not found\");\n await kysely(args);\n },\n async prisma() {\n throw new Error(\n '[media] Prisma schema generator is not implemented yet. Run \"npx better-media generate\" with Kysely, then apply via Prisma migrate/push.'\n );\n },\n async drizzle({ cwd, outPath, dialect }) {\n const provider = dialectToProvider(dialect);\n const code = generateDrizzleSchema(schema, dialect);\n\n // Default output: better-media/drizzle-schema.ts (next to where SQL would go)\n const defaultTs = path.join(path.dirname(outPath), `drizzle-schema.${provider}.ts`);\n const resolvedOut = outPath.endsWith(\".ts\") ? outPath : defaultTs;\n\n await fs.ensureDir(path.dirname(resolvedOut));\n await fs.writeFile(resolvedOut, code, \"utf8\");\n console.log(\n chalk.green(`[media] Generated Drizzle schema at ${path.relative(cwd, resolvedOut)}`)\n );\n console.log(\n chalk.gray(`[media] Next: run \"npx drizzle-kit generate\" then \"npx drizzle-kit migrate\"`)\n );\n },\n};\n\nconst builtInMigrators: Record<string, MigrateFn> = {\n async kysely({ mode, dialect, adapter }) {\n const hasPlannedMigration =\n typeof (adapter as { __getMetadata?: unknown }).__getMetadata === \"function\" &&\n typeof (adapter as { __executeMigration?: unknown }).__executeMigration === \"function\";\n\n if (!hasPlannedMigration) {\n throw new Error(\n `[media] This adapter does not support direct CLI migrations. ` +\n `Use \"media generate\" and apply via your ORM migration tool.`\n );\n }\n const planned = await getMigrations(adapter, { mode, dialect });\n await planned.runMigrations();\n },\n async postgres(args) {\n const kysely = builtInMigrators.kysely;\n if (!kysely) throw new Error(\"Kysely migrator not found\");\n await kysely(args);\n },\n async prisma() {\n throw new Error(\n '[media] The migrate command only works with the built-in Kysely adapter. For Prisma, run \"npx better-media generate\" and apply with Prisma migrate/push.'\n );\n },\n async drizzle() {\n throw new Error(\n '[media] The migrate command only works with the built-in Kysely adapter. For Drizzle, run \"npx better-media generate\" and apply with Drizzle migrate/push.'\n );\n },\n};\n\nexport async function generateSchema(args: {\n cwd: string;\n adapter: DatabaseAdapter;\n outPath: string;\n dialect: SqlDialect;\n options?: unknown;\n}): Promise<void> {\n const adapterEx = args.adapter as AdapterWithExtras;\n const id = adapterEx.id;\n\n if (id && id in builtInGenerators) {\n await builtInGenerators[id]!(args);\n return;\n }\n\n if (typeof adapterEx.createSchema === \"function\") {\n const generated = await adapterEx.createSchema(args.options, args.outPath);\n const targetPath = generated.fileName ?? generated.path ?? args.outPath;\n const overwrite = generated.overwrite ?? true;\n if (!overwrite && (await fs.pathExists(targetPath))) {\n throw new Error(`[media] Refusing to overwrite existing file: ${targetPath}`);\n }\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, generated.code, \"utf8\");\n console.log(chalk.green(`[media] Generated schema at ${path.relative(args.cwd, targetPath)}`));\n return;\n }\n\n throw new Error(\n `[media] ${id ?? \"adapter\"} is not supported. If it is a custom adapter, implement createSchema(options, file).`\n );\n}\n\nexport async function migrateWithAdapter(args: {\n adapter: DatabaseAdapter;\n mode: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n}): Promise<void> {\n const adapterEx = args.adapter as AdapterWithExtras;\n const id = adapterEx.id;\n\n if (id && id in builtInMigrators) {\n await builtInMigrators[id]!(args);\n return;\n }\n\n if (\n typeof (args.adapter as { __getMetadata?: unknown }).__getMetadata === \"function\" &&\n typeof (args.adapter as { __executeMigration?: unknown }).__executeMigration === \"function\"\n ) {\n const kysely = builtInMigrators.kysely;\n if (!kysely) throw new Error(\"Kysely migrator not found\");\n await kysely(args);\n return;\n }\n\n throw new Error(`[media] Direct migrations are not supported for adapter \"${id ?? \"unknown\"}\".`);\n}\n","import type { BmSchema, FieldDefinition, SqlDialect } from \"@better-media/core\";\n\ntype DrizzleProvider = \"pg\" | \"mysql\" | \"sqlite\";\n\nexport function dialectToProvider(dialect: SqlDialect): DrizzleProvider {\n if (dialect === \"postgres\") return \"pg\";\n if (dialect === \"mysql\") return \"mysql\";\n return \"sqlite\";\n}\n\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\nfunction modelVarName(modelName: string): string {\n return snakeToCamel(modelName);\n}\n\nfunction indexName(tableName: string, fields: string[]): string {\n return `idx_${tableName}_${fields.map(camelToSnake).join(\"_\")}`;\n}\n\n// ─── column type per provider ────────────────────────────────────────────────\n\nfunction pgColFn(fieldName: string, field: FieldDefinition): string {\n const col = camelToSnake(fieldName);\n switch (field.type) {\n case \"number\":\n return `integer(\"${col}\")`;\n case \"boolean\":\n return `boolean(\"${col}\")`;\n case \"date\":\n return `timestamp(\"${col}\", { mode: \"date\" })`;\n case \"json\":\n return `jsonb(\"${col}\")`;\n default:\n return `text(\"${col}\")`;\n }\n}\n\nfunction mysqlColFn(fieldName: string, field: FieldDefinition): string {\n const col = camelToSnake(fieldName);\n switch (field.type) {\n case \"number\":\n return `int(\"${col}\")`;\n case \"boolean\":\n return `boolean(\"${col}\")`;\n case \"date\":\n return `datetime(\"${col}\", { mode: \"date\" })`;\n case \"json\":\n return `json(\"${col}\")`;\n default:\n return `text(\"${col}\")`;\n }\n}\n\nfunction sqliteColFn(fieldName: string, field: FieldDefinition): string {\n const col = camelToSnake(fieldName);\n switch (field.type) {\n case \"number\":\n return `integer(\"${col}\")`;\n case \"boolean\":\n return `integer(\"${col}\", { mode: \"boolean\" })`;\n case \"date\":\n return `integer(\"${col}\", { mode: \"timestamp\" })`;\n case \"json\":\n return `text(\"${col}\", { mode: \"json\" })`;\n default:\n return `text(\"${col}\")`;\n }\n}\n\nfunction getColFn(fieldName: string, field: FieldDefinition, provider: DrizzleProvider): string {\n switch (provider) {\n case \"pg\":\n return pgColFn(fieldName, field);\n case \"mysql\":\n return mysqlColFn(fieldName, field);\n case \"sqlite\":\n return sqliteColFn(fieldName, field);\n }\n}\n\n// ─── chain modifiers ─────────────────────────────────────────────────────────\n\nfunction buildColChain(\n fieldName: string,\n field: FieldDefinition,\n provider: DrizzleProvider\n): string {\n let chain = getColFn(fieldName, field, provider);\n if (field.primaryKey) chain += \".primaryKey()\";\n if (field.required && !field.primaryKey) chain += \".notNull()\";\n if (field.unique && !field.primaryKey) chain += \".unique()\";\n if (field.references) {\n const refVar = modelVarName(field.references.model);\n const onDelete = field.references.onDelete ?? \"cascade\";\n chain += `.references(() => ${refVar}.${field.references.field}, { onDelete: \"${onDelete}\" })`;\n }\n return chain;\n}\n\n// ─── imports ─────────────────────────────────────────────────────────────────\n\nfunction collectImports(\n schema: BmSchema,\n provider: DrizzleProvider\n): { modulePath: string; names: string[] } {\n const names = new Set<string>();\n\n switch (provider) {\n case \"pg\":\n names.add(\"pgTable\");\n break;\n case \"mysql\":\n names.add(\"mysqlTable\");\n break;\n case \"sqlite\":\n names.add(\"sqliteTable\");\n break;\n }\n\n for (const model of Object.values(schema)) {\n for (const field of Object.values(model.fields)) {\n switch (provider) {\n case \"pg\":\n if (field.type === \"number\") names.add(\"integer\");\n else if (field.type === \"boolean\") names.add(\"boolean\");\n else if (field.type === \"date\") names.add(\"timestamp\");\n else if (field.type === \"json\") names.add(\"jsonb\");\n else names.add(\"text\");\n break;\n case \"mysql\":\n if (field.type === \"number\") names.add(\"int\");\n else if (field.type === \"boolean\") names.add(\"boolean\");\n else if (field.type === \"date\") names.add(\"datetime\");\n else if (field.type === \"json\") names.add(\"json\");\n else names.add(\"text\");\n break;\n case \"sqlite\":\n if (field.type === \"string\" || field.type === \"json\") names.add(\"text\");\n else names.add(\"integer\");\n break;\n }\n }\n\n if (model.indexes && model.indexes.length > 0) {\n for (const idx of model.indexes) {\n if (idx.unique && idx.fields.length > 1) names.add(\"uniqueIndex\");\n else if (!idx.unique) names.add(\"index\");\n }\n }\n }\n\n const modulePath =\n provider === \"pg\"\n ? \"drizzle-orm/pg-core\"\n : provider === \"mysql\"\n ? \"drizzle-orm/mysql-core\"\n : \"drizzle-orm/sqlite-core\";\n\n return { modulePath, names: [...names].sort() };\n}\n\n// ─── topological sort ────────────────────────────────────────────────────────\n\nfunction topoSort(schema: BmSchema): string[] {\n const deps: Record<string, Set<string>> = {};\n for (const [name, model] of Object.entries(schema)) {\n deps[name] = new Set();\n for (const field of Object.values(model.fields)) {\n if (field.references) deps[name]!.add(field.references.model);\n }\n }\n\n const sorted: string[] = [];\n const visited = new Set<string>();\n\n function visit(name: string) {\n if (visited.has(name)) return;\n visited.add(name);\n for (const dep of deps[name] ?? []) visit(dep);\n sorted.push(name);\n }\n\n for (const name of Object.keys(schema)) visit(name);\n return sorted;\n}\n\n// ─── table codegen ───────────────────────────────────────────────────────────\n\nfunction tableFactoryName(provider: DrizzleProvider): string {\n return provider === \"pg\" ? \"pgTable\" : provider === \"mysql\" ? \"mysqlTable\" : \"sqliteTable\";\n}\n\nfunction generateTable(\n modelName: string,\n model: BmSchema[string],\n provider: DrizzleProvider\n): string {\n const varName = modelVarName(modelName);\n const factory = tableFactoryName(provider);\n const lines: string[] = [];\n\n for (const [fieldName, field] of Object.entries(model.fields)) {\n lines.push(` ${fieldName}: ${buildColChain(fieldName, field, provider)},`);\n }\n\n // Composite indexes in the third argument (single-field unique already handled inline)\n const compositeIndexes =\n model.indexes?.filter(\n (idx) => idx.fields.length > 1 || (idx.fields.length === 1 && !idx.unique)\n ) ?? [];\n\n if (compositeIndexes.length === 0) {\n return `export const ${varName} = ${factory}(\"${modelName}\", {\\n${lines.join(\"\\n\")}\\n});`;\n }\n\n const idxLines = compositeIndexes.map((idx) => {\n const cols = idx.fields.map((f) => `t.${f}`).join(\", \");\n const name = indexName(modelName, idx.fields);\n return idx.unique ? ` uniqueIndex(\"${name}\").on(${cols}),` : ` index(\"${name}\").on(${cols}),`;\n });\n\n return `export const ${varName} = ${factory}(\"${modelName}\", {\\n${lines.join(\"\\n\")}\\n}, (t) => [\\n${idxLines.join(\"\\n\")}\\n]);`;\n}\n\n// ─── public API ──────────────────────────────────────────────────────────────\n\nexport function generateDrizzleSchema(schema: BmSchema, dialect: SqlDialect): string {\n const provider = dialectToProvider(dialect);\n const { modulePath, names } = collectImports(schema, provider);\n const order = topoSort(schema);\n\n const header = [\n `// Auto-generated by @better-media/cli — do not edit directly.`,\n `// Run \"npx better-media generate --dialect ${dialect}\" to regenerate.`,\n `// After editing, run \"npx drizzle-kit generate\" then \"npx drizzle-kit migrate\".`,\n ``,\n `import { ${names.join(\", \")} } from \"${modulePath}\";`,\n ``,\n ].join(\"\\n\");\n\n const tables = order\n .map((name) => {\n const model = schema[name];\n if (!model) return \"\";\n return generateTable(name, model, provider);\n })\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n return header + tables + \"\\n\";\n}\n","import { Command } from \"commander\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport fs from \"fs-extra\";\n\ntype DetectedFramework = \"express\" | \"nestjs\" | \"unknown\";\n\nfunction detectFramework(pkg: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}): DetectedFramework {\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n if (\"@nestjs/core\" in deps || \"@nestjs/common\" in deps) return \"nestjs\";\n if (\"express\" in deps) return \"express\";\n return \"unknown\";\n}\n\nfunction inferExtension(cwd: string, framework: DetectedFramework, pkgType?: string): \"ts\" | \"js\" {\n if (framework === \"nestjs\") return \"ts\";\n if (pkgType === \"module\") return \"js\";\n return \"ts\";\n}\n\nfunction buildConfigContent(ext: \"ts\" | \"js\"): string {\n const importPool = ext === \"ts\" ? 'import { Pool } from \"pg\";' : 'import { Pool } from \"pg\";';\n return `${importPool}\n\nexport const mediaOptions = {\n database: new Pool({\n connectionString:\n process.env.DATABASE_URL ?? \"postgres://postgres:postgres@localhost:5432/better_media\",\n }),\n dialect: \"postgres\",\n migrationsDir: \"better-media\",\n};\n\nexport default mediaOptions;\n`;\n}\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .description(\"Generate media.config.ts/js based on detected framework\")\n .option(\"-C, --cwd <path>\", \"Working directory\", process.cwd())\n .option(\"-f, --force\", \"Overwrite existing config file\", false)\n .action(async (opts: { cwd: string; force?: boolean }) => {\n const cwd = path.resolve(opts.cwd);\n const pkgPath = path.join(cwd, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) {\n throw new Error(`[media] No package.json found in ${cwd}`);\n }\n\n const pkg = (await fs.readJson(pkgPath)) as {\n type?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const framework = detectFramework(pkg);\n const ext = inferExtension(cwd, framework, pkg.type);\n const configFile = path.join(cwd, `media.config.${ext}`);\n\n if ((await fs.pathExists(configFile)) && !opts.force) {\n throw new Error(\n `[media] ${path.basename(configFile)} already exists. Re-run with --force to overwrite.`\n );\n }\n\n const content = buildConfigContent(ext);\n await fs.writeFile(configFile, content, \"utf8\");\n\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n if (!(\"pg\" in deps)) {\n console.warn('[media] Added config uses \"pg\". Install it with: pnpm add pg');\n }\n\n console.log(\n `[media] Created ${path.basename(configFile)} (${framework === \"unknown\" ? \"generic\" : framework} template)`\n );\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { existsSync } from \"node:fs\";\nimport { createInterface } from \"node:readline/promises\";\nimport {\n getAdapter,\n getMigrations,\n type MigrationOptions,\n type SqlDialect,\n} from \"@better-media/core\";\nimport { loadProjectConfig } from \"../project-config\";\nimport { migrateWithAdapter } from \"../generators\";\n\nexport function registerMigrateCommand(program: Command): void {\n program\n .command(\"migrate\")\n .description(\"Apply Better Media schema directly to the database (Kysely adapter only)\")\n .option(\"-C, --cwd <path>\", \"Working directory to resolve config from\", process.cwd())\n .option(\"--config <path>\", \"Path to media config file\")\n .option(\"--mode <mode>\", \"Migration mode (safe|diff|force)\", \"diff\")\n .option(\"-y, --yes\", \"Automatically accept and run migrations without prompting\", false)\n .option(\n \"--dialect <dialect>\",\n \"SQL dialect override (postgres|mysql|sqlite|mssql). Defaults from adapter/config.\",\n undefined\n )\n .action(async (opts: unknown) => {\n const parsed = opts as {\n cwd?: string;\n config?: string;\n mode?: MigrationOptions[\"mode\"];\n dialect?: SqlDialect;\n y?: boolean;\n yes?: boolean;\n };\n const options = {\n cwd: parsed.cwd ?? process.cwd(),\n config: parsed.config,\n mode: parsed.mode ?? \"diff\",\n dialect: parsed.dialect,\n y: Boolean(parsed.y),\n yes: Boolean(parsed.yes),\n };\n if (![\"safe\", \"diff\", \"force\"].includes(options.mode)) {\n throw new Error(`[media] Invalid --mode \"${String(options.mode)}\". Use safe|diff|force.`);\n }\n if (options.dialect && ![\"postgres\", \"mysql\", \"sqlite\", \"mssql\"].includes(options.dialect)) {\n throw new Error(\n `[media] Invalid --dialect \"${String(options.dialect)}\". Use postgres|mysql|sqlite|mssql.`\n );\n }\n\n const cwd = path.resolve(options.cwd);\n if (!existsSync(cwd)) {\n console.error(`[media] The directory \"${cwd}\" does not exist.`);\n process.exit(1);\n }\n\n const loaded = await loadProjectConfig({ cwd, configPath: options.config });\n const adapter = await getAdapter(loaded.config);\n\n const dialectFromAdapter =\n typeof (adapter as unknown as { __getDialect?: () => SqlDialect }).__getDialect ===\n \"function\"\n ? (adapter as unknown as { __getDialect: () => SqlDialect }).__getDialect()\n : undefined;\n const dialect =\n options.dialect ?? (loaded.config.dialect as SqlDialect | undefined) ?? dialectFromAdapter;\n\n const planned = await getMigrations(adapter, { mode: options.mode, dialect });\n if (!planned.operations.length) {\n console.log(\"No migrations needed.\");\n process.exit(0);\n }\n\n console.log(\"[media] The migration will affect the following:\");\n for (const table of [...planned.toBeCreated, ...planned.toBeAdded]) {\n console.log(\n \"->\",\n chalk.magenta(table.fields.join(\", \")),\n chalk.white(\"fields on\"),\n chalk.yellow(table.table),\n chalk.white(\"table.\")\n );\n }\n\n let shouldMigrate = options.yes ?? false;\n if (!shouldMigrate) {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await rl.question(\"Are you sure you want to run these migrations? (y/N) \");\n rl.close();\n shouldMigrate = /^y(es)?$/i.test(answer.trim());\n }\n\n if (!shouldMigrate) {\n console.log(\"Migration cancelled.\");\n process.exit(0);\n }\n\n try {\n await migrateWithAdapter({ adapter, mode: options.mode, dialect });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (loaded.adapterHint === \"prisma\" || loaded.adapterHint === \"drizzle\") {\n console.error(message);\n process.exit(0);\n }\n throw error;\n }\n console.log(\"Migration completed successfully.\");\n });\n}\n"],"mappings":"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","names":["chalk","path","process","require","path","process","path","fs","schema","path","fs","program","process","path","path","process","fs","program","chalk","path","process","getAdapter","getMigrations","program","process","path","getAdapter","getMigrations","chalk","process","path","chalk"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-media/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Abenezer Atnafu",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"fs-extra": "^11.2.0",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
32
|
"ts-node": "^10.9.2",
|
|
33
|
-
"@better-media/core": "0.
|
|
33
|
+
"@better-media/core": "0.8.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/fs-extra": "^11.0.4",
|