turbine-orm 0.29.0 → 0.31.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.
Files changed (48) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/cli/index.js +5 -0
  3. package/dist/cjs/cli/mcp.js +22 -92
  4. package/dist/cjs/client.js +47 -6
  5. package/dist/cjs/generate.js +71 -25
  6. package/dist/cjs/index.js +4 -1
  7. package/dist/cjs/introspect.js +350 -120
  8. package/dist/cjs/mssql.js +42 -136
  9. package/dist/cjs/mysql.js +16 -129
  10. package/dist/cjs/optional-peer-import.cjs +122 -0
  11. package/dist/cjs/powdb.js +579 -89
  12. package/dist/cjs/powql.js +56 -26
  13. package/dist/cjs/query/builder.js +601 -86
  14. package/dist/cjs/query/filters.js +80 -2
  15. package/dist/cjs/schema-metadata.js +316 -0
  16. package/dist/cjs/sqlite.js +8 -89
  17. package/dist/cli/index.d.ts +2 -0
  18. package/dist/cli/index.js +5 -0
  19. package/dist/cli/mcp.d.ts +18 -0
  20. package/dist/cli/mcp.js +22 -93
  21. package/dist/client.d.ts +19 -2
  22. package/dist/client.js +47 -6
  23. package/dist/generate.d.ts +16 -4
  24. package/dist/generate.js +71 -25
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +2 -0
  27. package/dist/introspect.d.ts +94 -1
  28. package/dist/introspect.js +345 -120
  29. package/dist/mssql.js +40 -104
  30. package/dist/mysql.js +14 -97
  31. package/dist/optional-peer-import.cjs +89 -0
  32. package/dist/optional-peer-import.d.cts +53 -0
  33. package/dist/powdb.d.ts +118 -23
  34. package/dist/powdb.js +574 -88
  35. package/dist/powql.d.ts +6 -0
  36. package/dist/powql.js +58 -28
  37. package/dist/query/builder.d.ts +145 -8
  38. package/dist/query/builder.js +602 -87
  39. package/dist/query/deferred.d.ts +7 -2
  40. package/dist/query/filters.d.ts +46 -1
  41. package/dist/query/filters.js +76 -1
  42. package/dist/query/index.d.ts +1 -1
  43. package/dist/query/types.d.ts +85 -11
  44. package/dist/schema-metadata.d.ts +77 -0
  45. package/dist/schema-metadata.js +313 -0
  46. package/dist/schema.d.ts +10 -0
  47. package/dist/sqlite.js +9 -90
  48. package/package.json +3 -3
package/dist/cjs/mssql.js CHANGED
@@ -90,39 +90,9 @@
90
90
  * await db.disconnect();
