@technicity/data-service-generator 0.23.0-next.4 → 0.23.0-next.6

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.
@@ -1645,7 +1645,7 @@ function getRelationManyToOneFieldName(x) {
1645
1645
  return changeCase.camelCase(x.foreignKey.replace(new RegExp(x.referencedKey + "$", "i"), ""));
1646
1646
  }
1647
1647
  // TODO: not sure if this logic is correct
1648
- async function getJunctionTables() {
1648
+ const getJunctionTables = (0, memoize_1.default)(async function getJunctionTables() {
1649
1649
  const tables = await getTableNames();
1650
1650
  return (await Promise.all(tables.map(async (table) => {
1651
1651
  const relations = await getRelationsManyToOne(table);
@@ -1660,7 +1660,7 @@ async function getJunctionTables() {
1660
1660
  }
1661
1661
  return null;
1662
1662
  }))).filter(isNotNullOrUndefined_1.isNotNullOrUndefined);
1663
- }
1663
+ }, () => getCtx().runId);
1664
1664
  // `from` relations
1665
1665
  // https://stackoverflow.com/a/54732547
1666
1666
  const getRelationsManyToOne = (0, memoize_1.default)(async function getRelationsManyToOne(table) {
@@ -1690,7 +1690,8 @@ const getRelationsManyToOne = (0, memoize_1.default)(async function getRelations
1690
1690
  FROM information_schema.key_column_usage kcu
1691
1691
  JOIN information_schema.referential_constraints rc ON kcu.constraint_name = rc.constraint_name AND kcu.table_schema = rc.constraint_schema
1692
1692
  JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_name = ccu.constraint_name AND rc.unique_constraint_schema = ccu.table_schema
1693
- WHERE kcu.table_schema = 'public' AND kcu.table_name = $1`, [table]);
1693
+ WHERE kcu.table_schema = 'public' AND kcu.table_name = $1
1694
+ ORDER BY ccu.table_name, ccu.column_name`, [table]);
1694
1695
  }
1695
1696
  else {
1696
1697
  throw new Error("Unsupported dialect: " + dialect);
@@ -1704,7 +1705,7 @@ const getRelationsManyToOne = (0, memoize_1.default)(async function getRelations
1704
1705
  nullable: tableMeta.find((m) => m.Field === v.t1Field)?.Null === "YES"
1705
1706
  };
1706
1707
  })));
1707
- return _.sortBy((x) => x.referencedTable, xs);
1708
+ return _.sortBy([(x) => x.referencedTable, (x) => x.referencedKey, (x) => x.foreignKey], xs);
1708
1709
  }, (table) => getCtx().runId + ":" + table);
1709
1710
  // `to` relations
1710
1711
  const getRelationsOneToMany = (0, memoize_1.default)(async function getRelationsOneToMany(table) {
@@ -1733,7 +1734,8 @@ const getRelationsOneToMany = (0, memoize_1.default)(async function getRelations
1733
1734
  FROM information_schema.key_column_usage kcu
1734
1735
  JOIN information_schema.referential_constraints rc ON kcu.constraint_name = rc.constraint_name AND kcu.table_schema = rc.constraint_schema
1735
1736
  JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_name = ccu.constraint_name AND rc.unique_constraint_schema = ccu.table_schema
1736
- WHERE kcu.table_schema = 'public' AND ccu.table_name = $1`, [table]);
1737
+ WHERE kcu.table_schema = 'public' AND ccu.table_name = $1
1738
+ ORDER BY kcu.table_name, kcu.column_name`, [table]);
1737
1739
  }
1738
1740
  else {
1739
1741
  throw new Error("Unsupported dialect: " + dialect);
@@ -1747,7 +1749,7 @@ const getRelationsOneToMany = (0, memoize_1.default)(async function getRelations
1747
1749
  nullable: false
1748
1750
  };
1749
1751
  })));
1750
- return _.sortBy((x) => x.referencedKey, _.sortBy((x) => x.referencedTable, xs));
1752
+ return _.sortBy([(x) => x.referencedTable, (x) => x.referencedKey, (x) => x.foreignKey], xs);
1751
1753
  }, (table) => getCtx().runId + ":" + table);
1752
1754
  async function getPrimaryColumn(table) {
1753
1755
  const tableMeta = await getTableMeta(table);
@@ -1786,27 +1788,27 @@ async function getUuidColumn(table) {
1786
1788
  nullable: column.Null === "YES"
1787
1789
  };
1788
1790
  }
