drizzle-graphql-plus 0.8.37 → 0.8.38

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/index.cjs CHANGED
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/export-tool/utils.ts
33
+ // src/export-directive/utils.ts
34
34
  var utils_exports = {};
35
35
  __export(utils_exports, {
36
36
  extractExportDirectives: () => extractExportDirectives,
@@ -50,24 +50,20 @@ function getVariableName(value) {
50
50
  }
51
51
  return value.slice(2);
52
52
  }
53
- async function resolveExportVariables(args, exportStore, timeout, allowNull = true) {
53
+ async function resolveExportVariables(args, exportStore, timeout = 5e3) {
54
54
  if (isExportVariable(args)) {
55
55
  const varName = getVariableName(args);
56
- return await exportStore.waitFor(varName, timeout, allowNull);
56
+ const resolvedValue = await exportStore.waitFor(varName, timeout, false);
57
+ return resolvedValue;
57
58
  }
58
59
  if (Array.isArray(args)) {
59
60
  const resolved = await Promise.all(
60
61
  args.map(async (item) => {
61
62
  if (isExportVariable(item)) {
62
63
  const varName = getVariableName(item);
63
- return await exportStore.waitFor(varName, timeout, allowNull);
64
+ return await exportStore.waitFor(varName, timeout, false);
64
65
  } else if (typeof item === "object" && item !== null) {
65
- return await resolveExportVariables(
66
- item,
67
- exportStore,
68
- timeout,
69
- allowNull
70
- );
66
+ return await resolveExportVariables(item, exportStore, timeout);
71
67
  }
72
68
  return item;
73
69
  })
@@ -79,20 +75,21 @@ async function resolveExportVariables(args, exportStore, timeout, allowNull = tr
79
75
  for (const [key, value] of Object.entries(args)) {
80
76
  if (isExportVariable(value)) {
81
77
  const varName = getVariableName(value);
82
- resolved[key] = await exportStore.waitFor(varName, timeout, allowNull);
83
- } else if (Array.isArray(value)) {
84
- resolved[key] = await resolveExportVariables(
85
- value,
86
- exportStore,
78
+ const resolvedValue = await exportStore.waitFor(
79
+ varName,
87
80
  timeout,
88
- allowNull
81
+ false
89
82
  );
83
+ if (key === "OR" && Array.isArray(resolvedValue)) {
84
+ resolved[key] = resolvedValue.map((id) => ({ id: { eq: id } }));
85
+ } else {
86
+ resolved[key] = resolvedValue;
87
+ }
90
88
  } else if (typeof value === "object" && value !== null) {
91
89
  resolved[key] = await resolveExportVariables(
92
90
  value,
93
91
  exportStore,
94
- timeout,
95
- allowNull
92
+ timeout
96
93
  );
97
94
  } else {
98
95
  resolved[key] = value;
@@ -186,7 +183,7 @@ function processExports(result, selectionSet, exportStore, isArrayItem = false)
186
183
  }
187
184
  }
188
185
  var init_utils = __esm({
189
- "src/export-tool/utils.ts"() {
186
+ "src/export-directive/utils.ts"() {
190
187
  "use strict";
191
188
  }
192
189
  });
@@ -194,12 +191,18 @@ var init_utils = __esm({
194
191
  // src/index.ts
195
192
  var src_exports = {};
196
193
  __export(src_exports, {
194
+ ExportStore: () => ExportStore,
195
+ SerialExecutor: () => SerialExecutor,
197
196
  buildSchemaSDLWithDataLoader: () => buildSchemaSDL,
198
197
  cleanupDataLoaderContext: () => cleanupDataLoaderContext,
199
198
  createDataLoaderContext: () => createDataLoaderContext,
200
199
  createExportMiddleware: () => createExportMiddleware,
200
+ createExportResolverMap: () => createExportResolverMap,
201
+ createSerialMiddleware: () => createSerialMiddleware,
202
+ createSerialResolverMap: () => createSerialResolverMap,
201
203
  exportDirectiveTypeDefs: () => exportDirectiveTypeDefs,
202
204
  makeScalarAcceptExports: () => makeScalarAcceptExports,
205
+ serialDirectiveTypeDefs: () => serialDirectiveTypeDefs,
203
206
  setCustomGraphQL: () => setCustomGraphQL,
204
207
  setCustomGraphQLTypes: () => setCustomGraphQLTypes,
205
208
  useDataLoaderCleanup: () => useDataLoaderCleanup,
@@ -912,15 +915,27 @@ var RelationDataLoader = class {
912
915
  if (hasExportVariables2(resolvedWhere)) {
913
916
  try {
914
917
  if (this.debugConfig?.exportVariables) {
915
- console.log(`\u{1F50D} DataLoader: Resolving export variables in where clause:`, resolvedWhere);
918
+ console.log(
919
+ `\u{1F50D} DataLoader: Resolving export variables in where clause:`,
920
+ resolvedWhere
921
+ );
916
922
  }
917
- resolvedWhere = await resolveExportVariables2(resolvedWhere, this.context.exportStore);
923
+ resolvedWhere = await resolveExportVariables2(
924
+ resolvedWhere,
925
+ this.context.exportStore
926
+ );
918
927
  if (this.debugConfig?.exportVariables) {
919
- console.log(`\u2705 DataLoader: Successfully resolved to:`, resolvedWhere);
928
+ console.log(
929
+ `\u2705 DataLoader: Successfully resolved to:`,
930
+ resolvedWhere
931
+ );
920
932
  }
921
933
  } catch (error) {
922
934
  if (this.debugConfig?.exportVariables) {
923
- console.warn(`\u274C DataLoader: Failed to resolve export variables:`, error);
935
+ console.warn(
936
+ `\u274C DataLoader: Failed to resolve export variables:`,
937
+ error
938
+ );
924
939
  }
925
940
  }
926
941
  }
@@ -948,11 +963,16 @@ var RelationDataLoader = class {
948
963
  offset: firstKey.offset
949
964
  });
950
965
  if (this.debugConfig?.dataLoader) {
951
- console.log(`DataLoader executing query for relation ${firstKey.relationName} with foreign key ${firstKey.foreignKey}`);
966
+ console.log(
967
+ `DataLoader executing query for relation ${firstKey.relationName} with foreign key ${firstKey.foreignKey}`
968
+ );
952
969
  }
953
970
  const batchResults = await query;
954
971
  if (this.debugConfig?.dataLoader) {
955
- console.log(`DataLoader got ${batchResults.length} results:`, batchResults);
972
+ console.log(
973
+ `DataLoader got ${batchResults.length} results:`,
974
+ batchResults
975
+ );
956
976
  }
957
977
  const resultsByParentId = /* @__PURE__ */ new Map();
958
978
  for (const result of batchResults) {
@@ -963,10 +983,12 @@ var RelationDataLoader = class {
963
983
  resultsByParentId.get(parentId).push(result);
964
984
  }
965
985
  for (const key of groupKeys) {
966
- const keyResults = key.parentIds.map((parentId) => ({
967
- parentId,
968
- data: resultsByParentId.get(parentId) || []
969
- }));
986
+ const keyResults = key.parentIds.map(
987
+ (parentId) => ({
988
+ parentId,
989
+ data: resultsByParentId.get(parentId) || []
990
+ })
991
+ );
970
992
  results.push(keyResults);
971
993
  }
972
994
  }
@@ -975,7 +997,9 @@ var RelationDataLoader = class {
975
997
  buildBatchWhereClause(parentIds, isReversedRelation, foreignKeyName, additionalWhere) {
976
998
  const foreignKeyColumn = this.tableInfo.columns[foreignKeyName];
977
999
  if (!foreignKeyColumn) {
978
- console.error(`Foreign key column ${foreignKeyName} not found in table ${this.tableInfo.name}`);
1000
+ console.error(
1001
+ `Foreign key column ${foreignKeyName} not found in table ${this.tableInfo.name}`
1002
+ );
979
1003
  console.error(`Available columns:`, Object.keys(this.tableInfo.columns));
980
1004
  return void 0;
981
1005
  }
@@ -1011,7 +1035,13 @@ function getRelationLoader(context, tableName, queryBase, tableInfo, relations,
1011
1035
  if (!context.relationLoaders.has(tableName)) {
1012
1036
  context.relationLoaders.set(
1013
1037
  tableName,
1014
- new RelationDataLoader(queryBase, tableInfo, relations, context, debugConfig)
1038
+ new RelationDataLoader(
1039
+ queryBase,
1040
+ tableInfo,
1041
+ relations,
1042
+ context,
1043
+ debugConfig
1044
+ )
1015
1045
  // Pass debug config
1016
1046
  );
1017
1047
  }
@@ -1523,9 +1553,12 @@ var generateMutations = (db, tables, relations, debugConfig) => {
1523
1553
  return { mutations, deleteResultResolvers };
1524
1554
  };
1525
1555
 
1526
- // src/export-tool/directive-definitions.ts
1556
+ // src/export-directive/directive-definitions.ts
1527
1557
  var exportDirectiveTypeDefs = `directive @export(as: String!) on FIELD`;
1528
1558
 
1559
+ // src/serial-directive/directive-definitions.ts
1560
+ var serialDirectiveTypeDefs = `directive @serial on QUERY | MUTATION | SUBSCRIPTION`;
1561
+
1529
1562
  // src/build-schema-sdl-with-dl/index.ts
1530
1563
  var import_schema2 = require("@graphql-tools/schema");
1531
1564
  var buildSchemaSDL = (db, config) => {
@@ -1617,7 +1650,185 @@ var useDataLoaderCleanupOnly = () => ({
1617
1650
  })
1618
1651
  });
1619
1652
 
1620
- // src/export-tool/ExportStore.ts
1653
+ // src/serial-directive/SerialExecutor.ts
1654
+ var SerialExecutor = class {
1655
+ executionQueue = /* @__PURE__ */ new Map();
1656
+ isEnabled = false;
1657
+ /**
1658
+ * Enable serial execution for the current operation
1659
+ */
1660
+ enable() {
1661
+ this.isEnabled = true;
1662
+ }
1663
+ /**
1664
+ * Disable serial execution for the current operation
1665
+ */
1666
+ disable() {
1667
+ this.isEnabled = false;
1668
+ this.executionQueue.clear();
1669
+ }
1670
+ /**
1671
+ * Check if serial execution is enabled
1672
+ */
1673
+ isSerialEnabled() {
1674
+ return this.isEnabled;
1675
+ }
1676
+ /**
1677
+ * Add a resolver promise to the execution queue
1678
+ * @param parentPath - The path of the parent field
1679
+ * @param resolverPromise - The resolver promise to queue
1680
+ */
1681
+ queueResolver(parentPath, resolverPromise) {
1682
+ if (!this.isEnabled) {
1683
+ return resolverPromise();
1684
+ }
1685
+ const queue = this.executionQueue.get(parentPath) || [];
1686
+ const lastPromise = queue.length > 0 ? queue[queue.length - 1] : null;
1687
+ const serialPromise = lastPromise ? lastPromise.then(() => resolverPromise()) : resolverPromise();
1688
+ queue.push(serialPromise);
1689
+ this.executionQueue.set(parentPath, queue);
1690
+ return serialPromise;
1691
+ }
1692
+ /**
1693
+ * Wait for all queued resolvers in a specific path to complete
1694
+ * @param parentPath - The path to wait for
1695
+ */
1696
+ async waitForPath(parentPath) {
1697
+ const queue = this.executionQueue.get(parentPath);
1698
+ if (queue && queue.length > 0) {
1699
+ await Promise.all(queue);
1700
+ }
1701
+ }
1702
+ /**
1703
+ * Wait for all queued resolvers to complete
1704
+ */
1705
+ async waitForAll() {
1706
+ const allQueues = Array.from(this.executionQueue.values());
1707
+ const allPromises = allQueues.flat();
1708
+ if (allPromises.length > 0) {
1709
+ await Promise.all(allPromises);
1710
+ }
1711
+ }
1712
+ /**
1713
+ * Clear the execution queue for a specific path
1714
+ * @param parentPath - The path to clear
1715
+ */
1716
+ clearPath(parentPath) {
1717
+ this.executionQueue.delete(parentPath);
1718
+ }
1719
+ /**
1720
+ * Clear all execution queues
1721
+ */
1722
+ clearAll() {
1723
+ this.executionQueue.clear();
1724
+ }
1725
+ };
1726
+
1727
+ // src/serial-directive/utils.ts
1728
+ function hasSerialDirective(info) {
1729
+ const operation = info.operation;
1730
+ return operation.directives?.some(
1731
+ (directive) => directive.name.value === "serial"
1732
+ ) || false;
1733
+ }
1734
+ function getFieldPath(info) {
1735
+ const path = [];
1736
+ let currentPath = info.path;
1737
+ while (currentPath) {
1738
+ if (typeof currentPath.key === "string") {
1739
+ path.unshift(currentPath.key);
1740
+ }
1741
+ currentPath = currentPath.prev;
1742
+ }
1743
+ return path.join(".");
1744
+ }
1745
+ function getParentFieldPath(info) {
1746
+ const path = [];
1747
+ let currentPath = info.path.prev;
1748
+ while (currentPath) {
1749
+ if (typeof currentPath.key === "string") {
1750
+ path.unshift(currentPath.key);
1751
+ }
1752
+ currentPath = currentPath.prev;
1753
+ }
1754
+ return path.join(".") || "root";
1755
+ }
1756
+ function isRootField(info) {
1757
+ return !info.path.prev || info.path.prev.key === void 0;
1758
+ }
1759
+ function logSerialExecution(message, info, data) {
1760
+ if (process.env["DEBUG_SERIAL"]) {
1761
+ const fieldPath = getFieldPath(info);
1762
+ const parentPath = getParentFieldPath(info);
1763
+ console.log(`[SERIAL] ${message}`, {
1764
+ field: `${info.parentType.name}.${info.fieldName}`,
1765
+ fieldPath,
1766
+ parentPath,
1767
+ operation: info.operation.operation,
1768
+ data
1769
+ });
1770
+ }
1771
+ }
1772
+
1773
+ // src/serial-directive/middleware.ts
1774
+ function createSerialMiddleware() {
1775
+ return (next) => {
1776
+ return async (source, args, context, info) => {
1777
+ if (!context.serialExecutor) {
1778
+ context.serialExecutor = new SerialExecutor();
1779
+ }
1780
+ const serialExecutor = context.serialExecutor;
1781
+ const shouldExecuteSerially = hasSerialDirective(info);
1782
+ if (shouldExecuteSerially && !serialExecutor.isSerialEnabled()) {
1783
+ serialExecutor.enable();
1784
+ logSerialExecution("Serial execution enabled for operation", info);
1785
+ }
1786
+ if (!serialExecutor.isSerialEnabled()) {
1787
+ return next(source, args, context, info);
1788
+ }
1789
+ const parentPath = getParentFieldPath(info);
1790
+ const isRoot = isRootField(info);
1791
+ logSerialExecution("Queuing resolver execution", info, {
1792
+ parentPath,
1793
+ isRoot,
1794
+ fieldName: info.fieldName
1795
+ });
1796
+ const resolverPromise = () => {
1797
+ logSerialExecution("Executing resolver", info);
1798
+ return Promise.resolve(next(source, args, context, info));
1799
+ };
1800
+ try {
1801
+ const result = await serialExecutor.queueResolver(
1802
+ parentPath,
1803
+ resolverPromise
1804
+ );
1805
+ logSerialExecution("Resolver execution completed", info);
1806
+ return result;
1807
+ } catch (error) {
1808
+ logSerialExecution("Resolver execution failed", info, { error });
1809
+ throw error;
1810
+ }
1811
+ };
1812
+ };
1813
+ }
1814
+ function createSerialResolverMap(resolvers) {
1815
+ const serialMiddleware = createSerialMiddleware();
1816
+ const wrappedResolvers = {};
1817
+ for (const typeName in resolvers) {
1818
+ wrappedResolvers[typeName] = {};
1819
+ for (const fieldName in resolvers[typeName]) {
1820
+ const originalResolver = resolvers[typeName][fieldName];
1821
+ if (typeof originalResolver === "function") {
1822
+ wrappedResolvers[typeName][fieldName] = serialMiddleware(originalResolver);
1823
+ } else {
1824
+ wrappedResolvers[typeName][fieldName] = originalResolver;
1825
+ }
1826
+ }
1827
+ }
1828
+ return wrappedResolvers;
1829
+ }
1830
+
1831
+ // src/export-directive/ExportStore.ts
1621
1832
  var ExportStore = class {
1622
1833
  store = /* @__PURE__ */ new Map();
1623
1834
  pending = /* @__PURE__ */ new Map();
@@ -1636,22 +1847,23 @@ var ExportStore = class {
1636
1847
  }
1637
1848
  /**
1638
1849
  * Accumulate values into an array with deduplication
1639
- * First call initializes an array, subsequent calls add to it
1640
- * Use this when the same export variable is used in multiple array items
1850
+ * Works great with @serial directive to build arrays from sequential field exports
1641
1851
  */
1642
1852
  accumulate(name, value) {
1643
1853
  if (!this.accumulators.has(name)) {
1644
1854
  this.accumulators.set(name, /* @__PURE__ */ new Set());
1645
1855
  }
1646
1856
  const accumulator = this.accumulators.get(name);
1647
- if (Array.isArray(value)) {
1648
- value.forEach((item) => {
1649
- if (item !== null && item !== void 0) {
1650
- accumulator.add(item);
1651
- }
1652
- });
1653
- } else if (value !== null && value !== void 0) {
1654
- accumulator.add(value);
1857
+ if (value !== null && value !== void 0) {
1858
+ if (Array.isArray(value)) {
1859
+ value.forEach((item) => {
1860
+ if (item !== null && item !== void 0) {
1861
+ accumulator.add(item);
1862
+ }
1863
+ });
1864
+ } else {
1865
+ accumulator.add(value);
1866
+ }
1655
1867
  }
1656
1868
  const accumulatedArray = Array.from(accumulator);
1657
1869
  this.store.set(name, accumulatedArray);
@@ -1721,7 +1933,7 @@ var ExportStore = class {
1721
1933
  }
1722
1934
  };
1723
1935
 
1724
- // src/export-tool/middleware.ts
1936
+ // src/export-directive/middleware.ts
1725
1937
  init_utils();
1726
1938
  function createExportMiddleware() {
1727
1939
  return (next) => {
@@ -1733,15 +1945,10 @@ function createExportMiddleware() {
1733
1945
  let resolvedArgs = args;
1734
1946
  if (args && typeof args === "object" && hasExportVariables(args)) {
1735
1947
  try {
1736
- resolvedArgs = await resolveExportVariables(args, exportStore);
1948
+ resolvedArgs = await resolveExportVariables(args, exportStore, 1e4);
1737
1949
  } catch (error) {
1738
- if (error instanceof Error && error.message.includes("Timeout waiting for export variable")) {
1739
- throw new Error(
1740
- `Failed to resolve export variables in ${info.parentType.name}.${info.fieldName}: ${error.message}. Consider using a fallback value or checking if the exported field can return null.`
1741
- );
1742
- }
1743
1950
  throw new Error(
1744
- `Failed to resolve export variables in ${info.parentType.name}.${info.fieldName}: ${error instanceof Error ? error.message : String(error)}`
1951
+ `Export variable resolution failed in ${info.parentType.name}.${info.fieldName}: ${error instanceof Error ? error.message : String(error)}`
1745
1952
  );
1746
1953
  }
1747
1954
  }
@@ -1750,11 +1957,13 @@ function createExportMiddleware() {
1750
1957
  if (!fieldNode)
1751
1958
  return result;
1752
1959
  const selfExportName = getExportDirective(fieldNode);
1753
- if (selfExportName && result !== void 0) {
1960
+ if (selfExportName && result !== void 0 && result !== null) {
1754
1961
  if (Array.isArray(result)) {
1755
- result.forEach(
1756
- (value) => exportStore.accumulate(selfExportName, value)
1757
- );
1962
+ result.forEach((value) => {
1963
+ if (value !== void 0 && value !== null) {
1964
+ exportStore.accumulate(selfExportName, value);
1965
+ }
1966
+ });
1758
1967
  } else {
1759
1968
  exportStore.set(selfExportName, result);
1760
1969
  }
@@ -1774,11 +1983,17 @@ function createExportMiddleware() {
1774
1983
  };
1775
1984
  };
1776
1985
  }
1986
+ function createExportResolverMap() {
1987
+ return {
1988
+ // Apply to all resolvers (Query.*, Mutation.*, etc.)
1989
+ "*.*": [createExportMiddleware()]
1990
+ };
1991
+ }
1777
1992
 
1778
- // src/export-tool/index.ts
1993
+ // src/export-directive/index.ts
1779
1994
  init_utils();
1780
1995
 
1781
- // src/export-tool/makeScalarAcceptExports.ts
1996
+ // src/export-directive/makeScalarAcceptExports.ts
1782
1997
  var import_graphql5 = require("graphql");
1783
1998
  function makeScalarAcceptExports(originalScalar) {
1784
1999
  const config = originalScalar.toConfig();
@@ -1840,12 +2055,18 @@ function setCustomGraphQLTypes(table, columnTypes) {
1840
2055
  }
1841
2056
  // Annotate the CommonJS export names for ESM import in node:
1842
2057
  0 && (module.exports = {
2058
+ ExportStore,
2059
+ SerialExecutor,
1843
2060
  buildSchemaSDLWithDataLoader,
1844
2061
  cleanupDataLoaderContext,
1845
2062
  createDataLoaderContext,
1846
2063
  createExportMiddleware,
2064
+ createExportResolverMap,
2065
+ createSerialMiddleware,
2066
+ createSerialResolverMap,
1847
2067
  exportDirectiveTypeDefs,
1848
2068
  makeScalarAcceptExports,
2069
+ serialDirectiveTypeDefs,
1849
2070
  setCustomGraphQL,
1850
2071
  setCustomGraphQLTypes,
1851
2072
  useDataLoaderCleanup,