91
91
  * ```
92
92
  */
93
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
94
- if (k2 === undefined) k2 = k;
95
- var desc = Object.getOwnPropertyDescriptor(m, k);
96
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
97
- desc = { enumerable: true, get: function() { return m[k]; } };
98
- }
99
- Object.defineProperty(o, k2, desc);
100
- }) : (function(o, m, k, k2) {
101
- if (k2 === undefined) k2 = k;
102
- o[k2] = m[k];
103
- }));
104
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
105
- Object.defineProperty(o, "default", { enumerable: true, value: v });
106
- }) : function(o, v) {
107
- o["default"] = v;
108
- });
109
- var __importStar = (this && this.__importStar) || (function () {
110
- var ownKeys = function(o) {
111
- ownKeys = Object.getOwnPropertyNames || function (o) {
112
- var ar = [];
113
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
114
- return ar;
115
- };
116
- return ownKeys(o);
117
- };
118
- return function (mod) {
119
- if (mod && mod.__esModule) return mod;
120
- var result = {};
121
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
122
- __setModuleDefault(result, mod);
123
- return result;
124
- };
125
- })();
93
+ var __importDefault = (this && this.__importDefault) || function (mod) {
94
+ return (mod && mod.__esModule) ? mod : { "default": mod };
95
+ };
126
96
  Object.defineProperty(exports, "__esModule", { value: true });
127
97
  exports.mssqlDialect = exports.MssqlPool = void 0;
128
98
  exports.mssqlTypeToTs = mssqlTypeToTs;
@@ -132,6 +102,8 @@ exports.turbineMssql = turbineMssql;
132
102
  const client_js_1 = require("./client.js");
133
103
  const dialect_js_1 = require("./dialect.js");
134
104
  const errors_js_1 = require("./errors.js");
105
+ const introspect_js_1 = require("./introspect.js");
106
+ const optional_peer_import_cjs_1 = __importDefault(require("./optional-peer-import.cjs"));
135
107
  const schema_js_1 = require("./schema.js");
136
108
  // ---------------------------------------------------------------------------
137
109
  // SQL Server / connection limits
@@ -784,11 +756,32 @@ function buildForJsonSubquery(dialect, ctx) {
784
756
  if (hasOrder) {
785
757
  const orderBy = orderEntries
786
758
  .map(([k, dir]) => {
787
- const col = (0, schema_js_1.camelToSnake)(k);
759
+ // FOR JSON nested ordering supports plain directions and { sort }
760
+ // specs only. Object shapes the core builder compiles with params
761
+ // (JSON-path / vector / relation ordering) must throw here: the
762
+ // shared param-collect mirror is gated on the native path, so a
763
+ // silently-ignored object would desync SQL text from params.
764
+ let rawDir = dir;
765
+ if (typeof dir === 'object' && dir !== null) {
766
+ const sortValue = dir.sort;
767
+ if (typeof sortValue !== 'string') {
768
+ throw new errors_js_1.ValidationError(`[turbine] Nested orderBy on "${k}" (table "${targetTable}"): only plain directions and ` +
769
+ `{ sort } specs are supported inside a relation orderBy on SQL Server.`);
770
+ }
771
+ if (dir.nulls !== undefined) {
772
+ throw new errors_js_1.UnsupportedFeatureError('NULLS FIRST/LAST ordering', 'sqlserver', 'Explicit nulls placement in orderBy is only available on PostgreSQL and SQLite.');
773
+ }
774
+ rawDir = sortValue;
775
+ }
776
+ // columnMap-first resolution (camelToSnake fallback): matches the
777
+ // core builder's nested orderBy path so camelCase-named DB columns
778
+ // resolve on SQL Server too.
779
+ const col = targetMeta.columnMap[k] ?? (0, schema_js_1.camelToSnake)(k);
788
780
  if (!targetMeta.allColumns.includes(col)) {
789
- throw new errors_js_1.ValidationError(`[turbine] Unknown column "${k}" in orderBy for table "${targetTable}"`);
781
+ throw new errors_js_1.ValidationError(`[turbine] Unknown field "${k}" in orderBy on table "${targetTable}". ` +
782
+ `Known fields: ${Object.keys(targetMeta.columnMap).join(', ') || '(none)'}.`);
790
783
  }
791
- const safeDir = String(dir).toLowerCase() === 'desc' ? 'DESC' : 'ASC';
784
+ const safeDir = String(rawDir).toLowerCase() === 'desc' ? 'DESC' : 'ASC';
792
785
  return `${a}.${q(col)} ${safeDir}`;
793
786
  })
794
787
  .join(', ');
@@ -894,103 +887,15 @@ function buildForJsonManyToMany(dialect, ctx, h) {
894
887
  }
895
888
  const num = (v) => (typeof v === 'string' ? Number(v) : (v ?? 0));
896
889
  /**
897
- * Derive belongsTo + hasMany relations (and conservatively-detected manyToMany
898
- * junctions) from a flat foreign-key list. Mirrors the PostgreSQL / MySQL / SQLite
899
- * introspectors so the produced {@link SchemaMetadata} has an identical relation
900
- * shape across engines.
890
+ * Derive relations from the FK list via the SHARED introspection pipeline
891
+ * (`deriveEngineRelations` `buildRelationsFromForeignKeys` +
892
+ * `addAutoManyToManyRelations` in introspect.ts), so this engine derives
893
+ * IDENTICAL relation names to `turbine generate` against Postgres for the
894
+ * same logical schema — legacy-first naming, per-column disambiguation, and
895
+ * collision resolution against scalar column fields included.
901
896
  */
902
897
  function buildRelationsFromForeignKeys(tableNames, foreignKeys, pkByTable, columnsByTable) {
903
- const tableSet = new Set(tableNames);
904
- const fkCounts = new Map();
905
- for (const fk of foreignKeys) {
906
- const key = `${fk.sourceTable}->${fk.targetTable}`;
907
- fkCounts.set(key, (fkCounts.get(key) ?? 0) + 1);
908
- }
909
- const relationsByTable = new Map();
910
- for (const fk of foreignKeys) {
911
- if (!tableSet.has(fk.targetTable))
912
- continue;
913
- const needsDisambiguation = (fkCounts.get(`${fk.sourceTable}->${fk.targetTable}`) ?? 0) > 1;
914
- const foreignKey = fk.sourceColumns.length === 1 ? fk.sourceColumns[0] : fk.sourceColumns;
915
- const referenceKey = fk.targetColumns.length === 1 ? fk.targetColumns[0] : fk.targetColumns;
916
- const belongsToName = needsDisambiguation && fk.sourceColumns.length === 1
917
- ? (0, schema_js_1.snakeToCamel)(fk.sourceColumns[0].replace(/_id$/, ''))
918
- : (0, schema_js_1.singularize)((0, schema_js_1.snakeToCamel)(fk.targetTable));
919
- if (!relationsByTable.has(fk.sourceTable))
920
- relationsByTable.set(fk.sourceTable, {});
921
- relationsByTable.get(fk.sourceTable)[belongsToName] = {
922
- type: 'belongsTo',
923
- name: belongsToName,
924
- from: fk.sourceTable,
925
- to: fk.targetTable,
926
- foreignKey,
927
- referenceKey,
928
- };
929
- const hasManyName = needsDisambiguation && fk.sourceColumns.length === 1
930
- ? (0, schema_js_1.snakeToCamel)(`${fk.sourceTable}_by_${fk.sourceColumns[0].replace(/_id$/, '')}`)
931
- : (0, schema_js_1.snakeToCamel)(fk.sourceTable);
932
- if (!relationsByTable.has(fk.targetTable))
933
- relationsByTable.set(fk.targetTable, {});
934
- relationsByTable.get(fk.targetTable)[hasManyName] = {
935
- type: 'hasMany',
936
- name: hasManyName,
937
- from: fk.targetTable,
938
- to: fk.sourceTable,
939
- foreignKey,
940
- referenceKey,
941
- };
942
- }
943
- // Conservative many-to-many auto-detection (additive): a table J is a pure
944
- // junction iff PK is exactly two columns, exactly two single-column FKs whose
945
- // source columns ARE the PK, two distinct target tables, and no payload columns.
946
- for (const tableName of tableNames) {
947
- const pk = pkByTable.get(tableName) ?? [];
948
- if (pk.length !== 2)
949
- continue;
950
- const tableFks = foreignKeys.filter((fk) => fk.sourceTable === tableName);
951
- if (tableFks.length !== 2)
952
- continue;
953
- if (tableFks.some((fk) => fk.sourceColumns.length !== 1))
954
- continue;
955
- const fkCols = tableFks.map((fk) => fk.sourceColumns[0]);
956
- const pkSet = new Set(pk);
957
- if (!fkCols.every((c) => pkSet.has(c)))
958
- continue;
959
- if (new Set(fkCols).size !== 2)
960
- continue;
961
- const [fkA, fkB] = tableFks;
962
- if (fkA.targetTable === fkB.targetTable)
963
- continue;
964
- const jCols = (columnsByTable.get(tableName) ?? []).map((c) => c.name);
965
- if (jCols.length !== 2)
966
- continue;
967
- const addM2M = (self, other) => {
968
- const sourceTbl = self.targetTable;
969
- const targetTbl = other.targetTable;
970
- const relName = (0, schema_js_1.snakeToCamel)(targetTbl);
971
- if (!relationsByTable.has(sourceTbl))
972
- relationsByTable.set(sourceTbl, {});
973
- const existing = relationsByTable.get(sourceTbl);
974
- if (existing[relName])
975
- return;
976
- existing[relName] = {
977
- type: 'manyToMany',
978
- name: relName,
979
- from: sourceTbl,
980
- to: targetTbl,
981
- referenceKey: self.targetColumns.length === 1 ? self.targetColumns[0] : self.targetColumns,
982
- foreignKey: self.targetColumns.length === 1 ? self.targetColumns[0] : self.targetColumns,
983
- through: {
984
- table: tableName,
985
- sourceKey: self.sourceColumns[0],
986
- targetKey: other.sourceColumns[0],
987
- },
988
- };
989
- };
990
- addM2M(fkA, fkB);
991
- addM2M(fkB, fkA);
992
- }
993
- return relationsByTable;
898
+ return (0, introspect_js_1.deriveEngineRelations)(tableNames, foreignKeys, pkByTable, columnsByTable);
994
899
  }
995
900
  /**
996
901
  * Introspect a SQL Server database into the same {@link SchemaMetadata} shape the
@@ -1237,11 +1142,12 @@ async function loadMssql() {
1237
1142
  let mod;
1238
1143
  try {
1239
1144
  // `mssql` ships no bundled type declarations (it needs @types/mssql, which
1240
- // Turbine deliberately does not depend on) — the structural MssqlModule above
1241
- // is our typed surface. Import through a widened specifier so tsc treats the
1242
- // typeless module as `any` instead of erroring (TS7016).
1243
- const specifier = 'mssql';
1244
- mod = (await Promise.resolve(`${specifier}`).then(s => __importStar(require(s))));
1145
+ // Turbine deliberately does not depend on) — the structural MssqlModule
1146
+ // above is our typed surface; the helper returns `unknown` so no TS7016.
1147
+ // Via the .cts helper so the CJS build keeps a path to a REAL dynamic
1148
+ // import() even if a future mssql major goes ESM-only (the CommonJS pass
1149
+ // transpiles a plain `import()` here into `require()`).
1150
+ mod = (await (0, optional_peer_import_cjs_1.default)('mssql'));
1245
1151
  }
1246
1152
  catch (err) {
1247
1153
  throw new errors_js_1.ConnectionError("[turbine] turbine-orm/mssql requires the optional peer dependency 'mssql'. Install it: npm i mssql. " +
package/dist/cjs/mysql.js CHANGED
@@ -63,39 +63,9 @@
63
63
  * await db.disconnect();
64
64
  * ```
