pecunia-cli 0.2.2 → 0.2.3
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/api.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as generateKyselySchema, n as generateSchema, o as generateDrizzleSchema, r as generatePrismaSchema, t as adapters } from "./generators-
|
|
1
|
+
import { a as generateKyselySchema, n as generateSchema, o as generateDrizzleSchema, r as generatePrismaSchema, t as adapters } from "./generators-CMgruX4S.mjs";
|
|
2
2
|
|
|
3
3
|
export { adapters, generateDrizzleSchema, generateKyselySchema, generatePrismaSchema, generateSchema };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs, { existsSync } from "node:fs";
|
|
1
|
+
import fs, { existsSync, statSync } from "node:fs";
|
|
2
2
|
import fs$1 from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { getMigrations, getPaymentTables } from "pecunia-root";
|
|
@@ -306,6 +306,101 @@ CREATE TRIGGER ${triggerName}
|
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
+
//#endregion
|
|
310
|
+
//#region src/utils/drizzle-migrations.ts
|
|
311
|
+
/**
|
|
312
|
+
* Find or create the Drizzle migrations directory.
|
|
313
|
+
* Never places migrations under src/ to avoid drizzle-kit crashes.
|
|
314
|
+
*
|
|
315
|
+
* @param projectRoot - The project root directory (where package.json typically lives)
|
|
316
|
+
* @returns The path to the drizzle migrations directory
|
|
317
|
+
*/
|
|
318
|
+
async function getDrizzleMigrationsDir(projectRoot) {
|
|
319
|
+
const drizzleDir = path.resolve(projectRoot, "drizzle");
|
|
320
|
+
if (existsSync(drizzleDir)) {
|
|
321
|
+
if (!statSync(drizzleDir).isDirectory()) throw new Error(`"drizzle" exists but is not a directory. Please remove it or rename it.`);
|
|
322
|
+
return drizzleDir;
|
|
323
|
+
}
|
|
324
|
+
await fs$1.mkdir(drizzleDir, { recursive: true });
|
|
325
|
+
return drizzleDir;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Find existing invariants migration file if it exists.
|
|
329
|
+
*
|
|
330
|
+
* @param migrationsDir - Path to the drizzle migrations directory
|
|
331
|
+
* @returns The migration number if found, or null
|
|
332
|
+
*/
|
|
333
|
+
async function findExistingInvariantsMigration(migrationsDir) {
|
|
334
|
+
if (!existsSync(migrationsDir)) return null;
|
|
335
|
+
const invariantsFile = (await fs$1.readdir(migrationsDir)).find((file) => file.endsWith("_pecunia_invariants.sql") && /^\d{4}_/.test(file));
|
|
336
|
+
if (!invariantsFile) return null;
|
|
337
|
+
const match = invariantsFile.match(/^(\d{4})_/);
|
|
338
|
+
return match ? match[1] : null;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Determine the next migration number by scanning existing migration files.
|
|
342
|
+
* Migration files are expected to follow the pattern: `NNNN_description.sql`
|
|
343
|
+
* where NNNN is a 4-digit number.
|
|
344
|
+
*
|
|
345
|
+
* @param migrationsDir - Path to the drizzle migrations directory
|
|
346
|
+
* @returns The next migration number (4-digit string, e.g., "0001")
|
|
347
|
+
*/
|
|
348
|
+
async function getNextMigrationNumber(migrationsDir) {
|
|
349
|
+
const existingInvariantsNumber = await findExistingInvariantsMigration(migrationsDir);
|
|
350
|
+
if (existingInvariantsNumber) return existingInvariantsNumber;
|
|
351
|
+
if (!existsSync(migrationsDir)) return "0001";
|
|
352
|
+
const migrationFiles = (await fs$1.readdir(migrationsDir)).filter((file) => file.endsWith(".sql") && /^\d{4}_/.test(file));
|
|
353
|
+
if (migrationFiles.length === 0) return "0001";
|
|
354
|
+
const numbers = migrationFiles.map((file) => {
|
|
355
|
+
const match = file.match(/^(\d{4})_/);
|
|
356
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
357
|
+
}).filter((n) => n > 0);
|
|
358
|
+
if (numbers.length === 0) return "0001";
|
|
359
|
+
const nextNumber = Math.max(...numbers) + 1;
|
|
360
|
+
if (nextNumber >= 9999) return "9999";
|
|
361
|
+
return String(nextNumber).padStart(4, "0");
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Get the path for the invariants migration file.
|
|
365
|
+
* Uses a deterministic name based on migration number to ensure it runs after
|
|
366
|
+
* base table creation migrations.
|
|
367
|
+
*
|
|
368
|
+
* @param migrationsDir - Path to the drizzle migrations directory
|
|
369
|
+
* @param migrationNumber - The migration number to use (4-digit string)
|
|
370
|
+
* @returns The full path to the invariants migration file
|
|
371
|
+
*/
|
|
372
|
+
function getInvariantsMigrationPath(migrationsDir, migrationNumber) {
|
|
373
|
+
return path.join(migrationsDir, `${migrationNumber}_pecunia_invariants.sql`);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Write the invariants SQL file to the drizzle migrations directory.
|
|
377
|
+
* Handles idempotency by checking if the file exists and has the same content.
|
|
378
|
+
*
|
|
379
|
+
* @param projectRoot - The project root directory
|
|
380
|
+
* @param sqlContent - The SQL content to write
|
|
381
|
+
* @returns The path to the written file, or null if no changes were needed
|
|
382
|
+
*/
|
|
383
|
+
async function writeInvariantsMigration(projectRoot, sqlContent) {
|
|
384
|
+
const migrationsDir = await getDrizzleMigrationsDir(projectRoot);
|
|
385
|
+
const migrationPath = getInvariantsMigrationPath(migrationsDir, await getNextMigrationNumber(migrationsDir));
|
|
386
|
+
let created = false;
|
|
387
|
+
let updated = false;
|
|
388
|
+
if (existsSync(migrationPath)) {
|
|
389
|
+
if (await fs$1.readFile(migrationPath, "utf-8") === sqlContent) return {
|
|
390
|
+
path: migrationPath,
|
|
391
|
+
created: false,
|
|
392
|
+
updated: false
|
|
393
|
+
};
|
|
394
|
+
updated = true;
|
|
395
|
+
} else created = true;
|
|
396
|
+
await fs$1.writeFile(migrationPath, sqlContent, "utf-8");
|
|
397
|
+
return {
|
|
398
|
+
path: migrationPath,
|
|
399
|
+
created,
|
|
400
|
+
updated
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
309
404
|
//#endregion
|
|
310
405
|
//#region src/generators/drizzle.ts
|
|
311
406
|
function convertToSnakeCase(str, camelCase) {
|
|
@@ -314,10 +409,14 @@ function convertToSnakeCase(str, camelCase) {
|
|
|
314
409
|
}
|
|
315
410
|
const generateDrizzleSchema = async ({ options, file, adapter }) => {
|
|
316
411
|
const tables = getPaymentTables$1(options);
|
|
317
|
-
const filePath = file || "./
|
|
412
|
+
const filePath = file || "./src/db/schema.ts";
|
|
318
413
|
const databaseType = adapter.options?.provider;
|
|
414
|
+
const projectRoot = process.cwd();
|
|
319
415
|
if (!databaseType) throw new Error("Database provider type is undefined during Drizzle schema generation. Please define a `provider` in the Drizzle adapter config.");
|
|
320
|
-
const
|
|
416
|
+
const resolvedSchemaPath = path.isAbsolute(filePath) ? filePath : path.resolve(projectRoot, filePath);
|
|
417
|
+
const schemaDir = path.dirname(resolvedSchemaPath);
|
|
418
|
+
if (!existsSync(schemaDir)) await fs$1.mkdir(schemaDir, { recursive: true });
|
|
419
|
+
const fileExist = existsSync(resolvedSchemaPath);
|
|
321
420
|
let code = generateImport({
|
|
322
421
|
databaseType,
|
|
323
422
|
tables,
|
|
@@ -646,19 +745,17 @@ const generateDrizzleSchema = async ({ options, file, adapter }) => {
|
|
|
646
745
|
if (typeHints) code += `\n\n${typeHints}`;
|
|
647
746
|
const formattedCode = await prettier.format(code, { parser: "typescript" });
|
|
648
747
|
if (databaseType === "pg") {
|
|
649
|
-
const
|
|
748
|
+
const result = await writeInvariantsMigration(projectRoot, emitPostgresInvariantSql(normalizeInvariants(tables, {
|
|
650
749
|
getModelName,
|
|
651
750
|
getFieldName
|
|
652
|
-
}), "public");
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
await fs$1.writeFile(path.resolve(process.cwd(), sqlFilePath), sql);
|
|
657
|
-
console.log(`📝 Generated invariant SQL: ${sqlFilePath}`);
|
|
751
|
+
}), "public"));
|
|
752
|
+
if (result.created) console.log(`Generated invariants migration: ${path.relative(projectRoot, result.path)}\nNote: Created ./drizzle directory. Invariants SQL is placed in Drizzle migrations.`);
|
|
753
|
+
else if (result.updated) console.log(`Updated invariants migration: ${path.relative(projectRoot, result.path)}`);
|
|
754
|
+
else console.log(`Invariants migration up to date: ${path.relative(projectRoot, result.path)}`);
|
|
658
755
|
}
|
|
659
756
|
return {
|
|
660
757
|
code: formattedCode,
|
|
661
|
-
fileName:
|
|
758
|
+
fileName: path.relative(projectRoot, resolvedSchemaPath),
|
|
662
759
|
overwrite: fileExist
|
|
663
760
|
};
|
|
664
761
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as getPackageInfo, n as generateSchema } from "./generators-
|
|
2
|
+
import { i as getPackageInfo, n as generateSchema } from "./generators-CMgruX4S.mjs";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import fs, { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
import fs$1 from "node:fs/promises";
|