@alpha.consultings/eloquent-orm.js 1.1.0 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [1.1.1](https://github.com/MetalDz/Eloquent-ORM.js/compare/v1.1.0...v1.1.1) (2026-04-05)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * use descriptive helper migration names for pivots and indexes ([13baedc](https://github.com/MetalDz/Eloquent-ORM.js/commit/13baedc78296de7c22e8f2ab1834411a738957d7))
7
+ * use descriptive helper migration names for pivots and indexes ([7faeb4c](https://github.com/MetalDz/Eloquent-ORM.js/commit/7faeb4cf736c5c4f50429204c70713bb167cd5a9))
8
+
1
9
  # [1.1.0](https://github.com/MetalDz/Eloquent-ORM.js/compare/v1.0.11...v1.1.0) (2026-04-04)
2
10
 
3
11
 
@@ -1,6 +1,6 @@
1
1
  # Package Update Summary
2
2
 
3
- Version: `1.1.0`
3
+ Version: `1.1.1`
4
4
 
5
5
  This file is the source of truth for the release-focused quick info block that appears in `README.md`.
6
6
 
@@ -14,22 +14,22 @@ npm run docs:sync-package-metadata
14
14
 
15
15
  <!-- release-lineup:start -->
16
16
  Latest Release:
17
- - `v1.0.11 latest`
17
+ - `v1.1.1 latest`
18
18
 
19
19
  Old Release:
20
- - `v1.0.10`
20
+ - `v1.0.11`
21
21
  <!-- release-lineup:end -->
22
22
 
23
23
  ## Latest Release Headline
24
24
 
25
25
  <!-- latest-package-headline:start -->
26
- - Minor release. The ORM now supports model-declared relational DDL metadata and safe PostgreSQL smart-update diffs that preserve unmanaged foreign keys.
26
+ - Fix release. Migration helpers now use descriptive pivot and table-scoped index filenames instead of a generic `create_pivot_table` fallback.
27
27
  <!-- latest-package-headline:end -->
28
28
 
29
29
  ## Latest Release Summary
30
30
 
31
31
  <!-- latest-package-update:start -->
32
- - Add first-class model `database` metadata for foreign keys and indexes, emit relational DDL from the model source of truth, preserve unmanaged PostgreSQL foreign keys during smart-update diffs, keep the source-tree TypeScript contract on NodeNext while `dist/*` stays CommonJS, and restore `100%` statement, branch, function, and line coverage.
32
+ - Keep the relational DDL and safe-diff model contract from `1.1.0`, fix migration helper generation so real `belongsToMany` pivots emit descriptive `create_<pivotTable>_table` files, group relational index helpers into table-scoped `add_<table>_indexes` migrations instead of a generic `create_pivot_table` fallback, and preserve the clean NodeNext source-tree, CommonJS `dist/*` build, and `100%` coverage baseline.
33
33
  <!-- latest-package-update:end -->
34
34
 
35
35
  ## Synced Quick Info
@@ -37,11 +37,11 @@ Old Release:
37
37
  <!-- package-quick-info:start -->
38
38
  Quick info:
39
39
  - Package: `@alpha.consultings/eloquent-orm.js`
40
- - Version: `v1.1.0`
41
- - Latest release: `v1.0.11 latest`
42
- - What's new: [Minor release. The ORM now supports model-declared relational DDL metadata and safe PostgreSQL smart-update diffs that preserve unmanaged foreign keys.](https://alphaconsultings.mintlify.app/release/latest-release-summary)
43
- - Old release: `v1.0.10`
44
- - Latest update: Add first-class model `database` metadata for foreign keys and indexes, emit relational DDL from the model source of truth, preserve unmanaged PostgreSQL foreign keys during smart-update diffs, keep the source-tree TypeScript contract on NodeNext while `dist/*` stays CommonJS, and restore `100%` statement, branch, function, and line coverage.
40
+ - Version: `v1.1.1`
41
+ - Latest release: `v1.1.1 latest`
42
+ - What's new: [Fix release. Migration helpers now use descriptive pivot and table-scoped index filenames instead of a generic `create_pivot_table` fallback.](https://alphaconsultings.mintlify.app/release/latest-release-summary)
43
+ - Old release: `v1.0.11`
44
+ - Latest update: Keep the relational DDL and safe-diff model contract from `1.1.0`, fix migration helper generation so real `belongsToMany` pivots emit descriptive `create_<pivotTable>_table` files, group relational index helpers into table-scoped `add_<table>_indexes` migrations instead of a generic `create_pivot_table` fallback, and preserve the clean NodeNext source-tree, CommonJS `dist/*` build, and `100%` coverage baseline.
45
45
  - Official docs: https://alphaconsultings.mintlify.app
46
46
  - Quick start: https://alphaconsultings.mintlify.app/getting-started/quick-start
47
47
  - Release history: https://alphaconsultings.mintlify.app/release/history
package/README.md CHANGED
@@ -17,11 +17,11 @@ Laravel-inspired ORM + CLI for Node.js + TypeScript with SQL and MongoDB runtime
17
17
  <!-- package-quick-info:start -->
18
18
  Quick info:
19
19
  - Package: `@alpha.consultings/eloquent-orm.js`
20
- - Version: `v1.1.0`
21
- - Latest release: `v1.0.11 latest`
22
- - What's new: [Minor release. The ORM now supports model-declared relational DDL metadata and safe PostgreSQL smart-update diffs that preserve unmanaged foreign keys.](https://alphaconsultings.mintlify.app/release/latest-release-summary)
23
- - Old release: `v1.0.10`
24
- - Latest update: Add first-class model `database` metadata for foreign keys and indexes, emit relational DDL from the model source of truth, preserve unmanaged PostgreSQL foreign keys during smart-update diffs, keep the source-tree TypeScript contract on NodeNext while `dist/*` stays CommonJS, and restore `100%` statement, branch, function, and line coverage.
20
+ - Version: `v1.1.1`
21
+ - Latest release: `v1.1.1 latest`
22
+ - What's new: [Fix release. Migration helpers now use descriptive pivot and table-scoped index filenames instead of a generic `create_pivot_table` fallback.](https://alphaconsultings.mintlify.app/release/latest-release-summary)
23
+ - Old release: `v1.0.11`
24
+ - Latest update: Keep the relational DDL and safe-diff model contract from `1.1.0`, fix migration helper generation so real `belongsToMany` pivots emit descriptive `create_<pivotTable>_table` files, group relational index helpers into table-scoped `add_<table>_indexes` migrations instead of a generic `create_pivot_table` fallback, and preserve the clean NodeNext source-tree, CommonJS `dist/*` build, and `100%` coverage baseline.
25
25
  - Official docs: https://alphaconsultings.mintlify.app
26
26
  - Quick start: https://alphaconsultings.mintlify.app/getting-started/quick-start
27
27
  - Release history: https://alphaconsultings.mintlify.app/release/history
@@ -51,6 +51,38 @@ function hasSameGeneratedBody(filePath, nextContent) {
51
51
  function pascalCase(name) {
52
52
  return name.charAt(0).toUpperCase() + name.slice(1);
53
53
  }
54
+ function classifyExtraMigrationSql(sql) {
55
+ const createTableMatch = sql.match(/CREATE TABLE(?: IF NOT EXISTS)?\s+[`"]?([A-Za-z0-9_]+)/i);
56
+ if (createTableMatch) {
57
+ const tableName = createTableMatch[1];
58
+ return {
59
+ targetName: tableName,
60
+ fileSuffix: `create_${tableName}_table`,
61
+ headerLabel: tableName,
62
+ logLabel: "Pivot migration",
63
+ fallbackRollbackSql: `DROP TABLE IF EXISTS ${tableName};`,
64
+ };
65
+ }
66
+ const createIndexMatch = sql.match(/CREATE(?: UNIQUE)? INDEX(?: IF NOT EXISTS)?\s+[`"]?([A-Za-z0-9_]+)[`"]?\s+ON\s+[`"]?([A-Za-z0-9_]+)/i);
67
+ if (createIndexMatch) {
68
+ const indexName = createIndexMatch[1];
69
+ const tableName = createIndexMatch[2];
70
+ return {
71
+ targetName: tableName,
72
+ fileSuffix: `add_${tableName}_indexes`,
73
+ headerLabel: `${tableName} indexes`,
74
+ logLabel: "Helper migration",
75
+ fallbackRollbackSql: `DROP INDEX IF EXISTS ${indexName};`,
76
+ };
77
+ }
78
+ return {
79
+ targetName: "schema_extras",
80
+ fileSuffix: "add_schema_extras",
81
+ headerLabel: "schema extras",
82
+ logLabel: "Helper migration",
83
+ fallbackRollbackSql: "-- rollback SQL unavailable for schema extras",
84
+ };
85
+ }
54
86
  function getBelongsToDependencies(schema, knownModels) {
55
87
  const deps = new Set();
56
88
  for (const value of Object.values(schema)) {
@@ -349,7 +381,8 @@ export async function down(db: { dropCollection(name: string): Promise<void> })
349
381
  pendingPivotMigrations.set(`${connectionName}:${pivot.collectionName}`, {
350
382
  connectionName,
351
383
  migrationsDir,
352
- pivotTable: pivot.collectionName,
384
+ fileSuffix: `create_${pivot.collectionName}_table`,
385
+ logLabel: "Pivot migration",
353
386
  content: pivotContent,
354
387
  });
355
388
  }
@@ -429,29 +462,24 @@ export async function down(db: { query(sql: string): Promise<void> }) {
429
462
  }
430
463
  if (pivotSeparate && extraTables.length > 0) {
431
464
  for (const [pivotIndex, originalSql] of extraTables.entries()) {
432
- const match = originalSql.match(/CREATE TABLE(?: IF NOT EXISTS)?\s+[`"]?([A-Za-z0-9_]+)/i);
433
- const pivotTable = match?.[1] ?? "pivot";
434
- const safePivotSql = originalSql.replace(/`/g, "\\`");
435
- const safeRollbackPivotSql = (rollbackExtraTables[pivotIndex] ?? `DROP TABLE IF EXISTS ${pivotTable};`).replace(/`/g, "\\`");
436
- const pivotHeader = `/**
437
- * Auto-generated CREATE migration for ${pivotTable}
438
- * Connection: ${connectionName}
439
- * Mode: ${isTest ? "TEST" : "DEVELOPMENT"}
440
- * Generated at ${new Date().toISOString()}
441
- */`;
442
- const pivotContent = `${pivotHeader}
443
- export async function up(db: { query(sql: string): Promise<void> }) {
444
- await db.query(\`${safePivotSql}\`);
445
- }
446
-
447
- export async function down(db: { query(sql: string): Promise<void> }) {
448
- await db.query(\`${safeRollbackPivotSql}\`);
449
- }`;
450
- pendingPivotMigrations.set(`${connectionName}:${pivotTable}`, {
465
+ const descriptor = classifyExtraMigrationSql(originalSql);
466
+ const rollbackSql = rollbackExtraTables[pivotIndex] ?? descriptor.fallbackRollbackSql;
467
+ const pendingKey = `${connectionName}:${descriptor.fileSuffix}`;
468
+ const existingPending = pendingPivotMigrations.get(pendingKey);
469
+ if (existingPending) {
470
+ existingPending.upSql.push(originalSql);
471
+ existingPending.downSql.unshift(rollbackSql);
472
+ continue;
473
+ }
474
+ pendingPivotMigrations.set(pendingKey, {
451
475
  connectionName,
452
476
  migrationsDir,
453
- pivotTable,
454
- content: pivotContent,
477
+ targetName: descriptor.targetName,
478
+ fileSuffix: descriptor.fileSuffix,
479
+ headerLabel: descriptor.headerLabel,
480
+ logLabel: descriptor.logLabel,
481
+ upSql: [originalSql],
482
+ downSql: [rollbackSql],
455
483
  });
456
484
  }
457
485
  }
@@ -463,27 +491,47 @@ export async function down(db: { query(sql: string): Promise<void> }) {
463
491
  }
464
492
  }
465
493
  for (const pendingPivot of pendingPivotMigrations.values()) {
494
+ const content = pendingPivot.content ??
495
+ (() => {
496
+ const escapeForTemplateLiteral = (sql) => sql.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
497
+ const header = `/**
498
+ * Auto-generated ${pendingPivot.logLabel === "Pivot migration" ? "CREATE migration" : "INDEX helper migration"} for ${pendingPivot.headerLabel}
499
+ * Connection: ${pendingPivot.connectionName}
500
+ * Mode: ${isTest ? "TEST" : "DEVELOPMENT"}
501
+ * Generated at ${new Date().toISOString()}
502
+ */`;
503
+ return `${header}
504
+ export async function up(db: { query(sql: string): Promise<void> }) {
505
+ ${pendingPivot.upSql
506
+ .map((sql) => `await db.query(\`${escapeForTemplateLiteral(sql)}\`);`)
507
+ .join("\n ")}
508
+ }
509
+
510
+ export async function down(db: { query(sql: string): Promise<void> }) {
511
+ ${pendingPivot.downSql
512
+ .map((sql) => `await db.query(\`${escapeForTemplateLiteral(sql)}\`);`)
513
+ .join("\n ")}
514
+ }`;
515
+ })();
466
516
  const allFiles = fs_1.default
467
517
  .readdirSync(pendingPivot.migrationsDir)
468
518
  .filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
469
- const existingPivotFiles = allFiles
470
- .filter((f) => /_create_[A-Za-z0-9_]+_table\.ts$/.test(f))
471
- .filter((f) => f.includes(`_create_${pendingPivot.pivotTable}_table.ts`));
472
- if (pendingPivot.pivotTable !== "pivot") {
519
+ const existingPivotFiles = allFiles.filter((f) => f.includes(`_${pendingPivot.fileSuffix}.ts`));
520
+ if (pendingPivot.logLabel !== "Pivot migration") {
473
521
  const genericPivotFiles = allFiles.filter((f) => f.includes("_create_pivot_table.ts"));
474
522
  existingPivotFiles.push(...genericPivotFiles);
475
523
  }
476
524
  const uniquePivotFiles = [...new Set(existingPivotFiles)];
477
- const unchangedPivot = uniquePivotFiles.find((fileName) => hasSameGeneratedBody(path_1.default.join(pendingPivot.migrationsDir, fileName), pendingPivot.content));
525
+ const unchangedPivot = uniquePivotFiles.find((fileName) => hasSameGeneratedBody(path_1.default.join(pendingPivot.migrationsDir, fileName), content));
478
526
  if (unchangedPivot) {
479
- console.log(chalk_1.default.gray(`INFO: Pivot migration unchanged: ${unchangedPivot}`));
527
+ console.log(chalk_1.default.gray(`INFO: ${pendingPivot.logLabel} unchanged: ${unchangedPivot}`));
480
528
  continue;
481
529
  }
482
530
  const pivotTimestamp = nextTimestamp();
483
- const pivotFile = `${pivotTimestamp}_create_${pendingPivot.pivotTable}_table.ts`;
531
+ const pivotFile = `${pivotTimestamp}_${pendingPivot.fileSuffix}.ts`;
484
532
  const pivotPath = path_1.default.join(pendingPivot.migrationsDir, pivotFile);
485
- fs_1.default.writeFileSync(pivotPath, pendingPivot.content, "utf8");
486
- console.log(chalk_1.default.green(`OK: Pivot migration saved: ${pivotPath}`));
533
+ fs_1.default.writeFileSync(pivotPath, content, "utf8");
534
+ console.log(chalk_1.default.green(`OK: ${pendingPivot.logLabel} saved: ${pivotPath}`));
487
535
  }
488
536
  try {
489
537
  await (0, ConnectionFactory_js_1.closeAllConnections)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpha.consultings/eloquent-orm.js",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "A Laravel Eloquent-inspired ORM Multi Driver SQL & NoSQL and Cache System and Artisan CLI like for Node.js Lovers",
5
5
  "keywords": [
6
6
  "orm",