65
65
  */
66
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
67
- if (k2 === undefined) k2 = k;
68
- var desc = Object.getOwnPropertyDescriptor(m, k);
69
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
70
- desc = { enumerable: true, get: function() { return m[k]; } };
71
- }
72
- Object.defineProperty(o, k2, desc);
73
- }) : (function(o, m, k, k2) {
74
- if (k2 === undefined) k2 = k;
75
- o[k2] = m[k];
76
- }));
77
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
78
- Object.defineProperty(o, "default", { enumerable: true, value: v });
79
- }) : function(o, v) {
80
- o["default"] = v;
81
- });
82
- var __importStar = (this && this.__importStar) || (function () {
83
- var ownKeys = function(o) {
84
- ownKeys = Object.getOwnPropertyNames || function (o) {
85
- var ar = [];
86
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
87
- return ar;
88
- };
89
- return ownKeys(o);
90
- };
91
- return function (mod) {
92
- if (mod && mod.__esModule) return mod;
93
- var result = {};
94
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
95
- __setModuleDefault(result, mod);
96
- return result;
97
- };
98
- })();
66
+ var __importDefault = (this && this.__importDefault) || function (mod) {
67
+ return (mod && mod.__esModule) ? mod : { "default": mod };
68
+ };
99
69
  Object.defineProperty(exports, "__esModule", { value: true });
