@launchsecure/launch-kit 0.0.19 → 0.0.20
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/dist/server/chart-serve.js +157 -38
- package/dist/server/cli.js +157 -38
- package/dist/server/graph-mcp-entry.js +158 -39
- package/package.json +1 -1
|
@@ -1694,51 +1694,149 @@ function pgTypeToPrisma(pgType) {
|
|
|
1694
1694
|
const upper = pgType.toUpperCase().trim();
|
|
1695
1695
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
1696
1696
|
}
|
|
1697
|
+
var ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
1698
|
+
var QID = `(?:${ID}\\.)?${ID}`;
|
|
1699
|
+
function bareName(captured) {
|
|
1700
|
+
const parts = captured.split(".");
|
|
1701
|
+
const last = parts[parts.length - 1];
|
|
1702
|
+
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
1703
|
+
}
|
|
1697
1704
|
function parseCreateTable(sql, state) {
|
|
1698
|
-
const re =
|
|
1705
|
+
const re = new RegExp(
|
|
1706
|
+
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
1707
|
+
"gi"
|
|
1708
|
+
);
|
|
1699
1709
|
let m;
|
|
1700
1710
|
while ((m = re.exec(sql)) !== null) {
|
|
1701
|
-
const tableName = m[1];
|
|
1711
|
+
const tableName = bareName(m[1]);
|
|
1702
1712
|
const body = m[2];
|
|
1703
1713
|
const columns = /* @__PURE__ */ new Map();
|
|
1704
1714
|
let primaryCol = null;
|
|
1705
|
-
|
|
1706
|
-
|
|
1715
|
+
const inlineFks = [];
|
|
1716
|
+
const lines = splitTopLevelCommas(body);
|
|
1717
|
+
for (const raw of lines) {
|
|
1718
|
+
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
1707
1719
|
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
1708
|
-
const
|
|
1709
|
-
if (
|
|
1710
|
-
primaryCol =
|
|
1720
|
+
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1721
|
+
if (namedPk) {
|
|
1722
|
+
primaryCol = bareName(namedPk[1]);
|
|
1711
1723
|
continue;
|
|
1712
1724
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1725
|
+
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1726
|
+
if (tablePk) {
|
|
1727
|
+
primaryCol = bareName(tablePk[1]);
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
1731
|
+
const namedFk = trimmed.match(new RegExp(
|
|
1732
|
+
`^CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1733
|
+
"i"
|
|
1734
|
+
));
|
|
1735
|
+
if (namedFk) {
|
|
1736
|
+
inlineFks.push({
|
|
1737
|
+
constraintName: bareName(namedFk[1]),
|
|
1738
|
+
sourceTable: tableName,
|
|
1739
|
+
sourceColumn: bareName(namedFk[2]),
|
|
1740
|
+
targetTable: bareName(namedFk[3]),
|
|
1741
|
+
targetColumn: bareName(namedFk[4]),
|
|
1742
|
+
onDelete: namedFk[5] ?? null
|
|
1743
|
+
});
|
|
1744
|
+
continue;
|
|
1745
|
+
}
|
|
1746
|
+
const bareFk = trimmed.match(new RegExp(
|
|
1747
|
+
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1748
|
+
"i"
|
|
1749
|
+
));
|
|
1750
|
+
if (bareFk) {
|
|
1751
|
+
inlineFks.push({
|
|
1752
|
+
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
1753
|
+
sourceTable: tableName,
|
|
1754
|
+
sourceColumn: bareName(bareFk[1]),
|
|
1755
|
+
targetTable: bareName(bareFk[2]),
|
|
1756
|
+
targetColumn: bareName(bareFk[3]),
|
|
1757
|
+
onDelete: bareFk[4] ?? null
|
|
1758
|
+
});
|
|
1759
|
+
continue;
|
|
1760
|
+
}
|
|
1761
|
+
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
1762
|
+
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
1715
1763
|
if (!colMatch) continue;
|
|
1716
|
-
const colName = colMatch[1];
|
|
1764
|
+
const colName = bareName(colMatch[1]);
|
|
1717
1765
|
let rest = colMatch[2];
|
|
1766
|
+
const inlineRefMatch = rest.match(new RegExp(
|
|
1767
|
+
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1768
|
+
"i"
|
|
1769
|
+
));
|
|
1770
|
+
if (inlineRefMatch) {
|
|
1771
|
+
inlineFks.push({
|
|
1772
|
+
constraintName: `${tableName}_${colName}_fkey`,
|
|
1773
|
+
sourceTable: tableName,
|
|
1774
|
+
sourceColumn: colName,
|
|
1775
|
+
targetTable: bareName(inlineRefMatch[1]),
|
|
1776
|
+
targetColumn: bareName(inlineRefMatch[2]),
|
|
1777
|
+
onDelete: inlineRefMatch[3] ?? null
|
|
1778
|
+
});
|
|
1779
|
+
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
1780
|
+
}
|
|
1718
1781
|
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
1782
|
+
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
1783
|
+
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
1719
1784
|
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
1720
1785
|
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
1721
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
1786
|
+
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bPRIMARY\s+KEY\b/gi, "").replace(/\bUNIQUE\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
1722
1787
|
columns.set(colName, {
|
|
1723
1788
|
name: colName,
|
|
1724
1789
|
type: colType,
|
|
1725
|
-
nullable: !isNotNull,
|
|
1726
|
-
primary:
|
|
1727
|
-
unique:
|
|
1790
|
+
nullable: !isNotNull && !isPrimaryKey,
|
|
1791
|
+
primary: isPrimaryKey,
|
|
1792
|
+
unique: isUnique,
|
|
1728
1793
|
default: defaultVal
|
|
1729
1794
|
});
|
|
1795
|
+
if (isPrimaryKey) primaryCol = colName;
|
|
1730
1796
|
}
|
|
1731
1797
|
if (primaryCol && columns.has(primaryCol)) {
|
|
1732
1798
|
columns.get(primaryCol).primary = true;
|
|
1733
1799
|
}
|
|
1734
1800
|
state.tables.set(tableName, { name: tableName, columns });
|
|
1801
|
+
state.fks.push(...inlineFks);
|
|
1735
1802
|
}
|
|
1736
1803
|
}
|
|
1804
|
+
function splitTopLevelCommas(body) {
|
|
1805
|
+
const out = [];
|
|
1806
|
+
let depth = 0;
|
|
1807
|
+
let buf = "";
|
|
1808
|
+
let inString = null;
|
|
1809
|
+
for (const ch of body) {
|
|
1810
|
+
if (inString) {
|
|
1811
|
+
buf += ch;
|
|
1812
|
+
if (ch === inString) inString = null;
|
|
1813
|
+
continue;
|
|
1814
|
+
}
|
|
1815
|
+
if (ch === "'" || ch === '"') {
|
|
1816
|
+
inString = ch;
|
|
1817
|
+
buf += ch;
|
|
1818
|
+
continue;
|
|
1819
|
+
}
|
|
1820
|
+
if (ch === "(") depth++;
|
|
1821
|
+
else if (ch === ")") depth--;
|
|
1822
|
+
if (ch === "," && depth === 0) {
|
|
1823
|
+
out.push(buf);
|
|
1824
|
+
buf = "";
|
|
1825
|
+
continue;
|
|
1826
|
+
}
|
|
1827
|
+
buf += ch;
|
|
1828
|
+
}
|
|
1829
|
+
if (buf.trim()) out.push(buf);
|
|
1830
|
+
return out;
|
|
1831
|
+
}
|
|
1737
1832
|
function parseCreateEnum(sql, state) {
|
|
1738
|
-
const re =
|
|
1833
|
+
const re = new RegExp(
|
|
1834
|
+
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
1835
|
+
"gi"
|
|
1836
|
+
);
|
|
1739
1837
|
let m;
|
|
1740
1838
|
while ((m = re.exec(sql)) !== null) {
|
|
1741
|
-
const enumName = m[1];
|
|
1839
|
+
const enumName = bareName(m[1]);
|
|
1742
1840
|
const valuesStr = m[2];
|
|
1743
1841
|
const values = new Set(
|
|
1744
1842
|
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
@@ -1747,11 +1845,14 @@ function parseCreateEnum(sql, state) {
|
|
|
1747
1845
|
}
|
|
1748
1846
|
}
|
|
1749
1847
|
function parseAlterTable(sql, state) {
|
|
1750
|
-
const addColRe =
|
|
1848
|
+
const addColRe = new RegExp(
|
|
1849
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
1850
|
+
"gi"
|
|
1851
|
+
);
|
|
1751
1852
|
let m;
|
|
1752
1853
|
while ((m = addColRe.exec(sql)) !== null) {
|
|
1753
|
-
const tableName = m[1];
|
|
1754
|
-
const colName = m[2];
|
|
1854
|
+
const tableName = bareName(m[1]);
|
|
1855
|
+
const colName = bareName(m[2]);
|
|
1755
1856
|
let rest = m[3];
|
|
1756
1857
|
const table = state.tables.get(tableName);
|
|
1757
1858
|
if (!table) continue;
|
|
@@ -1768,48 +1869,66 @@ function parseAlterTable(sql, state) {
|
|
|
1768
1869
|
default: defaultVal
|
|
1769
1870
|
});
|
|
1770
1871
|
}
|
|
1771
|
-
const dropColRe =
|
|
1872
|
+
const dropColRe = new RegExp(
|
|
1873
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1874
|
+
"gi"
|
|
1875
|
+
);
|
|
1772
1876
|
while ((m = dropColRe.exec(sql)) !== null) {
|
|
1773
|
-
const table = state.tables.get(m[1]);
|
|
1774
|
-
if (table) table.columns.delete(m[2]);
|
|
1877
|
+
const table = state.tables.get(bareName(m[1]));
|
|
1878
|
+
if (table) table.columns.delete(bareName(m[2]));
|
|
1775
1879
|
}
|
|
1776
|
-
const fkRe =
|
|
1880
|
+
const fkRe = new RegExp(
|
|
1881
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1882
|
+
"gi"
|
|
1883
|
+
);
|
|
1777
1884
|
while ((m = fkRe.exec(sql)) !== null) {
|
|
1778
1885
|
state.fks.push({
|
|
1779
|
-
constraintName: m[2],
|
|
1780
|
-
sourceTable: m[1],
|
|
1781
|
-
sourceColumn: m[3],
|
|
1782
|
-
targetTable: m[4],
|
|
1783
|
-
targetColumn: m[5],
|
|
1886
|
+
constraintName: bareName(m[2]),
|
|
1887
|
+
sourceTable: bareName(m[1]),
|
|
1888
|
+
sourceColumn: bareName(m[3]),
|
|
1889
|
+
targetTable: bareName(m[4]),
|
|
1890
|
+
targetColumn: bareName(m[5]),
|
|
1784
1891
|
onDelete: m[6] ?? null
|
|
1785
1892
|
});
|
|
1786
1893
|
}
|
|
1787
1894
|
}
|
|
1788
1895
|
function parseAlterEnum(sql, state) {
|
|
1789
|
-
const re =
|
|
1896
|
+
const re = new RegExp(
|
|
1897
|
+
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
1898
|
+
"gi"
|
|
1899
|
+
);
|
|
1790
1900
|
let m;
|
|
1791
1901
|
while ((m = re.exec(sql)) !== null) {
|
|
1792
|
-
const en = state.enums.get(m[1]);
|
|
1902
|
+
const en = state.enums.get(bareName(m[1]));
|
|
1793
1903
|
if (en) en.values.add(m[2]);
|
|
1794
1904
|
}
|
|
1795
1905
|
}
|
|
1796
1906
|
function parseDropTable(sql, state) {
|
|
1797
|
-
const re =
|
|
1907
|
+
const re = new RegExp(
|
|
1908
|
+
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1909
|
+
"gi"
|
|
1910
|
+
);
|
|
1798
1911
|
let m;
|
|
1799
1912
|
while ((m = re.exec(sql)) !== null) {
|
|
1800
|
-
|
|
1801
|
-
state.
|
|
1913
|
+
const dropped = bareName(m[1]);
|
|
1914
|
+
state.tables.delete(dropped);
|
|
1915
|
+
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
1802
1916
|
}
|
|
1803
1917
|
}
|
|
1804
1918
|
function parseUniqueIndex(sql, state) {
|
|
1805
|
-
const re =
|
|
1919
|
+
const re = new RegExp(
|
|
1920
|
+
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
1921
|
+
"gi"
|
|
1922
|
+
);
|
|
1806
1923
|
let m;
|
|
1807
1924
|
while ((m = re.exec(sql)) !== null) {
|
|
1808
|
-
const
|
|
1809
|
-
const
|
|
1925
|
+
const tableName = bareName(m[1]);
|
|
1926
|
+
const colName = bareName(m[2]);
|
|
1927
|
+
const table = state.tables.get(tableName);
|
|
1928
|
+
const col = table?.columns.get(colName);
|
|
1810
1929
|
if (col) col.unique = true;
|
|
1811
|
-
if (!state.uniqueIndexes.has(
|
|
1812
|
-
state.uniqueIndexes.get(
|
|
1930
|
+
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
1931
|
+
state.uniqueIndexes.get(tableName).add(colName);
|
|
1813
1932
|
}
|
|
1814
1933
|
}
|
|
1815
1934
|
function discoverMigrationFiles(migrationsDir) {
|
package/dist/server/cli.js
CHANGED
|
@@ -8051,51 +8051,149 @@ function pgTypeToPrisma(pgType) {
|
|
|
8051
8051
|
const upper = pgType.toUpperCase().trim();
|
|
8052
8052
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
8053
8053
|
}
|
|
8054
|
+
var ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
8055
|
+
var QID = `(?:${ID}\\.)?${ID}`;
|
|
8056
|
+
function bareName(captured) {
|
|
8057
|
+
const parts = captured.split(".");
|
|
8058
|
+
const last = parts[parts.length - 1];
|
|
8059
|
+
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
8060
|
+
}
|
|
8054
8061
|
function parseCreateTable(sql, state) {
|
|
8055
|
-
const re =
|
|
8062
|
+
const re = new RegExp(
|
|
8063
|
+
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
8064
|
+
"gi"
|
|
8065
|
+
);
|
|
8056
8066
|
let m;
|
|
8057
8067
|
while ((m = re.exec(sql)) !== null) {
|
|
8058
|
-
const tableName = m[1];
|
|
8068
|
+
const tableName = bareName(m[1]);
|
|
8059
8069
|
const body = m[2];
|
|
8060
8070
|
const columns = /* @__PURE__ */ new Map();
|
|
8061
8071
|
let primaryCol = null;
|
|
8062
|
-
|
|
8063
|
-
|
|
8072
|
+
const inlineFks = [];
|
|
8073
|
+
const lines = splitTopLevelCommas(body);
|
|
8074
|
+
for (const raw of lines) {
|
|
8075
|
+
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
8064
8076
|
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
8065
|
-
const
|
|
8066
|
-
if (
|
|
8067
|
-
primaryCol =
|
|
8077
|
+
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
8078
|
+
if (namedPk) {
|
|
8079
|
+
primaryCol = bareName(namedPk[1]);
|
|
8068
8080
|
continue;
|
|
8069
8081
|
}
|
|
8070
|
-
|
|
8071
|
-
|
|
8082
|
+
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
8083
|
+
if (tablePk) {
|
|
8084
|
+
primaryCol = bareName(tablePk[1]);
|
|
8085
|
+
continue;
|
|
8086
|
+
}
|
|
8087
|
+
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
8088
|
+
const namedFk = trimmed.match(new RegExp(
|
|
8089
|
+
`^CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8090
|
+
"i"
|
|
8091
|
+
));
|
|
8092
|
+
if (namedFk) {
|
|
8093
|
+
inlineFks.push({
|
|
8094
|
+
constraintName: bareName(namedFk[1]),
|
|
8095
|
+
sourceTable: tableName,
|
|
8096
|
+
sourceColumn: bareName(namedFk[2]),
|
|
8097
|
+
targetTable: bareName(namedFk[3]),
|
|
8098
|
+
targetColumn: bareName(namedFk[4]),
|
|
8099
|
+
onDelete: namedFk[5] ?? null
|
|
8100
|
+
});
|
|
8101
|
+
continue;
|
|
8102
|
+
}
|
|
8103
|
+
const bareFk = trimmed.match(new RegExp(
|
|
8104
|
+
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8105
|
+
"i"
|
|
8106
|
+
));
|
|
8107
|
+
if (bareFk) {
|
|
8108
|
+
inlineFks.push({
|
|
8109
|
+
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
8110
|
+
sourceTable: tableName,
|
|
8111
|
+
sourceColumn: bareName(bareFk[1]),
|
|
8112
|
+
targetTable: bareName(bareFk[2]),
|
|
8113
|
+
targetColumn: bareName(bareFk[3]),
|
|
8114
|
+
onDelete: bareFk[4] ?? null
|
|
8115
|
+
});
|
|
8116
|
+
continue;
|
|
8117
|
+
}
|
|
8118
|
+
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
8119
|
+
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
8072
8120
|
if (!colMatch) continue;
|
|
8073
|
-
const colName = colMatch[1];
|
|
8121
|
+
const colName = bareName(colMatch[1]);
|
|
8074
8122
|
let rest = colMatch[2];
|
|
8123
|
+
const inlineRefMatch = rest.match(new RegExp(
|
|
8124
|
+
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8125
|
+
"i"
|
|
8126
|
+
));
|
|
8127
|
+
if (inlineRefMatch) {
|
|
8128
|
+
inlineFks.push({
|
|
8129
|
+
constraintName: `${tableName}_${colName}_fkey`,
|
|
8130
|
+
sourceTable: tableName,
|
|
8131
|
+
sourceColumn: colName,
|
|
8132
|
+
targetTable: bareName(inlineRefMatch[1]),
|
|
8133
|
+
targetColumn: bareName(inlineRefMatch[2]),
|
|
8134
|
+
onDelete: inlineRefMatch[3] ?? null
|
|
8135
|
+
});
|
|
8136
|
+
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
8137
|
+
}
|
|
8075
8138
|
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
8139
|
+
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
8140
|
+
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
8076
8141
|
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
8077
8142
|
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
8078
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
8143
|
+
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bPRIMARY\s+KEY\b/gi, "").replace(/\bUNIQUE\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
8079
8144
|
columns.set(colName, {
|
|
8080
8145
|
name: colName,
|
|
8081
8146
|
type: colType,
|
|
8082
|
-
nullable: !isNotNull,
|
|
8083
|
-
primary:
|
|
8084
|
-
unique:
|
|
8147
|
+
nullable: !isNotNull && !isPrimaryKey,
|
|
8148
|
+
primary: isPrimaryKey,
|
|
8149
|
+
unique: isUnique,
|
|
8085
8150
|
default: defaultVal
|
|
8086
8151
|
});
|
|
8152
|
+
if (isPrimaryKey) primaryCol = colName;
|
|
8087
8153
|
}
|
|
8088
8154
|
if (primaryCol && columns.has(primaryCol)) {
|
|
8089
8155
|
columns.get(primaryCol).primary = true;
|
|
8090
8156
|
}
|
|
8091
8157
|
state.tables.set(tableName, { name: tableName, columns });
|
|
8158
|
+
state.fks.push(...inlineFks);
|
|
8092
8159
|
}
|
|
8093
8160
|
}
|
|
8161
|
+
function splitTopLevelCommas(body) {
|
|
8162
|
+
const out = [];
|
|
8163
|
+
let depth = 0;
|
|
8164
|
+
let buf = "";
|
|
8165
|
+
let inString = null;
|
|
8166
|
+
for (const ch of body) {
|
|
8167
|
+
if (inString) {
|
|
8168
|
+
buf += ch;
|
|
8169
|
+
if (ch === inString) inString = null;
|
|
8170
|
+
continue;
|
|
8171
|
+
}
|
|
8172
|
+
if (ch === "'" || ch === '"') {
|
|
8173
|
+
inString = ch;
|
|
8174
|
+
buf += ch;
|
|
8175
|
+
continue;
|
|
8176
|
+
}
|
|
8177
|
+
if (ch === "(") depth++;
|
|
8178
|
+
else if (ch === ")") depth--;
|
|
8179
|
+
if (ch === "," && depth === 0) {
|
|
8180
|
+
out.push(buf);
|
|
8181
|
+
buf = "";
|
|
8182
|
+
continue;
|
|
8183
|
+
}
|
|
8184
|
+
buf += ch;
|
|
8185
|
+
}
|
|
8186
|
+
if (buf.trim()) out.push(buf);
|
|
8187
|
+
return out;
|
|
8188
|
+
}
|
|
8094
8189
|
function parseCreateEnum(sql, state) {
|
|
8095
|
-
const re =
|
|
8190
|
+
const re = new RegExp(
|
|
8191
|
+
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
8192
|
+
"gi"
|
|
8193
|
+
);
|
|
8096
8194
|
let m;
|
|
8097
8195
|
while ((m = re.exec(sql)) !== null) {
|
|
8098
|
-
const enumName = m[1];
|
|
8196
|
+
const enumName = bareName(m[1]);
|
|
8099
8197
|
const valuesStr = m[2];
|
|
8100
8198
|
const values = new Set(
|
|
8101
8199
|
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
@@ -8104,11 +8202,14 @@ function parseCreateEnum(sql, state) {
|
|
|
8104
8202
|
}
|
|
8105
8203
|
}
|
|
8106
8204
|
function parseAlterTable(sql, state) {
|
|
8107
|
-
const addColRe =
|
|
8205
|
+
const addColRe = new RegExp(
|
|
8206
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
8207
|
+
"gi"
|
|
8208
|
+
);
|
|
8108
8209
|
let m;
|
|
8109
8210
|
while ((m = addColRe.exec(sql)) !== null) {
|
|
8110
|
-
const tableName = m[1];
|
|
8111
|
-
const colName = m[2];
|
|
8211
|
+
const tableName = bareName(m[1]);
|
|
8212
|
+
const colName = bareName(m[2]);
|
|
8112
8213
|
let rest = m[3];
|
|
8113
8214
|
const table = state.tables.get(tableName);
|
|
8114
8215
|
if (!table) continue;
|
|
@@ -8125,48 +8226,66 @@ function parseAlterTable(sql, state) {
|
|
|
8125
8226
|
default: defaultVal
|
|
8126
8227
|
});
|
|
8127
8228
|
}
|
|
8128
|
-
const dropColRe =
|
|
8229
|
+
const dropColRe = new RegExp(
|
|
8230
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
8231
|
+
"gi"
|
|
8232
|
+
);
|
|
8129
8233
|
while ((m = dropColRe.exec(sql)) !== null) {
|
|
8130
|
-
const table = state.tables.get(m[1]);
|
|
8131
|
-
if (table) table.columns.delete(m[2]);
|
|
8234
|
+
const table = state.tables.get(bareName(m[1]));
|
|
8235
|
+
if (table) table.columns.delete(bareName(m[2]));
|
|
8132
8236
|
}
|
|
8133
|
-
const fkRe =
|
|
8237
|
+
const fkRe = new RegExp(
|
|
8238
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8239
|
+
"gi"
|
|
8240
|
+
);
|
|
8134
8241
|
while ((m = fkRe.exec(sql)) !== null) {
|
|
8135
8242
|
state.fks.push({
|
|
8136
|
-
constraintName: m[2],
|
|
8137
|
-
sourceTable: m[1],
|
|
8138
|
-
sourceColumn: m[3],
|
|
8139
|
-
targetTable: m[4],
|
|
8140
|
-
targetColumn: m[5],
|
|
8243
|
+
constraintName: bareName(m[2]),
|
|
8244
|
+
sourceTable: bareName(m[1]),
|
|
8245
|
+
sourceColumn: bareName(m[3]),
|
|
8246
|
+
targetTable: bareName(m[4]),
|
|
8247
|
+
targetColumn: bareName(m[5]),
|
|
8141
8248
|
onDelete: m[6] ?? null
|
|
8142
8249
|
});
|
|
8143
8250
|
}
|
|
8144
8251
|
}
|
|
8145
8252
|
function parseAlterEnum(sql, state) {
|
|
8146
|
-
const re =
|
|
8253
|
+
const re = new RegExp(
|
|
8254
|
+
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
8255
|
+
"gi"
|
|
8256
|
+
);
|
|
8147
8257
|
let m;
|
|
8148
8258
|
while ((m = re.exec(sql)) !== null) {
|
|
8149
|
-
const en = state.enums.get(m[1]);
|
|
8259
|
+
const en = state.enums.get(bareName(m[1]));
|
|
8150
8260
|
if (en) en.values.add(m[2]);
|
|
8151
8261
|
}
|
|
8152
8262
|
}
|
|
8153
8263
|
function parseDropTable(sql, state) {
|
|
8154
|
-
const re =
|
|
8264
|
+
const re = new RegExp(
|
|
8265
|
+
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
8266
|
+
"gi"
|
|
8267
|
+
);
|
|
8155
8268
|
let m;
|
|
8156
8269
|
while ((m = re.exec(sql)) !== null) {
|
|
8157
|
-
|
|
8158
|
-
state.
|
|
8270
|
+
const dropped = bareName(m[1]);
|
|
8271
|
+
state.tables.delete(dropped);
|
|
8272
|
+
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
8159
8273
|
}
|
|
8160
8274
|
}
|
|
8161
8275
|
function parseUniqueIndex(sql, state) {
|
|
8162
|
-
const re =
|
|
8276
|
+
const re = new RegExp(
|
|
8277
|
+
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
8278
|
+
"gi"
|
|
8279
|
+
);
|
|
8163
8280
|
let m;
|
|
8164
8281
|
while ((m = re.exec(sql)) !== null) {
|
|
8165
|
-
const
|
|
8166
|
-
const
|
|
8282
|
+
const tableName = bareName(m[1]);
|
|
8283
|
+
const colName = bareName(m[2]);
|
|
8284
|
+
const table = state.tables.get(tableName);
|
|
8285
|
+
const col = table?.columns.get(colName);
|
|
8167
8286
|
if (col) col.unique = true;
|
|
8168
|
-
if (!state.uniqueIndexes.has(
|
|
8169
|
-
state.uniqueIndexes.get(
|
|
8287
|
+
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
8288
|
+
state.uniqueIndexes.get(tableName).add(colName);
|
|
8170
8289
|
}
|
|
8171
8290
|
}
|
|
8172
8291
|
function discoverMigrationFiles(migrationsDir) {
|
|
@@ -1767,51 +1767,147 @@ function pgTypeToPrisma(pgType) {
|
|
|
1767
1767
|
const upper = pgType.toUpperCase().trim();
|
|
1768
1768
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
1769
1769
|
}
|
|
1770
|
+
function bareName(captured) {
|
|
1771
|
+
const parts = captured.split(".");
|
|
1772
|
+
const last = parts[parts.length - 1];
|
|
1773
|
+
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
1774
|
+
}
|
|
1770
1775
|
function parseCreateTable(sql, state) {
|
|
1771
|
-
const re =
|
|
1776
|
+
const re = new RegExp(
|
|
1777
|
+
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
1778
|
+
"gi"
|
|
1779
|
+
);
|
|
1772
1780
|
let m;
|
|
1773
1781
|
while ((m = re.exec(sql)) !== null) {
|
|
1774
|
-
const tableName = m[1];
|
|
1782
|
+
const tableName = bareName(m[1]);
|
|
1775
1783
|
const body = m[2];
|
|
1776
1784
|
const columns = /* @__PURE__ */ new Map();
|
|
1777
1785
|
let primaryCol = null;
|
|
1778
|
-
|
|
1779
|
-
|
|
1786
|
+
const inlineFks = [];
|
|
1787
|
+
const lines = splitTopLevelCommas(body);
|
|
1788
|
+
for (const raw of lines) {
|
|
1789
|
+
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
1780
1790
|
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
1781
|
-
const
|
|
1782
|
-
if (
|
|
1783
|
-
primaryCol =
|
|
1791
|
+
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1792
|
+
if (namedPk) {
|
|
1793
|
+
primaryCol = bareName(namedPk[1]);
|
|
1784
1794
|
continue;
|
|
1785
1795
|
}
|
|
1786
|
-
|
|
1787
|
-
|
|
1796
|
+
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1797
|
+
if (tablePk) {
|
|
1798
|
+
primaryCol = bareName(tablePk[1]);
|
|
1799
|
+
continue;
|
|
1800
|
+
}
|
|
1801
|
+
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
1802
|
+
const namedFk = trimmed.match(new RegExp(
|
|
1803
|
+
`^CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1804
|
+
"i"
|
|
1805
|
+
));
|
|
1806
|
+
if (namedFk) {
|
|
1807
|
+
inlineFks.push({
|
|
1808
|
+
constraintName: bareName(namedFk[1]),
|
|
1809
|
+
sourceTable: tableName,
|
|
1810
|
+
sourceColumn: bareName(namedFk[2]),
|
|
1811
|
+
targetTable: bareName(namedFk[3]),
|
|
1812
|
+
targetColumn: bareName(namedFk[4]),
|
|
1813
|
+
onDelete: namedFk[5] ?? null
|
|
1814
|
+
});
|
|
1815
|
+
continue;
|
|
1816
|
+
}
|
|
1817
|
+
const bareFk = trimmed.match(new RegExp(
|
|
1818
|
+
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1819
|
+
"i"
|
|
1820
|
+
));
|
|
1821
|
+
if (bareFk) {
|
|
1822
|
+
inlineFks.push({
|
|
1823
|
+
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
1824
|
+
sourceTable: tableName,
|
|
1825
|
+
sourceColumn: bareName(bareFk[1]),
|
|
1826
|
+
targetTable: bareName(bareFk[2]),
|
|
1827
|
+
targetColumn: bareName(bareFk[3]),
|
|
1828
|
+
onDelete: bareFk[4] ?? null
|
|
1829
|
+
});
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
1833
|
+
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
1788
1834
|
if (!colMatch) continue;
|
|
1789
|
-
const colName = colMatch[1];
|
|
1835
|
+
const colName = bareName(colMatch[1]);
|
|
1790
1836
|
let rest = colMatch[2];
|
|
1837
|
+
const inlineRefMatch = rest.match(new RegExp(
|
|
1838
|
+
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1839
|
+
"i"
|
|
1840
|
+
));
|
|
1841
|
+
if (inlineRefMatch) {
|
|
1842
|
+
inlineFks.push({
|
|
1843
|
+
constraintName: `${tableName}_${colName}_fkey`,
|
|
1844
|
+
sourceTable: tableName,
|
|
1845
|
+
sourceColumn: colName,
|
|
1846
|
+
targetTable: bareName(inlineRefMatch[1]),
|
|
1847
|
+
targetColumn: bareName(inlineRefMatch[2]),
|
|
1848
|
+
onDelete: inlineRefMatch[3] ?? null
|
|
1849
|
+
});
|
|
1850
|
+
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
1851
|
+
}
|
|
1791
1852
|
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
1853
|
+
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
1854
|
+
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
1792
1855
|
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
1793
1856
|
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
1794
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
1857
|
+
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bPRIMARY\s+KEY\b/gi, "").replace(/\bUNIQUE\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
1795
1858
|
columns.set(colName, {
|
|
1796
1859
|
name: colName,
|
|
1797
1860
|
type: colType,
|
|
1798
|
-
nullable: !isNotNull,
|
|
1799
|
-
primary:
|
|
1800
|
-
unique:
|
|
1861
|
+
nullable: !isNotNull && !isPrimaryKey,
|
|
1862
|
+
primary: isPrimaryKey,
|
|
1863
|
+
unique: isUnique,
|
|
1801
1864
|
default: defaultVal
|
|
1802
1865
|
});
|
|
1866
|
+
if (isPrimaryKey) primaryCol = colName;
|
|
1803
1867
|
}
|
|
1804
1868
|
if (primaryCol && columns.has(primaryCol)) {
|
|
1805
1869
|
columns.get(primaryCol).primary = true;
|
|
1806
1870
|
}
|
|
1807
1871
|
state.tables.set(tableName, { name: tableName, columns });
|
|
1872
|
+
state.fks.push(...inlineFks);
|
|
1808
1873
|
}
|
|
1809
1874
|
}
|
|
1875
|
+
function splitTopLevelCommas(body) {
|
|
1876
|
+
const out = [];
|
|
1877
|
+
let depth = 0;
|
|
1878
|
+
let buf = "";
|
|
1879
|
+
let inString = null;
|
|
1880
|
+
for (const ch of body) {
|
|
1881
|
+
if (inString) {
|
|
1882
|
+
buf += ch;
|
|
1883
|
+
if (ch === inString) inString = null;
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
if (ch === "'" || ch === '"') {
|
|
1887
|
+
inString = ch;
|
|
1888
|
+
buf += ch;
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1891
|
+
if (ch === "(") depth++;
|
|
1892
|
+
else if (ch === ")") depth--;
|
|
1893
|
+
if (ch === "," && depth === 0) {
|
|
1894
|
+
out.push(buf);
|
|
1895
|
+
buf = "";
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
buf += ch;
|
|
1899
|
+
}
|
|
1900
|
+
if (buf.trim()) out.push(buf);
|
|
1901
|
+
return out;
|
|
1902
|
+
}
|
|
1810
1903
|
function parseCreateEnum(sql, state) {
|
|
1811
|
-
const re =
|
|
1904
|
+
const re = new RegExp(
|
|
1905
|
+
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
1906
|
+
"gi"
|
|
1907
|
+
);
|
|
1812
1908
|
let m;
|
|
1813
1909
|
while ((m = re.exec(sql)) !== null) {
|
|
1814
|
-
const enumName = m[1];
|
|
1910
|
+
const enumName = bareName(m[1]);
|
|
1815
1911
|
const valuesStr = m[2];
|
|
1816
1912
|
const values = new Set(
|
|
1817
1913
|
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
@@ -1820,11 +1916,14 @@ function parseCreateEnum(sql, state) {
|
|
|
1820
1916
|
}
|
|
1821
1917
|
}
|
|
1822
1918
|
function parseAlterTable(sql, state) {
|
|
1823
|
-
const addColRe =
|
|
1919
|
+
const addColRe = new RegExp(
|
|
1920
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
1921
|
+
"gi"
|
|
1922
|
+
);
|
|
1824
1923
|
let m;
|
|
1825
1924
|
while ((m = addColRe.exec(sql)) !== null) {
|
|
1826
|
-
const tableName = m[1];
|
|
1827
|
-
const colName = m[2];
|
|
1925
|
+
const tableName = bareName(m[1]);
|
|
1926
|
+
const colName = bareName(m[2]);
|
|
1828
1927
|
let rest = m[3];
|
|
1829
1928
|
const table = state.tables.get(tableName);
|
|
1830
1929
|
if (!table) continue;
|
|
@@ -1841,48 +1940,66 @@ function parseAlterTable(sql, state) {
|
|
|
1841
1940
|
default: defaultVal
|
|
1842
1941
|
});
|
|
1843
1942
|
}
|
|
1844
|
-
const dropColRe =
|
|
1943
|
+
const dropColRe = new RegExp(
|
|
1944
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1945
|
+
"gi"
|
|
1946
|
+
);
|
|
1845
1947
|
while ((m = dropColRe.exec(sql)) !== null) {
|
|
1846
|
-
const table = state.tables.get(m[1]);
|
|
1847
|
-
if (table) table.columns.delete(m[2]);
|
|
1948
|
+
const table = state.tables.get(bareName(m[1]));
|
|
1949
|
+
if (table) table.columns.delete(bareName(m[2]));
|
|
1848
1950
|
}
|
|
1849
|
-
const fkRe =
|
|
1951
|
+
const fkRe = new RegExp(
|
|
1952
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1953
|
+
"gi"
|
|
1954
|
+
);
|
|
1850
1955
|
while ((m = fkRe.exec(sql)) !== null) {
|
|
1851
1956
|
state.fks.push({
|
|
1852
|
-
constraintName: m[2],
|
|
1853
|
-
sourceTable: m[1],
|
|
1854
|
-
sourceColumn: m[3],
|
|
1855
|
-
targetTable: m[4],
|
|
1856
|
-
targetColumn: m[5],
|
|
1957
|
+
constraintName: bareName(m[2]),
|
|
1958
|
+
sourceTable: bareName(m[1]),
|
|
1959
|
+
sourceColumn: bareName(m[3]),
|
|
1960
|
+
targetTable: bareName(m[4]),
|
|
1961
|
+
targetColumn: bareName(m[5]),
|
|
1857
1962
|
onDelete: m[6] ?? null
|
|
1858
1963
|
});
|
|
1859
1964
|
}
|
|
1860
1965
|
}
|
|
1861
1966
|
function parseAlterEnum(sql, state) {
|
|
1862
|
-
const re =
|
|
1967
|
+
const re = new RegExp(
|
|
1968
|
+
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
1969
|
+
"gi"
|
|
1970
|
+
);
|
|
1863
1971
|
let m;
|
|
1864
1972
|
while ((m = re.exec(sql)) !== null) {
|
|
1865
|
-
const en = state.enums.get(m[1]);
|
|
1973
|
+
const en = state.enums.get(bareName(m[1]));
|
|
1866
1974
|
if (en) en.values.add(m[2]);
|
|
1867
1975
|
}
|
|
1868
1976
|
}
|
|
1869
1977
|
function parseDropTable(sql, state) {
|
|
1870
|
-
const re =
|
|
1978
|
+
const re = new RegExp(
|
|
1979
|
+
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1980
|
+
"gi"
|
|
1981
|
+
);
|
|
1871
1982
|
let m;
|
|
1872
1983
|
while ((m = re.exec(sql)) !== null) {
|
|
1873
|
-
|
|
1874
|
-
state.
|
|
1984
|
+
const dropped = bareName(m[1]);
|
|
1985
|
+
state.tables.delete(dropped);
|
|
1986
|
+
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
1875
1987
|
}
|
|
1876
1988
|
}
|
|
1877
1989
|
function parseUniqueIndex(sql, state) {
|
|
1878
|
-
const re =
|
|
1990
|
+
const re = new RegExp(
|
|
1991
|
+
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
1992
|
+
"gi"
|
|
1993
|
+
);
|
|
1879
1994
|
let m;
|
|
1880
1995
|
while ((m = re.exec(sql)) !== null) {
|
|
1881
|
-
const
|
|
1882
|
-
const
|
|
1996
|
+
const tableName = bareName(m[1]);
|
|
1997
|
+
const colName = bareName(m[2]);
|
|
1998
|
+
const table = state.tables.get(tableName);
|
|
1999
|
+
const col = table?.columns.get(colName);
|
|
1883
2000
|
if (col) col.unique = true;
|
|
1884
|
-
if (!state.uniqueIndexes.has(
|
|
1885
|
-
state.uniqueIndexes.get(
|
|
2001
|
+
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
2002
|
+
state.uniqueIndexes.get(tableName).add(colName);
|
|
1886
2003
|
}
|
|
1887
2004
|
}
|
|
1888
2005
|
function discoverMigrationFiles(migrationsDir) {
|
|
@@ -2168,7 +2285,7 @@ function generate3(rootDir) {
|
|
|
2168
2285
|
flagged_edges: flaggedEdges
|
|
2169
2286
|
};
|
|
2170
2287
|
}
|
|
2171
|
-
var import_node_fs8, import_node_path7, PG_TO_PRISMA, sqlMigrationsParser;
|
|
2288
|
+
var import_node_fs8, import_node_path7, PG_TO_PRISMA, ID, QID, sqlMigrationsParser;
|
|
2172
2289
|
var init_sql_migrations = __esm({
|
|
2173
2290
|
"src/server/graph/parsers/db/sql-migrations.ts"() {
|
|
2174
2291
|
"use strict";
|
|
@@ -2202,6 +2319,8 @@ var init_sql_migrations = __esm({
|
|
|
2202
2319
|
"UUID": "String",
|
|
2203
2320
|
"TEXT[]": "String[]"
|
|
2204
2321
|
};
|
|
2322
|
+
ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
2323
|
+
QID = `(?:${ID}\\.)?${ID}`;
|
|
2205
2324
|
sqlMigrationsParser = {
|
|
2206
2325
|
id: "sql-migrations",
|
|
2207
2326
|
layer: "db",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@launchsecure/launch-kit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "LaunchSecure toolkit — launch-pod (pipeline), launch-chart (project graph MCP), launch-deck (visual playground MCP).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "LaunchSecure - AutomateWithUs",
|