1789
- const getPgEnumDefinition = (0, memoize_1.default)(async function getPgEnumDefinition(udtName) {
1791
+ const getPgEnumDefinition = (0, memoize_1.default)(async function getPgEnumDefinition(udtSchema, udtName) {
1790
1792
  const { dialect, query } = getCtx();
1791
1793
  if (dialect !== "postgresql")
1792
1794
  return null;
1793
1795
  const rows = await query(`SELECT e.enumlabel FROM pg_enum e
1794
1796
  JOIN pg_type t ON e.enumtypid = t.oid
1795
1797
  JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid
1796
- WHERE t.typname = $1 AND n.nspname = 'public'
1797
- ORDER BY e.enumsortorder`, [udtName]);
1798
+ WHERE t.typname = $2 AND n.nspname = $1
1799
+ ORDER BY e.enumsortorder`, [udtSchema, udtName]);
1798
1800
  if (rows.length === 0)
1799
1801
  return null;
1800
1802
  const labels = rows.map((r) => String(r.enumlabel).replace(/'/g, "''"));
1801
1803
  return "enum('" + labels.join("', '") + "')";
1802
- }, (udtName) => getCtx().runId + ":" + udtName);
1804
+ }, (udtSchema, udtName) => getCtx().runId + ":" + udtSchema + ":" + udtName);
1803
1805
  const getTableMeta = (0, memoize_1.default)(async function getTableMeta(table) {
1804
1806
  const { dialect, query } = getCtx();
1805
1807
  if (dialect === "mysql") {
1806
1808
  return query("DESCRIBE ??", [table]).then((xs) => _.sortBy((x) => x.Field, xs));
1807
1809
  }
1808
1810
  if (dialect === "postgresql") {
1809
- const columns = await query(`SELECT column_name AS "Field", data_type, udt_name, character_maximum_length AS char_max, is_nullable, column_default AS "Default"
1811
+ const columns = await query(`SELECT column_name AS "Field", data_type, udt_schema, udt_name, character_maximum_length AS char_max, is_nullable, column_default AS "Default"
1810
1812
  FROM information_schema.columns
1811
1813
  WHERE table_schema = 'public' AND table_name = $1
1812
1814
  ORDER BY ordinal_position`, [table]);
@@ -1831,17 +1833,26 @@ const getTableMeta = (0, memoize_1.default)(async function getTableMeta(table) {
1831
1833
  if (!keyMap.has(k.col) || k.key_type === "PRI")
1832
1834
  keyMap.set(k.col, k.key_type);
1833
1835
  }
1834
- const udtNames = [
1835
- ...new Set(columns
1836
- .filter((c) => c.data_type === "USER-DEFINED" && c.udt_name != null)
1837
- .map((c) => c.udt_name))
1836
+ const udtKeys = [
1837
+ ...new Map(columns
1838
+ .filter((c) => c.data_type === "USER-DEFINED" &&
1839
+ c.udt_schema != null &&
1840
+ c.udt_name != null)
1841
+ .map((c) => [`${c.udt_schema}.${c.udt_name}`, c])).keys()
1838
1842
  ];
1839
- const enumDefs = await Promise.all(udtNames.map((udt) => getPgEnumDefinition(udt)));
1840
- const enumMap = new Map(udtNames.map((udt, i) => [udt, enumDefs[i] ?? "varchar(255)"]));
1843
+ const udtPairs = udtKeys.map((k) => {
1844
+ const [s, n] = k.split(".", 2);
1845
+ return [s, n];
1846
+ });
1847
+ const enumDefs = await Promise.all(udtPairs.map(([schema, name]) => getPgEnumDefinition(schema, name)));
1848
+ const enumMap = new Map(udtKeys.map((k, i) => [k, enumDefs[i] ?? "varchar(255)"]));
1841
1849
  const cols = columns.map((c) => {
1842
1850
  let type;
1843
- if (c.data_type === "USER-DEFINED" && c.udt_name != null) {
1844
- type = enumMap.get(c.udt_name) ?? "character varying(255)";
1851
+ if (c.data_type === "USER-DEFINED" &&
1852
+ c.udt_schema != null &&
1853
+ c.udt_name != null) {
1854
+ const enumKey = `${c.udt_schema}.${c.udt_name}`;
1855
+ type = enumMap.get(enumKey) ?? "character varying(255)";
1845
1856
  }
1846
1857
  else {
1847
1858
  type = c.data_type;
@@ -1855,8 +1866,13 @@ const getTableMeta = (0, memoize_1.default)(async function getTableMeta(table) {
1855
1866
  Type: type,
1856
1867
  Null: c.is_nullable === "YES" ? "YES" : "NO",
1857
1868
  Key: keyMap.get(c.Field) ?? "",
1858
- Default: c.Default ?? "",
1859
- ...(c.data_type === "USER-DEFINED" && c.udt_name != null
1869
+ // Preserve `null` when there is no default so that
1870
+ // required-field detection (via `hasDefault`) works
1871
+ // consistently with the MySQL `DESCRIBE` output.
1872
+ Default: c.Default,
1873
+ ...(c.data_type === "USER-DEFINED" &&
1874
+ c.udt_schema != null &&
1875
+ c.udt_name != null
1860
1876
  ? { PgType: c.udt_name }
1861
1877
  : {})
1862
1878
  };
@@ -2077,18 +2093,18 @@ function getPropertyFormat(sqlType) {
2077
2093
  }
2078
2094
  return undefined;
2079
2095
  }
2080
- async function getTableNames() {
2096
+ const getTableNames = (0, memoize_1.default)(async function getTableNames() {
2081
2097
  const { dialect, query } = getCtx();
2082
2098
  if (dialect === "mysql") {
2083
2099
  return query("SHOW TABLES").then((xs) => xs.flatMap((x) => Object.values(x)).sort());
2084
2100
  }
2085
2101
  if (dialect === "postgresql") {
2086
2102
  return query(`SELECT table_name FROM information_schema.tables
2087
- WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
2088
- ORDER BY table_name`).then((rows) => rows.map((r) => r.table_name));
2103
+ WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
2104
+ ORDER BY table_name`).then((rows) => rows.map((r) => r.table_name));
2089
2105
  }
2090
2106
  throw new Error("Unsupported dialect: " + dialect);
2091
- }
2107
+ }, () => getCtx().runId);
2092
2108
  function getMysql2sqliteSrc() {
2093
2109
  return `#!/usr/bin/awk -f
2094
2110
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technicity/data-service-generator",
3
- "version": "0.23.0-next.4",
3
+ "version": "0.23.0-next.6",
4
4
  "main": "./dist/index.js",
5
5
  "files": [
6
6
  "dist"