100
70
  exports.mysqlDialect = exports.MysqlPool = void 0;
101
71
  exports.mysqlTypeToTs = mysqlTypeToTs;
@@ -105,6 +75,8 @@ exports.turbineMysql = turbineMysql;
105
75
  const client_js_1 = require("./client.js");
106
76
  const dialect_js_1 = require("./dialect.js");
107
77
  const errors_js_1 = require("./errors.js");
78
+ const introspect_js_1 = require("./introspect.js");
79
+ const optional_peer_import_cjs_1 = __importDefault(require("./optional-peer-import.cjs"));
108
80
  const schema_js_1 = require("./schema.js");
109
81
  // ---------------------------------------------------------------------------
110
82
  // Value coercion (params in)
@@ -596,103 +568,15 @@ exports.mysqlDialect = {
596
568
  };
597
569
  const num = (v) => (typeof v === 'string' ? Number(v) : (v ?? 0));
598
570
  /**
599
- * Derive belongsTo + hasMany relations (and conservatively-detected manyToMany
600
- * junctions) from a flat foreign-key list. Mirrors the PostgreSQL / SQLite
601
- * introspectors so the produced {@link SchemaMetadata} has an identical relation
602
- * shape across engines.
571
+ * Derive relations from the FK list via the SHARED introspection pipeline
572
+ * (`deriveEngineRelations` `buildRelationsFromForeignKeys` +
573
+ * `addAutoManyToManyRelations` in introspect.ts), so this engine derives
574
+ * IDENTICAL relation names to `turbine generate` against Postgres for the
575
+ * same logical schema — legacy-first naming, per-column disambiguation, and
576
+ * collision resolution against scalar column fields included.
603
577
  */
