@smartive/graphql-magic 23.5.0-next.1 → 23.5.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/CHANGELOG.md CHANGED
@@ -1,20 +1,5 @@
1
- ## [23.5.0-next.1](https://github.com/smartive/graphql-magic/compare/v23.4.1...v23.5.0-next.1) (2026-02-09)
1
+ ## [23.5.0](https://github.com/smartive/graphql-magic/compare/v23.4.1...v23.5.0) (2026-02-09)
2
2
 
3
3
  ### Features
4
4
 
5
- * functions.sql and expression fiedls ([65d7079](https://github.com/smartive/graphql-magic/commit/65d7079b54da3a11300cb714a7ca70032e591204))
6
- * Use functions.ts instead of functions.sql ([58e0653](https://github.com/smartive/graphql-magic/commit/58e065347b2f3f1c80691911b5191af38586c1e2))
7
-
8
- ### Bug Fixes
9
-
10
- * Functions code order ([cf7f7a4](https://github.com/smartive/graphql-magic/commit/cf7f7a4421e8297af866c3ecc04b5e672862e6ab))
11
- * Generated expression handling ([e325eb2](https://github.com/smartive/graphql-magic/commit/e325eb232b7bbbbe7d65f9fae5221f4a764a8600))
12
- * improve handling of missing revision fields in migration updates ([4296662](https://github.com/smartive/graphql-magic/commit/429666247224ef782280fd6144cb749468b934cd))
13
- * Index ([42d109f](https://github.com/smartive/graphql-magic/commit/42d109fc6dbbf8fc7937f076403a69885779d8f6))
14
- * Linting ([2e997e4](https://github.com/smartive/graphql-magic/commit/2e997e464371a9d8cf05ceb67a6cd29a9452f615))
15
- * Omit more stuff ([df2ae04](https://github.com/smartive/graphql-magic/commit/df2ae044557166e876b7646d6ebe67a78df2722e))
16
- * Permissions ([c198115](https://github.com/smartive/graphql-magic/commit/c19811552ac3de05d4c1069116620067ec0a5540))
17
- * Temporarily disable tags ([52962c1](https://github.com/smartive/graphql-magic/commit/52962c1a792c1ae010ae542c23d50dd4f8486dde))
18
- * Trigger release ([2cd67b9](https://github.com/smartive/graphql-magic/commit/2cd67b91d33d101793c04eb87ad9c226bc0fdd0f))
19
- * Trigger release ([d5ac376](https://github.com/smartive/graphql-magic/commit/d5ac376533460921a638c71f4c9a69c83a057897))
20
- * Update functions ([3717f8a](https://github.com/smartive/graphql-magic/commit/3717f8aba9d908fbde8d2f49e7c21f87fe6a8d12))
5
+ * Functions migration generator ([0525bb5](https://github.com/smartive/graphql-magic/commit/0525bb5d182bdd258fd6408be32bfb9ce5146faa))
package/dist/bin/gqm.cjs CHANGED
@@ -763,6 +763,204 @@ var getColumnName = (field) => field.kind === "relation" ? field.foreignKey || `
763
763
  var import_cloneDeep2 = __toESM(require("lodash/cloneDeep"), 1);
764
764
  var import_flatMap = __toESM(require("lodash/flatMap"), 1);
765
765
 
766
+ // src/migrations/update-functions.ts
767
+ var normalizeWhitespace = (str) => {
768
+ return str.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").replace(/\s*;\s*/g, ";").trim();
769
+ };
770
+ var normalizeFunctionBody = (body) => {
771
+ return normalizeWhitespace(body);
772
+ };
773
+ var normalizeAggregateDefinition = (definition) => {
774
+ let normalized = definition.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").trim();
775
+ const initCondMatch = normalized.match(/INITCOND\s*=\s*([^,)]+)/i);
776
+ if (initCondMatch) {
777
+ const initCondValue = initCondMatch[1].trim();
778
+ const unquoted = initCondValue.replace(/^['"]|['"]$/g, "");
779
+ if (/^\d+$/.test(unquoted)) {
780
+ normalized = normalized.replace(/INITCOND\s*=\s*[^,)]+/i, `INITCOND = '${unquoted}'`);
781
+ }
782
+ }
783
+ return normalized;
784
+ };
785
+ var extractFunctionBody = (definition) => {
786
+ const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
787
+ if (dollarQuoteMatch) {
788
+ return dollarQuoteMatch[2].trim();
789
+ }
790
+ const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
791
+ if (bodyMatch) {
792
+ return bodyMatch[1].trim();
793
+ }
794
+ return definition;
795
+ };
796
+ var getDatabaseFunctions = async (knex2) => {
797
+ const regularFunctions = await knex2.raw(`
798
+ SELECT
799
+ p.proname as name,
800
+ pg_get_function_identity_arguments(p.oid) as arguments,
801
+ pg_get_functiondef(p.oid) as definition,
802
+ false as is_aggregate
803
+ FROM pg_proc p
804
+ JOIN pg_namespace n ON p.pronamespace = n.oid
805
+ WHERE n.nspname = 'public'
806
+ AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
807
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
808
+ `);
809
+ const aggregateFunctions = await knex2.raw(`
810
+ SELECT
811
+ p.proname as name,
812
+ pg_get_function_identity_arguments(p.oid) as arguments,
813
+ a.aggtransfn::regproc::text as trans_func,
814
+ a.aggfinalfn::regproc::text as final_func,
815
+ a.agginitval as init_val,
816
+ pg_catalog.format_type(a.aggtranstype, NULL) as state_type,
817
+ true as is_aggregate
818
+ FROM pg_proc p
819
+ JOIN pg_aggregate a ON p.oid = a.aggfnoid
820
+ JOIN pg_namespace n ON p.pronamespace = n.oid
821
+ WHERE n.nspname = 'public'
822
+ ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
823
+ `);
824
+ const result = [];
825
+ for (const row of regularFunctions.rows || []) {
826
+ const definition = row.definition || "";
827
+ const name2 = row.name || "";
828
+ const argumentsStr = row.arguments || "";
829
+ if (!definition) {
830
+ continue;
831
+ }
832
+ const signature = `${name2}(${argumentsStr})`;
833
+ const body = normalizeFunctionBody(extractFunctionBody(definition));
834
+ result.push({
835
+ name: name2,
836
+ signature,
837
+ body,
838
+ isAggregate: false,
839
+ definition
840
+ });
841
+ }
842
+ for (const row of aggregateFunctions.rows || []) {
843
+ const name2 = row.name || "";
844
+ const argumentsStr = row.arguments || "";
845
+ const transFunc = row.trans_func || "";
846
+ const finalFunc = row.final_func || "";
847
+ const initVal = row.init_val;
848
+ const stateType = row.state_type || "";
849
+ const signature = `${name2}(${argumentsStr})`;
850
+ let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (`;
851
+ aggregateDef += `SFUNC = ${transFunc}, STYPE = ${stateType}`;
852
+ if (finalFunc) {
853
+ aggregateDef += `, FINALFUNC = ${finalFunc}`;
854
+ }
855
+ if (initVal !== null && initVal !== void 0) {
856
+ let initValStr;
857
+ if (typeof initVal === "string") {
858
+ initValStr = `'${initVal}'`;
859
+ } else {
860
+ const numStr = String(initVal);
861
+ initValStr = /^\d+$/.test(numStr) ? `'${numStr}'` : numStr;
862
+ }
863
+ aggregateDef += `, INITCOND = ${initValStr}`;
864
+ }
865
+ aggregateDef += ");";
866
+ result.push({
867
+ name: name2,
868
+ signature,
869
+ body: normalizeAggregateDefinition(aggregateDef),
870
+ isAggregate: true,
871
+ definition: aggregateDef
872
+ });
873
+ }
874
+ return result;
875
+ };
876
+ var compareFunctions = (defined, db) => {
877
+ const definedBody = normalizeFunctionBody(defined.body);
878
+ const dbBody = normalizeFunctionBody(db.body);
879
+ if (definedBody !== dbBody) {
880
+ const definedPreview = definedBody.length > 200 ? `${definedBody.substring(0, 200)}...` : definedBody;
881
+ const dbPreview = dbBody.length > 200 ? `${dbBody.substring(0, 200)}...` : dbBody;
882
+ return {
883
+ changed: true,
884
+ diff: `Definition changed:
885
+ File: ${definedPreview}
886
+ DB: ${dbPreview}`
887
+ };
888
+ }
889
+ return { changed: false };
890
+ };
891
+ var updateFunctions = async (knex2, parsedFunctions) => {
892
+ if (parsedFunctions.length === 0) {
893
+ return;
894
+ }
895
+ const definedFunctions = parsedFunctions;
896
+ const dbFunctions = await getDatabaseFunctions(knex2);
897
+ const dbFunctionsBySignature = /* @__PURE__ */ new Map();
898
+ for (const func of dbFunctions) {
899
+ dbFunctionsBySignature.set(func.signature, func);
900
+ }
901
+ console.info(`Found ${definedFunctions.length} function(s) in file, ${dbFunctions.length} function(s) in database.`);
902
+ let updatedCount = 0;
903
+ let skippedCount = 0;
904
+ for (const definedFunc of definedFunctions) {
905
+ const dbFunc = dbFunctionsBySignature.get(definedFunc.signature);
906
+ if (!dbFunc) {
907
+ try {
908
+ await knex2.raw(definedFunc.fullDefinition);
909
+ console.info(`\u2713 Created ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}`);
910
+ updatedCount++;
911
+ } catch (error) {
912
+ console.error(
913
+ `\u2717 Failed to create ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
914
+ error.message
915
+ );
916
+ throw error;
917
+ }
918
+ } else {
919
+ const comparison = compareFunctions(definedFunc, dbFunc);
920
+ if (comparison.changed) {
921
+ console.info(`
922
+ \u26A0 ${definedFunc.isAggregate ? "Aggregate" : "Function"} ${definedFunc.signature} has changes:`);
923
+ if (comparison.diff) {
924
+ console.info(comparison.diff);
925
+ }
926
+ try {
927
+ if (definedFunc.isAggregate) {
928
+ const dropMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+([^(]+)\(/i);
929
+ if (dropMatch) {
930
+ const functionName = dropMatch[2].trim();
931
+ const argsMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+[^(]+\(([^)]*)\)/i);
932
+ const args2 = argsMatch ? argsMatch[2].trim() : "";
933
+ await knex2.raw(`DROP AGGREGATE IF EXISTS ${functionName}${args2 ? `(${args2})` : ""}`);
934
+ }
935
+ }
936
+ await knex2.raw(definedFunc.fullDefinition);
937
+ console.info(`\u2713 Updated ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}
938
+ `);
939
+ updatedCount++;
940
+ } catch (error) {
941
+ console.error(
942
+ `\u2717 Failed to update ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
943
+ error.message
944
+ );
945
+ throw error;
946
+ }
947
+ } else {
948
+ console.info(
949
+ `\u25CB Skipped ${definedFunc.isAggregate ? "aggregate" : "function"} (unchanged): ${definedFunc.signature}`
950
+ );
951
+ skippedCount++;
952
+ }
953
+ }
954
+ }
955
+ console.info(`
956
+ Summary: ${updatedCount} updated, ${skippedCount} skipped`);
957
+ if (updatedCount > 0) {
958
+ console.info("Functions updated successfully.");
959
+ } else {
960
+ console.info("All functions are up to date.");
961
+ }
962
+ };
963
+
766
964
  // src/migrations/generate.ts
767
965
  var MigrationGenerator = class {
768
966
  constructor(knex2, models, parsedFunctions) {
@@ -1327,7 +1525,7 @@ var MigrationGenerator = class {
1327
1525
  this.writer.write(`, ALTER COLUMN "${name2}" SET EXPRESSION AS (${field.generateAs.expression})`);
1328
1526
  } else {
1329
1527
  this.writer.write(
1330
- `${alter ? "ALTER" : "ADD"} COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs.expression}) STORED`
1528
+ `ADD COLUMN "${name2}" ${type}${nonNull2() ? " not null" : ""} GENERATED ALWAYS AS (${field.generateAs.expression}) STORED`
1331
1529
  );
1332
1530
  }
1333
1531
  return;
@@ -1523,118 +1721,12 @@ var MigrationGenerator = class {
1523
1721
  }
1524
1722
  return false;
1525
1723
  }
1526
- normalizeFunctionBody(body) {
1527
- return body.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").trim();
1528
- }
1529
- normalizeAggregateDefinition(definition) {
1530
- let normalized = definition.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").trim();
1531
- const initCondMatch = normalized.match(/INITCOND\s*=\s*([^,)]+)/i);
1532
- if (initCondMatch) {
1533
- const initCondValue = initCondMatch[1].trim();
1534
- const unquoted = initCondValue.replace(/^['"]|['"]$/g, "");
1535
- if (/^\d+$/.test(unquoted)) {
1536
- normalized = normalized.replace(/INITCOND\s*=\s*[^,)]+/i, `INITCOND = '${unquoted}'`);
1537
- }
1538
- }
1539
- return normalized;
1540
- }
1541
- extractFunctionBody(definition) {
1542
- const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
1543
- if (dollarQuoteMatch) {
1544
- return dollarQuoteMatch[2].trim();
1545
- }
1546
- const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
1547
- if (bodyMatch) {
1548
- return bodyMatch[1].trim();
1549
- }
1550
- return definition;
1551
- }
1552
- async getDatabaseFunctions() {
1553
- const regularFunctions = await this.knex.raw(`
1554
- SELECT
1555
- p.proname as name,
1556
- pg_get_function_identity_arguments(p.oid) as arguments,
1557
- pg_get_functiondef(p.oid) as definition,
1558
- false as is_aggregate
1559
- FROM pg_proc p
1560
- JOIN pg_namespace n ON p.pronamespace = n.oid
1561
- WHERE n.nspname = 'public'
1562
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1563
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1564
- `);
1565
- const aggregateFunctions = await this.knex.raw(`
1566
- SELECT
1567
- p.proname as name,
1568
- pg_get_function_identity_arguments(p.oid) as arguments,
1569
- a.aggtransfn::regproc::text as trans_func,
1570
- a.aggfinalfn::regproc::text as final_func,
1571
- a.agginitval as init_val,
1572
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type,
1573
- true as is_aggregate
1574
- FROM pg_proc p
1575
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1576
- JOIN pg_namespace n ON p.pronamespace = n.oid
1577
- WHERE n.nspname = 'public'
1578
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1579
- `);
1580
- const result = [];
1581
- for (const row of regularFunctions.rows || []) {
1582
- const definition = row.definition || "";
1583
- const name2 = row.name || "";
1584
- const argumentsStr = row.arguments || "";
1585
- if (!definition) {
1586
- continue;
1587
- }
1588
- const signature = `${name2}(${argumentsStr})`;
1589
- const body = this.normalizeFunctionBody(this.extractFunctionBody(definition));
1590
- result.push({
1591
- name: name2,
1592
- signature,
1593
- body,
1594
- isAggregate: false,
1595
- definition
1596
- });
1597
- }
1598
- for (const row of aggregateFunctions.rows || []) {
1599
- const name2 = row.name || "";
1600
- const argumentsStr = row.arguments || "";
1601
- const transFunc = row.trans_func || "";
1602
- const finalFunc = row.final_func || "";
1603
- const initVal = row.init_val;
1604
- const stateType = row.state_type || "";
1605
- const signature = `${name2}(${argumentsStr})`;
1606
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (`;
1607
- aggregateDef += `SFUNC = ${transFunc}, STYPE = ${stateType}`;
1608
- if (finalFunc) {
1609
- aggregateDef += `, FINALFUNC = ${finalFunc}`;
1610
- }
1611
- if (initVal !== null && initVal !== void 0) {
1612
- let initValStr;
1613
- if (typeof initVal === "string") {
1614
- initValStr = `'${initVal}'`;
1615
- } else {
1616
- const numStr = String(initVal);
1617
- initValStr = /^\d+$/.test(numStr) ? `'${numStr}'` : numStr;
1618
- }
1619
- aggregateDef += `, INITCOND = ${initValStr}`;
1620
- }
1621
- aggregateDef += ");";
1622
- result.push({
1623
- name: name2,
1624
- signature,
1625
- body: this.normalizeAggregateDefinition(aggregateDef),
1626
- isAggregate: true,
1627
- definition: aggregateDef
1628
- });
1629
- }
1630
- return result;
1631
- }
1632
1724
  async handleFunctions(up, down) {
1633
1725
  if (!this.parsedFunctions || this.parsedFunctions.length === 0) {
1634
1726
  return;
1635
1727
  }
1636
1728
  const definedFunctions = this.parsedFunctions;
1637
- const dbFunctions = await this.getDatabaseFunctions();
1729
+ const dbFunctions = await getDatabaseFunctions(this.knex);
1638
1730
  const dbFunctionsBySignature = /* @__PURE__ */ new Map();
1639
1731
  for (const func of dbFunctions) {
1640
1732
  dbFunctionsBySignature.set(func.signature, func);
@@ -1664,8 +1756,8 @@ var MigrationGenerator = class {
1664
1756
  }
1665
1757
  });
1666
1758
  } else {
1667
- const dbBody = dbFunc.isAggregate ? this.normalizeAggregateDefinition(dbFunc.body) : this.normalizeFunctionBody(dbFunc.body);
1668
- const definedBody = definedFunc.isAggregate ? this.normalizeAggregateDefinition(definedFunc.body) : this.normalizeFunctionBody(definedFunc.body);
1759
+ const dbBody = dbFunc.isAggregate ? normalizeAggregateDefinition(dbFunc.body) : normalizeFunctionBody(dbFunc.body);
1760
+ const definedBody = definedFunc.isAggregate ? normalizeAggregateDefinition(definedFunc.body) : normalizeFunctionBody(definedFunc.body);
1669
1761
  if (dbBody !== definedBody) {
1670
1762
  const oldDefinition = dbFunc.definition || dbFunc.body;
1671
1763
  up.push(() => {
@@ -1780,186 +1872,6 @@ ${functionsArrayString},
1780
1872
  `;
1781
1873
  };
1782
1874
 
1783
- // src/migrations/update-functions.ts
1784
- var normalizeWhitespace = (str) => {
1785
- return str.replace(/\s+/g, " ").replace(/\s*\(\s*/g, "(").replace(/\s*\)\s*/g, ")").replace(/\s*,\s*/g, ",").replace(/\s*;\s*/g, ";").trim();
1786
- };
1787
- var normalizeFunctionBody = (body) => {
1788
- return normalizeWhitespace(body);
1789
- };
1790
- var extractFunctionBody = (definition) => {
1791
- const dollarQuoteMatch = definition.match(/AS\s+\$([^$]*)\$([\s\S]*?)\$\1\$/i);
1792
- if (dollarQuoteMatch) {
1793
- return dollarQuoteMatch[2].trim();
1794
- }
1795
- const bodyMatch = definition.match(/AS\s+\$\$([\s\S]*?)\$\$/i) || definition.match(/AS\s+['"]([\s\S]*?)['"]/i);
1796
- if (bodyMatch) {
1797
- return bodyMatch[1].trim();
1798
- }
1799
- return definition;
1800
- };
1801
- var getDatabaseFunctions = async (knex2) => {
1802
- const regularFunctions = await knex2.raw(`
1803
- SELECT
1804
- p.proname as name,
1805
- pg_get_function_identity_arguments(p.oid) as arguments,
1806
- pg_get_functiondef(p.oid) as definition,
1807
- false as is_aggregate
1808
- FROM pg_proc p
1809
- JOIN pg_namespace n ON p.pronamespace = n.oid
1810
- WHERE n.nspname = 'public'
1811
- AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid)
1812
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1813
- `);
1814
- const aggregateFunctions = await knex2.raw(`
1815
- SELECT
1816
- p.proname as name,
1817
- pg_get_function_identity_arguments(p.oid) as arguments,
1818
- a.aggtransfn::regproc::text as trans_func,
1819
- a.aggfinalfn::regproc::text as final_func,
1820
- a.agginitval as init_val,
1821
- pg_catalog.format_type(a.aggtranstype, NULL) as state_type,
1822
- true as is_aggregate
1823
- FROM pg_proc p
1824
- JOIN pg_aggregate a ON p.oid = a.aggfnoid
1825
- JOIN pg_namespace n ON p.pronamespace = n.oid
1826
- WHERE n.nspname = 'public'
1827
- ORDER BY p.proname, pg_get_function_identity_arguments(p.oid)
1828
- `);
1829
- const result = [];
1830
- for (const row of regularFunctions.rows || []) {
1831
- const definition = row.definition || "";
1832
- const name2 = row.name || "";
1833
- const argumentsStr = row.arguments || "";
1834
- if (!definition) {
1835
- continue;
1836
- }
1837
- const signature = `${name2}(${argumentsStr})`;
1838
- const body = normalizeFunctionBody(extractFunctionBody(definition));
1839
- result.push({
1840
- name: name2,
1841
- signature,
1842
- body,
1843
- isAggregate: false,
1844
- definition
1845
- });
1846
- }
1847
- for (const row of aggregateFunctions.rows || []) {
1848
- const name2 = row.name || "";
1849
- const argumentsStr = row.arguments || "";
1850
- const transFunc = row.trans_func || "";
1851
- const finalFunc = row.final_func || "";
1852
- const initVal = row.init_val;
1853
- const stateType = row.state_type || "";
1854
- const signature = `${name2}(${argumentsStr})`;
1855
- let aggregateDef = `CREATE AGGREGATE ${name2}(${argumentsStr}) (`;
1856
- aggregateDef += `SFUNC = ${transFunc}, STYPE = ${stateType}`;
1857
- if (finalFunc) {
1858
- aggregateDef += `, FINALFUNC = ${finalFunc}`;
1859
- }
1860
- if (initVal !== null && initVal !== void 0) {
1861
- const initValStr = typeof initVal === "string" ? `'${initVal}'` : String(initVal);
1862
- aggregateDef += `, INITCOND = ${initValStr}`;
1863
- }
1864
- aggregateDef += ");";
1865
- result.push({
1866
- name: name2,
1867
- signature,
1868
- body: normalizeFunctionBody(aggregateDef),
1869
- isAggregate: true,
1870
- definition: aggregateDef
1871
- });
1872
- }
1873
- return result;
1874
- };
1875
- var compareFunctions = (defined, db) => {
1876
- const definedBody = normalizeFunctionBody(defined.body);
1877
- const dbBody = normalizeFunctionBody(db.body);
1878
- if (definedBody !== dbBody) {
1879
- const definedPreview = definedBody.length > 200 ? `${definedBody.substring(0, 200)}...` : definedBody;
1880
- const dbPreview = dbBody.length > 200 ? `${dbBody.substring(0, 200)}...` : dbBody;
1881
- return {
1882
- changed: true,
1883
- diff: `Definition changed:
1884
- File: ${definedPreview}
1885
- DB: ${dbPreview}`
1886
- };
1887
- }
1888
- return { changed: false };
1889
- };
1890
- var updateFunctions = async (knex2, parsedFunctions) => {
1891
- if (parsedFunctions.length === 0) {
1892
- return;
1893
- }
1894
- const definedFunctions = parsedFunctions;
1895
- const dbFunctions = await getDatabaseFunctions(knex2);
1896
- const dbFunctionsBySignature = /* @__PURE__ */ new Map();
1897
- for (const func of dbFunctions) {
1898
- dbFunctionsBySignature.set(func.signature, func);
1899
- }
1900
- console.info(`Found ${definedFunctions.length} function(s) in file, ${dbFunctions.length} function(s) in database.`);
1901
- let updatedCount = 0;
1902
- let skippedCount = 0;
1903
- for (const definedFunc of definedFunctions) {
1904
- const dbFunc = dbFunctionsBySignature.get(definedFunc.signature);
1905
- if (!dbFunc) {
1906
- try {
1907
- await knex2.raw(definedFunc.fullDefinition);
1908
- console.info(`\u2713 Created ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}`);
1909
- updatedCount++;
1910
- } catch (error) {
1911
- console.error(
1912
- `\u2717 Failed to create ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
1913
- error.message
1914
- );
1915
- throw error;
1916
- }
1917
- } else {
1918
- const comparison = compareFunctions(definedFunc, dbFunc);
1919
- if (comparison.changed) {
1920
- console.info(`
1921
- \u26A0 ${definedFunc.isAggregate ? "Aggregate" : "Function"} ${definedFunc.signature} has changes:`);
1922
- if (comparison.diff) {
1923
- console.info(comparison.diff);
1924
- }
1925
- try {
1926
- if (definedFunc.isAggregate) {
1927
- const dropMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+([^(]+)\(/i);
1928
- if (dropMatch) {
1929
- const functionName = dropMatch[2].trim();
1930
- const argsMatch = definedFunc.fullDefinition.match(/CREATE\s+(OR\s+REPLACE\s+)?AGGREGATE\s+[^(]+\(([^)]*)\)/i);
1931
- const args2 = argsMatch ? argsMatch[2].trim() : "";
1932
- await knex2.raw(`DROP AGGREGATE IF EXISTS ${functionName}${args2 ? `(${args2})` : ""}`);
1933
- }
1934
- }
1935
- await knex2.raw(definedFunc.fullDefinition);
1936
- console.info(`\u2713 Updated ${definedFunc.isAggregate ? "aggregate" : "function"}: ${definedFunc.signature}
1937
- `);
1938
- updatedCount++;
1939
- } catch (error) {
1940
- console.error(
1941
- `\u2717 Failed to update ${definedFunc.isAggregate ? "aggregate" : "function"} ${definedFunc.signature}:`,
1942
- error.message
1943
- );
1944
- throw error;
1945
- }
1946
- } else {
1947
- console.info(
1948
- `\u25CB Skipped ${definedFunc.isAggregate ? "aggregate" : "function"} (unchanged): ${definedFunc.signature}`
1949
- );
1950
- skippedCount++;
1951
- }
1952
- }
1953
- }
1954
- console.info(`
1955
- Summary: ${updatedCount} updated, ${skippedCount} skipped`);
1956
- if (updatedCount > 0) {
1957
- console.info("Functions updated successfully.");
1958
- } else {
1959
- console.info("All functions are up to date.");
1960
- }
1961
- };
1962
-
1963
1875
  // src/permissions/generate.ts
1964
1876
  var ACTIONS = ["READ", "CREATE", "UPDATE", "DELETE", "RESTORE", "LINK"];
1965
1877
 
@@ -3120,7 +3032,7 @@ var normalizeWhitespace2 = (str) => {
3120
3032
  var normalizeFunctionBody2 = (body) => {
3121
3033
  return normalizeWhitespace2(body);
3122
3034
  };
3123
- var normalizeAggregateDefinition = (definition) => {
3035
+ var normalizeAggregateDefinition2 = (definition) => {
3124
3036
  let normalized = normalizeWhitespace2(definition);
3125
3037
  const initCondMatch = normalized.match(/INITCOND\s*=\s*([^,)]+)/i);
3126
3038
  if (initCondMatch) {
@@ -3204,7 +3116,7 @@ var parseFunctionsFile = (filePath) => {
3204
3116
  parsedFunctions.push({
3205
3117
  name: name2,
3206
3118
  signature,
3207
- body: isAggregate ? normalizeAggregateDefinition(body) : normalizeFunctionBody2(body),
3119
+ body: isAggregate ? normalizeAggregateDefinition2(body) : normalizeFunctionBody2(body),
3208
3120
  fullDefinition: trimmedDefinition,
3209
3121
  isAggregate
3210
3122
  });