604
578
  function buildRelationsFromForeignKeys(tableNames, foreignKeys, pkByTable, columnsByTable) {
605
- const tableSet = new Set(tableNames);
606
- const fkCounts = new Map();
607
- for (const fk of foreignKeys) {
608
- const key = `${fk.sourceTable}->${fk.targetTable}`;
609
- fkCounts.set(key, (fkCounts.get(key) ?? 0) + 1);
610
- }
611
- const relationsByTable = new Map();
612
- for (const fk of foreignKeys) {
613
- if (!tableSet.has(fk.targetTable))
614
- continue;
615
- const needsDisambiguation = (fkCounts.get(`${fk.sourceTable}->${fk.targetTable}`) ?? 0) > 1;
616
- const foreignKey = fk.sourceColumns.length === 1 ? fk.sourceColumns[0] : fk.sourceColumns;
617
- const referenceKey = fk.targetColumns.length === 1 ? fk.targetColumns[0] : fk.targetColumns;
618
- const belongsToName = needsDisambiguation && fk.sourceColumns.length === 1
619
- ? (0, schema_js_1.snakeToCamel)(fk.sourceColumns[0].replace(/_id$/, ''))
620
- : (0, schema_js_1.singularize)((0, schema_js_1.snakeToCamel)(fk.targetTable));
621
- if (!relationsByTable.has(fk.sourceTable))
622
- relationsByTable.set(fk.sourceTable, {});
623
- relationsByTable.get(fk.sourceTable)[belongsToName] = {
624
- type: 'belongsTo',
625
- name: belongsToName,
626
- from: fk.sourceTable,
627
- to: fk.targetTable,
628
- foreignKey,
629
- referenceKey,
630
- };
631
- const hasManyName = needsDisambiguation && fk.sourceColumns.length === 1
632
- ? (0, schema_js_1.snakeToCamel)(`${fk.sourceTable}_by_${fk.sourceColumns[0].replace(/_id$/, '')}`)
633
- : (0, schema_js_1.snakeToCamel)(fk.sourceTable);
634
- if (!relationsByTable.has(fk.targetTable))
635
- relationsByTable.set(fk.targetTable, {});
636
- relationsByTable.get(fk.targetTable)[hasManyName] = {
637
- type: 'hasMany',
638
- name: hasManyName,
639
- from: fk.targetTable,
640
- to: fk.sourceTable,
641
- foreignKey,
642
- referenceKey,
643
- };
644
- }
645
- // Conservative many-to-many auto-detection (additive): a table J is a pure
646
- // junction iff PK is exactly two columns, exactly two single-column FKs whose
647
- // source columns ARE the PK, two distinct target tables, and no payload columns.
648
- for (const tableName of tableNames) {
649
- const pk = pkByTable.get(tableName) ?? [];
650
- if (pk.length !== 2)
651
- continue;
652
- const tableFks = foreignKeys.filter((fk) => fk.sourceTable === tableName);
653
- if (tableFks.length !== 2)
654
- continue;
655
- if (tableFks.some((fk) => fk.sourceColumns.length !== 1))
656
- continue;
657
- const fkCols = tableFks.map((fk) => fk.sourceColumns[0]);
658
- const pkSet = new Set(pk);
659
- if (!fkCols.every((c) => pkSet.has(c)))
660
- continue;
661
- if (new Set(fkCols).size !== 2)
662
- continue;
663
- const [fkA, fkB] = tableFks;
664
- if (fkA.targetTable === fkB.targetTable)
665
- continue;
666
- const jCols = (columnsByTable.get(tableName) ?? []).map((c) => c.name);
667
- if (jCols.length !== 2)
668
- continue;
669
- const addM2M = (self, other) => {
670
- const sourceTbl = self.targetTable;
671
- const targetTbl = other.targetTable;
672
- const relName = (0, schema_js_1.snakeToCamel)(targetTbl);
673
- if (!relationsByTable.has(sourceTbl))
674
- relationsByTable.set(sourceTbl, {});
675
- const existing = relationsByTable.get(sourceTbl);
676
- if (existing[relName])
677
- return;
678
- existing[relName] = {
679
- type: 'manyToMany',
680
- name: relName,
681
- from: sourceTbl,
682
- to: targetTbl,
683
- referenceKey: self.targetColumns.length === 1 ? self.targetColumns[0] : self.targetColumns,
684
- foreignKey: self.targetColumns.length === 1 ? self.targetColumns[0] : self.targetColumns,
685
- through: {
686
- table: tableName,
687
- sourceKey: self.sourceColumns[0],
688
- targetKey: other.sourceColumns[0],
689
- },
690
- };
691
- };
692
- addM2M(fkA, fkB);
693
- addM2M(fkB, fkA);
694
- }
695
- return relationsByTable;
579
+ return (0, introspect_js_1.deriveEngineRelations)(tableNames, foreignKeys, pkByTable, columnsByTable);
696
580
  }
697
581
  /**
698
582
  * Introspect a MySQL database into the same {@link SchemaMetadata} shape the
@@ -939,7 +823,10 @@ function parseMysqlConfig(connectionString) {
939
823
  async function loadCreatePool() {
940
824
  let mod;
941
825
  try {
942
- mod = (await Promise.resolve().then(() => __importStar(require('mysql2/promise'))));
826
+ // Via the .cts helper so the CJS build keeps a path to a REAL dynamic
827
+ // import() even if a future mysql2 major goes ESM-only (the CommonJS pass
828
+ // transpiles a plain `import()` here into `require()`).
829
+ mod = (await (0, optional_peer_import_cjs_1.default)('mysql2/promise'));
943
830
  }
944
831
  catch (err) {
945
832
  throw new errors_js_1.ConnectionError("[turbine] turbine-orm/mysql requires the optional peer dependency 'mysql2'. Install it: npm i mysql2. " +
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /**
3
+ * True dynamic `import()` for the optional peer dependencies (`mysql2`,
4
+ * `mssql`, `@zvndev/powdb-client`, `@zvndev/powdb-embedded`) — safe in BOTH
5
+ * build outputs, including for peers that are ESM-only.
6
+ *
7
+ * THE PROBLEM THIS FILE SOLVES (the `@zvndev/powdb-client` ≥ 0.9 CJS break):
8
+ * the engine subpaths load their optional peers with dynamic `import()` so the
9
+ * peers stay out of the static graph. The ESM build (`tsconfig.json`, module
10
+ * NodeNext) emits that `import()` verbatim. The CJS build (`tsconfig.cjs.json`,
11
+ * module CommonJS) however TRANSPILES `import()` into
12
+ * `Promise.resolve().then(() => require(...))` — and `require()` of an
13
+ * ESM-only package (no `require` export condition, e.g. powdb-client ≥ 0.9)
14
+ * throws `ERR_PACKAGE_PATH_NOT_EXPORTED`, breaking every CJS consumer.
15
+ *
16
+ * TypeScript offers no way to preserve `import()` under `module: CommonJS`,
17
+ * and the CJS pass cannot switch to `module: NodeNext` (the root package.json
18
+ * says `"type": "module"`, so NodeNext would classify every `.ts` source as
19
+ * ESM and emit ESM into dist/cjs). A `.cts` file is the escape hatch: it is
20
+ * CommonJS-format by extension regardless of package `type`, so under the ESM
21
+ * pass (NodeNext) it compiles to `dist/optional-peer-import.cjs` — a CommonJS
22
+ * file whose `import()` SURVIVES transpilation (NodeNext preserves dynamic
23
+ * import in CJS files precisely because it is the only way CJS can load ESM).
24
+ *
25
+ * That gives the published package two copies of this module:
26
+ * - `dist/optional-peer-import.cjs` (ESM pass, NodeNext) — real `import()`
27
+ * - `dist/cjs/optional-peer-import.cjs` (CJS pass, CommonJS) — lowered to `require()`
28
+ *
29
+ * The lowered copy works fine for CJS-loadable peers (`mysql2`, `mssql`, older
30
+ * powdb peers). When it hits an ESM-only peer, the `require()` fails with a
31
+ * recognizable code and this function falls back to delegating the load to the
32
+ * sibling NodeNext copy one directory up (`../optional-peer-import.cjs`) —
33
+ * which is a plain CommonJS file (loadable by `require()` on every supported
34
+ * Node) whose real `import()` then loads the ESM peer. The ESM-pass copy has
35
+ * no such sibling; its lazy `require` throws and the original error surfaces,
36
+ * so the fallback can never recurse.
37
+ *
38
+ * Keep this module dependency-free and side-effect-free: it must be loadable
39
+ * from both module systems on every supported Node (≥ 20) without pulling in
40
+ * anything else.
41
+ */
42
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
43
+ if (k2 === undefined) k2 = k;
44
+ var desc = Object.getOwnPropertyDescriptor(m, k);
45
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
46
+ desc = { enumerable: true, get: function() { return m[k]; } };
47
+ }
48
+ Object.defineProperty(o, k2, desc);
49
+ }) : (function(o, m, k, k2) {
50
+ if (k2 === undefined) k2 = k;
51
+ o[k2] = m[k];
52
+ }));
53
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
54
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
55
+ }) : function(o, v) {
56
+ o["default"] = v;
57
+ });
58
+ var __importStar = (this && this.__importStar) || (function () {
59
+ var ownKeys = function(o) {
60
+ ownKeys = Object.getOwnPropertyNames || function (o) {
61
+ var ar = [];
62
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
63
+ return ar;
64
+ };
65
+ return ownKeys(o);
66
+ };
67
+ return function (mod) {
68
+ if (mod && mod.__esModule) return mod;
69
+ var result = {};
70
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
71
+ __setModuleDefault(result, mod);
72
+ return result;
73
+ };
74
+ })();
75
+ /**
76
+ * Does this error mean "the module exists but cannot be loaded via
77
+ * `require()` because it is ESM-only"? These are the only failures worth
78
+ * retrying through a real `import()`; anything else (not installed, throw on
79
+ * init, …) is rethrown untouched so callers keep the original diagnostics.
80
+ */
81
+ function isEsmOnlyLoadError(err) {
82
+ const code = err?.code;
83
+ return (code === 'ERR_PACKAGE_PATH_NOT_EXPORTED' || // exports map has no `require` condition
84
+ code === 'ERR_REQUIRE_ESM' || // require() of an ES module (pre-require(esm) Node)
85
+ code === 'ERR_REQUIRE_ASYNC_MODULE' // require(esm) of a module with top-level await
86
+ );
87
+ }
88
+ /**
89
+ * Dynamically import an optional peer dependency. In the ESM build this is a
90
+ * plain `import()`. In the CJS build the first attempt is a transpiled
91
+ * `require()`; if the peer turns out to be ESM-only, the load is retried
92
+ * through the ESM-build sibling copy of this file, whose `import()` survived
93
+ * transpilation (see the module doc comment).
94
+ *
95
+ * @param specifier bare package specifier (e.g. `'@zvndev/powdb-client'`).
96
+ * @param allowEsmFallback internal recursion guard — the delegated call passes
97
+ * `false` so a failure in the sibling copy can never bounce back.
98
+ */
99
+ async function importOptionalPeer(specifier, allowEsmFallback = true) {
100
+ try {
101
+ return await Promise.resolve(`${specifier}`).then(s => __importStar(require(s)));
102
+ }
103
+ catch (err) {
104
+ if (!allowEsmFallback || !isEsmOnlyLoadError(err))
105
+ throw err;
106
+ let esmCapableCopy;
107
+ try {
108
+ // Only resolvable from dist/cjs/, where it lands on the NodeNext-built
109
+ // dist/optional-peer-import.cjs. From anywhere else (the ESM copy
110
+ // itself, or running the TypeScript source directly) the file does not
111
+ // exist and the original error is rethrown below.
112
+ esmCapableCopy = require('../optional-peer-import.cjs');
113
+ }
114
+ catch {
115
+ esmCapableCopy = undefined;
116
+ }
117
+ if (typeof esmCapableCopy !== 'function')
118
+ throw err;
119
+ return esmCapableCopy(specifier, false);
120
+ }
121
+ }
122
+ module.exports = importOptionalPeer;