@deepagents/text2sql 7.1.2 → 7.1.4
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/index.js +358 -479
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/spreadsheet/index.js +14 -17
- package/dist/lib/adapters/spreadsheet/index.js.map +2 -2
- package/dist/lib/adapters/spreadsheet/spreadsheet.d.ts.map +1 -1
- package/dist/lib/fs/mssql/mssql-fs.d.ts.map +1 -1
- package/dist/lib/fs/mssql/sqlserver-schema-lock.d.ts +14 -0
- package/dist/lib/fs/mssql/sqlserver-schema-lock.d.ts.map +1 -0
- package/dist/lib/fs/postgres/postgres-fs.d.ts.map +1 -1
- package/dist/lib/fs/sqlite/sqlite-fs.d.ts.map +1 -1
- package/package.json +9 -8
package/dist/index.js
CHANGED
|
@@ -1545,6 +1545,7 @@ function hashConfig(config) {
|
|
|
1545
1545
|
}
|
|
1546
1546
|
|
|
1547
1547
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1548
|
+
import { transaction } from "@zukhruf/sqlite-transaction";
|
|
1548
1549
|
import * as path2 from "node:path";
|
|
1549
1550
|
import { DatabaseSync } from "node:sqlite";
|
|
1550
1551
|
import z6 from "zod";
|
|
@@ -1583,7 +1584,7 @@ var chunkRow = z6.object({
|
|
|
1583
1584
|
var dataRow = chunkRow.pick({ data: true });
|
|
1584
1585
|
var SqliteFs = class {
|
|
1585
1586
|
#db;
|
|
1586
|
-
#
|
|
1587
|
+
#sql;
|
|
1587
1588
|
#chunkSize;
|
|
1588
1589
|
#root;
|
|
1589
1590
|
constructor(options) {
|
|
@@ -1592,25 +1593,18 @@ var SqliteFs = class {
|
|
|
1592
1593
|
this.#root = normalizedRoot === "/" ? "" : normalizedRoot;
|
|
1593
1594
|
this.#db = new DatabaseSync(options.dbPath);
|
|
1594
1595
|
this.#db.exec(ddl_sqlite_fs_default);
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
).get("/");
|
|
1596
|
+
this.#sql = this.#db.createTagStore();
|
|
1597
|
+
const rootSlashExists = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = '/'`;
|
|
1598
1598
|
if (!rootSlashExists) {
|
|
1599
|
-
this.#
|
|
1600
|
-
|
|
1601
|
-
VALUES ('/', 'directory', 493, 0, ?)`
|
|
1602
|
-
).run(Date.now());
|
|
1599
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1600
|
+
VALUES ('/', 'directory', 493, 0, ${Date.now()})`;
|
|
1603
1601
|
}
|
|
1604
1602
|
if (this.#root) {
|
|
1605
1603
|
this.#createParentDirs(this.#root);
|
|
1606
|
-
const rootExists = this.#
|
|
1607
|
-
"SELECT 1 FROM fs_entries WHERE path = ?"
|
|
1608
|
-
).get(this.#root);
|
|
1604
|
+
const rootExists = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${this.#root}`;
|
|
1609
1605
|
if (!rootExists) {
|
|
1610
|
-
this.#
|
|
1611
|
-
|
|
1612
|
-
VALUES (?, 'directory', 493, 0, ?)`
|
|
1613
|
-
).run(this.#root, Date.now());
|
|
1606
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1607
|
+
VALUES (${this.#root}, 'directory', 493, 0, ${Date.now()})`;
|
|
1614
1608
|
}
|
|
1615
1609
|
}
|
|
1616
1610
|
}
|
|
@@ -1623,25 +1617,13 @@ var SqliteFs = class {
|
|
|
1623
1617
|
let currentPath = "/";
|
|
1624
1618
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
1625
1619
|
currentPath = path2.posix.join(currentPath, segments[i]);
|
|
1626
|
-
const exists = this.#
|
|
1627
|
-
currentPath
|
|
1628
|
-
);
|
|
1620
|
+
const exists = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${currentPath}`;
|
|
1629
1621
|
if (!exists) {
|
|
1630
|
-
this.#
|
|
1631
|
-
|
|
1632
|
-
VALUES (?, 'directory', 493, 0, ?)`
|
|
1633
|
-
).run(currentPath, Date.now());
|
|
1622
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1623
|
+
VALUES (${currentPath}, 'directory', 493, 0, ${Date.now()})`;
|
|
1634
1624
|
}
|
|
1635
1625
|
}
|
|
1636
1626
|
}
|
|
1637
|
-
#stmt(sql) {
|
|
1638
|
-
let stmt = this.#statements.get(sql);
|
|
1639
|
-
if (!stmt) {
|
|
1640
|
-
stmt = this.#db.prepare(sql);
|
|
1641
|
-
this.#statements.set(sql, stmt);
|
|
1642
|
-
}
|
|
1643
|
-
return stmt;
|
|
1644
|
-
}
|
|
1645
1627
|
#normalizeRoot(root) {
|
|
1646
1628
|
return path2.posix.resolve("/", root.trim());
|
|
1647
1629
|
}
|
|
@@ -1666,20 +1648,6 @@ var SqliteFs = class {
|
|
|
1666
1648
|
}
|
|
1667
1649
|
return p;
|
|
1668
1650
|
}
|
|
1669
|
-
#useTransaction(fn) {
|
|
1670
|
-
this.#db.exec("BEGIN TRANSACTION");
|
|
1671
|
-
try {
|
|
1672
|
-
const result = fn();
|
|
1673
|
-
this.#db.exec("COMMIT");
|
|
1674
|
-
return result;
|
|
1675
|
-
} catch (error) {
|
|
1676
|
-
try {
|
|
1677
|
-
this.#db.exec("ROLLBACK");
|
|
1678
|
-
} catch {
|
|
1679
|
-
}
|
|
1680
|
-
throw error;
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
1651
|
#normalizePath(p) {
|
|
1684
1652
|
return path2.posix.resolve("/", p);
|
|
1685
1653
|
}
|
|
@@ -1691,43 +1659,33 @@ var SqliteFs = class {
|
|
|
1691
1659
|
const parent = this.#dirname(filePath);
|
|
1692
1660
|
const rootPath = this.#root || "/";
|
|
1693
1661
|
if (parent === rootPath || parent === "/") return;
|
|
1694
|
-
const entry = typeRow.optional().parse(
|
|
1695
|
-
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(parent)
|
|
1696
|
-
);
|
|
1662
|
+
const entry = typeRow.optional().parse(this.#sql.get`SELECT type FROM fs_entries WHERE path = ${parent}`);
|
|
1697
1663
|
if (!entry) {
|
|
1698
1664
|
this.#ensureParentExists(parent);
|
|
1699
|
-
this.#
|
|
1700
|
-
|
|
1701
|
-
VALUES (?, 'directory', 493, 0, ?)`
|
|
1702
|
-
).run(parent, Date.now());
|
|
1665
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1666
|
+
VALUES (${parent}, 'directory', 493, 0, ${Date.now()})`;
|
|
1703
1667
|
} else if (entry.type !== "directory") {
|
|
1704
1668
|
throw new Error(`mkdir: parent is not a directory: ${parent}`);
|
|
1705
1669
|
}
|
|
1706
1670
|
}
|
|
1707
1671
|
#writeChunks(filePath, content) {
|
|
1708
|
-
this.#
|
|
1672
|
+
this.#sql.run`DELETE FROM fs_chunks WHERE path = ${filePath}`;
|
|
1709
1673
|
for (let i = 0; i < content.length; i += this.#chunkSize) {
|
|
1710
1674
|
const chunk = content.slice(
|
|
1711
1675
|
i,
|
|
1712
1676
|
Math.min(i + this.#chunkSize, content.length)
|
|
1713
1677
|
);
|
|
1714
|
-
this.#
|
|
1715
|
-
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
1716
|
-
).run(filePath, Math.floor(i / this.#chunkSize), chunk);
|
|
1678
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${filePath}, ${Math.floor(i / this.#chunkSize)}, ${chunk})`;
|
|
1717
1679
|
}
|
|
1718
1680
|
}
|
|
1719
1681
|
#chunks(filePath) {
|
|
1720
1682
|
return z6.array(chunkRow).parse(
|
|
1721
|
-
this.#
|
|
1722
|
-
filePath
|
|
1723
|
-
)
|
|
1683
|
+
this.#sql.all`SELECT chunkIndex, data FROM fs_chunks WHERE path = ${filePath}`
|
|
1724
1684
|
);
|
|
1725
1685
|
}
|
|
1726
1686
|
#readChunks(filePath) {
|
|
1727
1687
|
const rows = z6.array(dataRow).parse(
|
|
1728
|
-
this.#
|
|
1729
|
-
"SELECT data FROM fs_chunks WHERE path = ? ORDER BY chunkIndex"
|
|
1730
|
-
).all(filePath)
|
|
1688
|
+
this.#sql.all`SELECT data FROM fs_chunks WHERE path = ${filePath} ORDER BY chunkIndex`
|
|
1731
1689
|
);
|
|
1732
1690
|
if (rows.length === 0) {
|
|
1733
1691
|
return new Uint8Array(0);
|
|
@@ -1746,9 +1704,7 @@ var SqliteFs = class {
|
|
|
1746
1704
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
1747
1705
|
}
|
|
1748
1706
|
const entry = linkRow.optional().parse(
|
|
1749
|
-
this.#
|
|
1750
|
-
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
1751
|
-
).get(p)
|
|
1707
|
+
this.#sql.get`SELECT type, symlinkTarget FROM fs_entries WHERE path = ${p}`
|
|
1752
1708
|
);
|
|
1753
1709
|
if (!entry) {
|
|
1754
1710
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
@@ -1776,7 +1732,7 @@ var SqliteFs = class {
|
|
|
1776
1732
|
const prefixed = this.#prefixPath(normalized);
|
|
1777
1733
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1778
1734
|
const entry = typeRow.optional().parse(
|
|
1779
|
-
this.#
|
|
1735
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${resolved}`
|
|
1780
1736
|
);
|
|
1781
1737
|
if (!entry) {
|
|
1782
1738
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1793,7 +1749,7 @@ var SqliteFs = class {
|
|
|
1793
1749
|
const prefixed = this.#prefixPath(normalized);
|
|
1794
1750
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1795
1751
|
const entry = typeRow.optional().parse(
|
|
1796
|
-
this.#
|
|
1752
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${resolved}`
|
|
1797
1753
|
);
|
|
1798
1754
|
if (!entry) {
|
|
1799
1755
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1808,63 +1764,61 @@ var SqliteFs = class {
|
|
|
1808
1764
|
const prefixed = this.#prefixPath(normalized);
|
|
1809
1765
|
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
1810
1766
|
const data = this.#toUint8Array(content, encoding);
|
|
1811
|
-
|
|
1812
|
-
this.#
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1767
|
+
transaction(
|
|
1768
|
+
this.#db,
|
|
1769
|
+
() => {
|
|
1770
|
+
this.#ensureParentExists(prefixed);
|
|
1771
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1772
|
+
VALUES (${prefixed}, 'file', 420, ${data.length}, ${Date.now()})
|
|
1816
1773
|
ON CONFLICT(path) DO UPDATE SET
|
|
1817
1774
|
type = 'file',
|
|
1818
1775
|
size = excluded.size,
|
|
1819
|
-
mtime = excluded.mtime
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1776
|
+
mtime = excluded.mtime`;
|
|
1777
|
+
this.#writeChunks(prefixed, data);
|
|
1778
|
+
},
|
|
1779
|
+
{ mode: "deferred" }
|
|
1780
|
+
);
|
|
1823
1781
|
}
|
|
1824
1782
|
async appendFile(filePath, content, options) {
|
|
1825
1783
|
const normalized = this.#normalizePath(filePath);
|
|
1826
1784
|
const prefixed = this.#prefixPath(normalized);
|
|
1827
1785
|
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
1828
1786
|
const newData = this.#toUint8Array(content, encoding);
|
|
1829
|
-
|
|
1830
|
-
this.#
|
|
1831
|
-
|
|
1832
|
-
this.#
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
VALUES (?, 'file', 420, ?, ?)
|
|
1787
|
+
transaction(
|
|
1788
|
+
this.#db,
|
|
1789
|
+
() => {
|
|
1790
|
+
this.#ensureParentExists(prefixed);
|
|
1791
|
+
const entry = typeRow.optional().parse(
|
|
1792
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${prefixed}`
|
|
1793
|
+
);
|
|
1794
|
+
if (entry && entry.type !== "file") {
|
|
1795
|
+
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
1796
|
+
}
|
|
1797
|
+
const existing = entry ? this.#readChunks(prefixed) : new Uint8Array(0);
|
|
1798
|
+
const combined = new Uint8Array(existing.length + newData.length);
|
|
1799
|
+
combined.set(existing, 0);
|
|
1800
|
+
combined.set(newData, existing.length);
|
|
1801
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1802
|
+
VALUES (${prefixed}, 'file', 420, ${combined.length}, ${Date.now()})
|
|
1846
1803
|
ON CONFLICT(path) DO UPDATE SET
|
|
1847
1804
|
size = excluded.size,
|
|
1848
|
-
mtime = excluded.mtime
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1805
|
+
mtime = excluded.mtime`;
|
|
1806
|
+
this.#writeChunks(prefixed, combined);
|
|
1807
|
+
},
|
|
1808
|
+
{ mode: "deferred" }
|
|
1809
|
+
);
|
|
1852
1810
|
}
|
|
1853
1811
|
async exists(filePath) {
|
|
1854
1812
|
const normalized = this.#normalizePath(filePath);
|
|
1855
1813
|
const prefixed = this.#prefixPath(normalized);
|
|
1856
|
-
const row = this.#
|
|
1857
|
-
prefixed
|
|
1858
|
-
);
|
|
1814
|
+
const row = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${prefixed}`;
|
|
1859
1815
|
return row !== void 0;
|
|
1860
1816
|
}
|
|
1861
1817
|
async stat(filePath) {
|
|
1862
1818
|
const normalized = this.#normalizePath(filePath);
|
|
1863
1819
|
const prefixed = this.#prefixPath(normalized);
|
|
1864
1820
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1865
|
-
const entry = entryRow.optional().parse(
|
|
1866
|
-
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(resolved)
|
|
1867
|
-
);
|
|
1821
|
+
const entry = entryRow.optional().parse(this.#sql.get`SELECT * FROM fs_entries WHERE path = ${resolved}`);
|
|
1868
1822
|
if (!entry) {
|
|
1869
1823
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
1870
1824
|
}
|
|
@@ -1881,9 +1835,7 @@ var SqliteFs = class {
|
|
|
1881
1835
|
async lstat(filePath) {
|
|
1882
1836
|
const normalized = this.#normalizePath(filePath);
|
|
1883
1837
|
const prefixed = this.#prefixPath(normalized);
|
|
1884
|
-
const entry = entryRow.optional().parse(
|
|
1885
|
-
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1886
|
-
);
|
|
1838
|
+
const entry = entryRow.optional().parse(this.#sql.get`SELECT * FROM fs_entries WHERE path = ${prefixed}`);
|
|
1887
1839
|
if (!entry) {
|
|
1888
1840
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
1889
1841
|
}
|
|
@@ -1900,7 +1852,7 @@ var SqliteFs = class {
|
|
|
1900
1852
|
const normalized = this.#normalizePath(dirPath);
|
|
1901
1853
|
const prefixed = this.#prefixPath(normalized);
|
|
1902
1854
|
const existing = typeRow.optional().parse(
|
|
1903
|
-
this.#
|
|
1855
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${prefixed}`
|
|
1904
1856
|
);
|
|
1905
1857
|
if (existing) {
|
|
1906
1858
|
if (options?.recursive) {
|
|
@@ -1908,54 +1860,50 @@ var SqliteFs = class {
|
|
|
1908
1860
|
}
|
|
1909
1861
|
throw new Error(`EEXIST: file already exists: ${dirPath}`);
|
|
1910
1862
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
currentPath =
|
|
1919
|
-
const
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1863
|
+
transaction(
|
|
1864
|
+
this.#db,
|
|
1865
|
+
() => {
|
|
1866
|
+
if (options?.recursive) {
|
|
1867
|
+
const rootPath = this.#root || "/";
|
|
1868
|
+
const relativePath = path2.posix.relative(rootPath, prefixed);
|
|
1869
|
+
const segments = relativePath.split("/").filter(Boolean);
|
|
1870
|
+
let currentPath = rootPath;
|
|
1871
|
+
for (const segment of segments) {
|
|
1872
|
+
currentPath = path2.posix.join(currentPath, segment);
|
|
1873
|
+
const exists = typeRow.optional().parse(
|
|
1874
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${currentPath}`
|
|
1875
|
+
);
|
|
1876
|
+
if (!exists) {
|
|
1877
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1878
|
+
VALUES (${currentPath}, 'directory', 493, 0, ${Date.now()})`;
|
|
1879
|
+
} else if (exists.type !== "directory") {
|
|
1880
|
+
throw new Error(`mkdir: not a directory: ${currentPath}`);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
} else {
|
|
1884
|
+
const parent = this.#dirname(prefixed);
|
|
1885
|
+
const parentEntry = typeRow.optional().parse(
|
|
1886
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${parent}`
|
|
1923
1887
|
);
|
|
1924
|
-
if (!
|
|
1925
|
-
|
|
1926
|
-
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1927
|
-
VALUES (?, 'directory', 493, 0, ?)`
|
|
1928
|
-
).run(currentPath, Date.now());
|
|
1929
|
-
} else if (exists.type !== "directory") {
|
|
1930
|
-
throw new Error(`mkdir: not a directory: ${currentPath}`);
|
|
1888
|
+
if (!parentEntry) {
|
|
1889
|
+
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
1931
1890
|
}
|
|
1891
|
+
if (parentEntry.type !== "directory") {
|
|
1892
|
+
throw new Error(`mkdir: parent is not a directory: ${parent}`);
|
|
1893
|
+
}
|
|
1894
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1895
|
+
VALUES (${prefixed}, 'directory', 493, 0, ${Date.now()})`;
|
|
1932
1896
|
}
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1937
|
-
parent
|
|
1938
|
-
)
|
|
1939
|
-
);
|
|
1940
|
-
if (!parentEntry) {
|
|
1941
|
-
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
1942
|
-
}
|
|
1943
|
-
if (parentEntry.type !== "directory") {
|
|
1944
|
-
throw new Error(`mkdir: parent is not a directory: ${parent}`);
|
|
1945
|
-
}
|
|
1946
|
-
this.#stmt(
|
|
1947
|
-
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
1948
|
-
VALUES (?, 'directory', 493, 0, ?)`
|
|
1949
|
-
).run(prefixed, Date.now());
|
|
1950
|
-
}
|
|
1951
|
-
});
|
|
1897
|
+
},
|
|
1898
|
+
{ mode: "deferred" }
|
|
1899
|
+
);
|
|
1952
1900
|
}
|
|
1953
1901
|
async readdir(dirPath) {
|
|
1954
1902
|
const normalized = this.#normalizePath(dirPath);
|
|
1955
1903
|
const prefixed = this.#prefixPath(normalized);
|
|
1956
1904
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1957
1905
|
const entry = typeRow.optional().parse(
|
|
1958
|
-
this.#
|
|
1906
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${resolved}`
|
|
1959
1907
|
);
|
|
1960
1908
|
if (!entry) {
|
|
1961
1909
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1965,12 +1913,10 @@ var SqliteFs = class {
|
|
|
1965
1913
|
}
|
|
1966
1914
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1967
1915
|
const rows = z6.array(pathRow).parse(
|
|
1968
|
-
this.#
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
AND path
|
|
1972
|
-
AND path NOT LIKE ? || '%/%'`
|
|
1973
|
-
).all(prefix, resolved, prefix)
|
|
1916
|
+
this.#sql.all`SELECT path FROM fs_entries
|
|
1917
|
+
WHERE path LIKE ${prefix} || '%'
|
|
1918
|
+
AND path != ${resolved}
|
|
1919
|
+
AND path NOT LIKE ${prefix} || '%/%'`
|
|
1974
1920
|
);
|
|
1975
1921
|
return rows.map((row) => path2.posix.basename(row.path));
|
|
1976
1922
|
}
|
|
@@ -1979,7 +1925,7 @@ var SqliteFs = class {
|
|
|
1979
1925
|
const prefixed = this.#prefixPath(normalized);
|
|
1980
1926
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1981
1927
|
const entry = typeRow.optional().parse(
|
|
1982
|
-
this.#
|
|
1928
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${resolved}`
|
|
1983
1929
|
);
|
|
1984
1930
|
if (!entry) {
|
|
1985
1931
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1989,12 +1935,10 @@ var SqliteFs = class {
|
|
|
1989
1935
|
}
|
|
1990
1936
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1991
1937
|
const rows = z6.array(pathTypeRow).parse(
|
|
1992
|
-
this.#
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
AND path
|
|
1996
|
-
AND path NOT LIKE ? || '%/%'`
|
|
1997
|
-
).all(prefix, resolved, prefix)
|
|
1938
|
+
this.#sql.all`SELECT path, type FROM fs_entries
|
|
1939
|
+
WHERE path LIKE ${prefix} || '%'
|
|
1940
|
+
AND path != ${resolved}
|
|
1941
|
+
AND path NOT LIKE ${prefix} || '%/%'`
|
|
1998
1942
|
);
|
|
1999
1943
|
return rows.map((row) => ({
|
|
2000
1944
|
name: path2.posix.basename(row.path),
|
|
@@ -2007,7 +1951,7 @@ var SqliteFs = class {
|
|
|
2007
1951
|
const normalized = this.#normalizePath(filePath);
|
|
2008
1952
|
const prefixed = this.#prefixPath(normalized);
|
|
2009
1953
|
const entry = typeRow.optional().parse(
|
|
2010
|
-
this.#
|
|
1954
|
+
this.#sql.get`SELECT type FROM fs_entries WHERE path = ${prefixed}`
|
|
2011
1955
|
);
|
|
2012
1956
|
if (!entry) {
|
|
2013
1957
|
if (options?.force) {
|
|
@@ -2015,21 +1959,21 @@ var SqliteFs = class {
|
|
|
2015
1959
|
}
|
|
2016
1960
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2017
1961
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
1962
|
+
transaction(
|
|
1963
|
+
this.#db,
|
|
1964
|
+
() => {
|
|
1965
|
+
if (entry.type === "directory") {
|
|
1966
|
+
const children = this.#sql.get`SELECT 1 FROM fs_entries WHERE path LIKE ${prefixed} || '/%' LIMIT 1`;
|
|
1967
|
+
if (children && !options?.recursive) {
|
|
1968
|
+
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
1969
|
+
}
|
|
1970
|
+
this.#sql.run`DELETE FROM fs_entries WHERE path = ${prefixed} OR path LIKE ${prefixed} || '/%'`;
|
|
1971
|
+
} else {
|
|
1972
|
+
this.#sql.run`DELETE FROM fs_entries WHERE path = ${prefixed}`;
|
|
2025
1973
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
} else {
|
|
2030
|
-
this.#stmt("DELETE FROM fs_entries WHERE path = ?").run(prefixed);
|
|
2031
|
-
}
|
|
2032
|
-
});
|
|
1974
|
+
},
|
|
1975
|
+
{ mode: "deferred" }
|
|
1976
|
+
);
|
|
2033
1977
|
}
|
|
2034
1978
|
async cp(src, dest, options) {
|
|
2035
1979
|
const srcNormalized = this.#normalizePath(src);
|
|
@@ -2037,7 +1981,7 @@ var SqliteFs = class {
|
|
|
2037
1981
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2038
1982
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2039
1983
|
const srcEntry = entryRow.optional().parse(
|
|
2040
|
-
this.#
|
|
1984
|
+
this.#sql.get`SELECT * FROM fs_entries WHERE path = ${srcPrefixed}`
|
|
2041
1985
|
);
|
|
2042
1986
|
if (!srcEntry) {
|
|
2043
1987
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
@@ -2045,60 +1989,40 @@ var SqliteFs = class {
|
|
|
2045
1989
|
if (srcEntry.type === "directory" && !options?.recursive) {
|
|
2046
1990
|
throw new Error(`cp: -r not specified; omitting directory: ${src}`);
|
|
2047
1991
|
}
|
|
2048
|
-
|
|
2049
|
-
this.#
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
);
|
|
2056
|
-
for (const entry of allEntries) {
|
|
2057
|
-
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2058
|
-
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
2059
|
-
this.#stmt(
|
|
2060
|
-
`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2061
|
-
VALUES (?, ?, ?, ?, ?, ?)`
|
|
2062
|
-
).run(
|
|
2063
|
-
newPath,
|
|
2064
|
-
entry.type,
|
|
2065
|
-
entry.mode,
|
|
2066
|
-
entry.size,
|
|
2067
|
-
Date.now(),
|
|
2068
|
-
entry.symlinkTarget
|
|
1992
|
+
transaction(
|
|
1993
|
+
this.#db,
|
|
1994
|
+
() => {
|
|
1995
|
+
this.#ensureParentExists(destPrefixed);
|
|
1996
|
+
if (srcEntry.type === "directory") {
|
|
1997
|
+
const allEntries = z6.array(entryRow).parse(
|
|
1998
|
+
this.#sql.all`SELECT * FROM fs_entries WHERE path = ${srcPrefixed} OR path LIKE ${srcPrefixed} || '/%'`
|
|
2069
1999
|
);
|
|
2070
|
-
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2000
|
+
for (const entry of allEntries) {
|
|
2001
|
+
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2002
|
+
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
2003
|
+
this.#sql.run`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2004
|
+
VALUES (${newPath}, ${entry.type}, ${entry.mode}, ${entry.size}, ${Date.now()}, ${entry.symlinkTarget})`;
|
|
2005
|
+
if (entry.type === "file") {
|
|
2006
|
+
const chunks = this.#chunks(entry.path);
|
|
2007
|
+
for (const chunk of chunks) {
|
|
2008
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${newPath}, ${chunk.chunkIndex}, ${chunk.data})`;
|
|
2009
|
+
}
|
|
2076
2010
|
}
|
|
2077
2011
|
}
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
srcEntry.size,
|
|
2088
|
-
Date.now(),
|
|
2089
|
-
srcEntry.symlinkTarget
|
|
2090
|
-
);
|
|
2091
|
-
if (srcEntry.type === "file") {
|
|
2092
|
-
const chunks = this.#chunks(srcPrefixed);
|
|
2093
|
-
this.#stmt("DELETE FROM fs_chunks WHERE path = ?").run(destPrefixed);
|
|
2094
|
-
for (const chunk of chunks) {
|
|
2095
|
-
this.#stmt(
|
|
2096
|
-
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
2097
|
-
).run(destPrefixed, chunk.chunkIndex, chunk.data);
|
|
2012
|
+
} else {
|
|
2013
|
+
this.#sql.run`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2014
|
+
VALUES (${destPrefixed}, ${srcEntry.type}, ${srcEntry.mode}, ${srcEntry.size}, ${Date.now()}, ${srcEntry.symlinkTarget})`;
|
|
2015
|
+
if (srcEntry.type === "file") {
|
|
2016
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2017
|
+
this.#sql.run`DELETE FROM fs_chunks WHERE path = ${destPrefixed}`;
|
|
2018
|
+
for (const chunk of chunks) {
|
|
2019
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${destPrefixed}, ${chunk.chunkIndex}, ${chunk.data})`;
|
|
2020
|
+
}
|
|
2098
2021
|
}
|
|
2099
2022
|
}
|
|
2100
|
-
}
|
|
2101
|
-
|
|
2023
|
+
},
|
|
2024
|
+
{ mode: "deferred" }
|
|
2025
|
+
);
|
|
2102
2026
|
}
|
|
2103
2027
|
async mv(src, dest) {
|
|
2104
2028
|
const srcNormalized = this.#normalizePath(src);
|
|
@@ -2106,83 +2030,59 @@ var SqliteFs = class {
|
|
|
2106
2030
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2107
2031
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2108
2032
|
const srcEntry = entryRow.optional().parse(
|
|
2109
|
-
this.#
|
|
2033
|
+
this.#sql.get`SELECT * FROM fs_entries WHERE path = ${srcPrefixed}`
|
|
2110
2034
|
);
|
|
2111
2035
|
if (!srcEntry) {
|
|
2112
2036
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
2113
2037
|
}
|
|
2114
|
-
|
|
2115
|
-
this.#
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
);
|
|
2122
|
-
for (const entry of [...allEntries].reverse()) {
|
|
2123
|
-
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2124
|
-
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
2125
|
-
this.#stmt(
|
|
2126
|
-
`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2127
|
-
VALUES (?, ?, ?, ?, ?, ?)`
|
|
2128
|
-
).run(
|
|
2129
|
-
newPath,
|
|
2130
|
-
entry.type,
|
|
2131
|
-
entry.mode,
|
|
2132
|
-
entry.size,
|
|
2133
|
-
Date.now(),
|
|
2134
|
-
entry.symlinkTarget
|
|
2038
|
+
transaction(
|
|
2039
|
+
this.#db,
|
|
2040
|
+
() => {
|
|
2041
|
+
this.#ensureParentExists(destPrefixed);
|
|
2042
|
+
if (srcEntry.type === "directory") {
|
|
2043
|
+
const allEntries = z6.array(entryRow).parse(
|
|
2044
|
+
this.#sql.all`SELECT * FROM fs_entries WHERE path = ${srcPrefixed} OR path LIKE ${srcPrefixed} || '/%' ORDER BY path DESC`
|
|
2135
2045
|
);
|
|
2136
|
-
|
|
2137
|
-
const
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2046
|
+
for (const entry of [...allEntries].reverse()) {
|
|
2047
|
+
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2048
|
+
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
2049
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2050
|
+
VALUES (${newPath}, ${entry.type}, ${entry.mode}, ${entry.size}, ${Date.now()}, ${entry.symlinkTarget})`;
|
|
2051
|
+
if (entry.type === "file") {
|
|
2052
|
+
const chunks = this.#chunks(entry.path);
|
|
2053
|
+
for (const chunk of chunks) {
|
|
2054
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${newPath}, ${chunk.chunkIndex}, ${chunk.data})`;
|
|
2055
|
+
}
|
|
2142
2056
|
}
|
|
2143
2057
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
`
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
destPrefixed,
|
|
2154
|
-
srcEntry.type,
|
|
2155
|
-
srcEntry.mode,
|
|
2156
|
-
srcEntry.size,
|
|
2157
|
-
Date.now(),
|
|
2158
|
-
srcEntry.symlinkTarget
|
|
2159
|
-
);
|
|
2160
|
-
if (srcEntry.type === "file") {
|
|
2161
|
-
const chunks = this.#chunks(srcPrefixed);
|
|
2162
|
-
for (const chunk of chunks) {
|
|
2163
|
-
this.#stmt(
|
|
2164
|
-
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
2165
|
-
).run(destPrefixed, chunk.chunkIndex, chunk.data);
|
|
2058
|
+
this.#sql.run`DELETE FROM fs_entries WHERE path = ${srcPrefixed} OR path LIKE ${srcPrefixed} || '/%'`;
|
|
2059
|
+
} else {
|
|
2060
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2061
|
+
VALUES (${destPrefixed}, ${srcEntry.type}, ${srcEntry.mode}, ${srcEntry.size}, ${Date.now()}, ${srcEntry.symlinkTarget})`;
|
|
2062
|
+
if (srcEntry.type === "file") {
|
|
2063
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2064
|
+
for (const chunk of chunks) {
|
|
2065
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${destPrefixed}, ${chunk.chunkIndex}, ${chunk.data})`;
|
|
2066
|
+
}
|
|
2166
2067
|
}
|
|
2068
|
+
this.#sql.run`DELETE FROM fs_entries WHERE path = ${srcPrefixed}`;
|
|
2167
2069
|
}
|
|
2168
|
-
|
|
2169
|
-
}
|
|
2170
|
-
|
|
2070
|
+
},
|
|
2071
|
+
{ mode: "deferred" }
|
|
2072
|
+
);
|
|
2171
2073
|
}
|
|
2172
2074
|
resolvePath(base, relativePath) {
|
|
2173
2075
|
return path2.posix.resolve(base, relativePath);
|
|
2174
2076
|
}
|
|
2175
2077
|
getAllPaths() {
|
|
2176
|
-
const rows = z6.array(pathRow).parse(this.#
|
|
2078
|
+
const rows = z6.array(pathRow).parse(this.#sql.all`SELECT path FROM fs_entries ORDER BY path`);
|
|
2177
2079
|
return rows.map((row) => row.path);
|
|
2178
2080
|
}
|
|
2179
2081
|
async realpath(filePath) {
|
|
2180
2082
|
const normalized = this.#normalizePath(filePath);
|
|
2181
2083
|
const prefixed = this.#prefixPath(normalized);
|
|
2182
2084
|
const resolved = this.#resolveSymlink(prefixed);
|
|
2183
|
-
const exists = this.#
|
|
2184
|
-
resolved
|
|
2185
|
-
);
|
|
2085
|
+
const exists = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${resolved}`;
|
|
2186
2086
|
if (!exists) {
|
|
2187
2087
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2188
2088
|
}
|
|
@@ -2192,9 +2092,7 @@ var SqliteFs = class {
|
|
|
2192
2092
|
const normalized = this.#normalizePath(filePath);
|
|
2193
2093
|
const prefixed = this.#prefixPath(normalized);
|
|
2194
2094
|
const resolved = this.#resolveSymlink(prefixed);
|
|
2195
|
-
const result = this.#
|
|
2196
|
-
"UPDATE fs_entries SET mtime = ? WHERE path = ?"
|
|
2197
|
-
).run(mtime.getTime(), resolved);
|
|
2095
|
+
const result = this.#sql.run`UPDATE fs_entries SET mtime = ${mtime.getTime()} WHERE path = ${resolved}`;
|
|
2198
2096
|
if (result.changes === 0) {
|
|
2199
2097
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2200
2098
|
}
|
|
@@ -2202,9 +2100,7 @@ var SqliteFs = class {
|
|
|
2202
2100
|
async chmod(filePath, mode) {
|
|
2203
2101
|
const normalized = this.#normalizePath(filePath);
|
|
2204
2102
|
const prefixed = this.#prefixPath(normalized);
|
|
2205
|
-
const result = this.#
|
|
2206
|
-
"UPDATE fs_entries SET mode = ? WHERE path = ?"
|
|
2207
|
-
).run(mode, prefixed);
|
|
2103
|
+
const result = this.#sql.run`UPDATE fs_entries SET mode = ${mode} WHERE path = ${prefixed}`;
|
|
2208
2104
|
if (result.changes === 0) {
|
|
2209
2105
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2210
2106
|
}
|
|
@@ -2212,19 +2108,19 @@ var SqliteFs = class {
|
|
|
2212
2108
|
async symlink(target, linkPath) {
|
|
2213
2109
|
const normalized = this.#normalizePath(linkPath);
|
|
2214
2110
|
const prefixed = this.#prefixPath(normalized);
|
|
2215
|
-
const existing = this.#
|
|
2216
|
-
prefixed
|
|
2217
|
-
);
|
|
2111
|
+
const existing = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${prefixed}`;
|
|
2218
2112
|
if (existing) {
|
|
2219
2113
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
2220
2114
|
}
|
|
2221
|
-
|
|
2222
|
-
this.#
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2115
|
+
transaction(
|
|
2116
|
+
this.#db,
|
|
2117
|
+
() => {
|
|
2118
|
+
this.#ensureParentExists(prefixed);
|
|
2119
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2120
|
+
VALUES (${prefixed}, 'symlink', 511, 0, ${Date.now()}, ${target})`;
|
|
2121
|
+
},
|
|
2122
|
+
{ mode: "deferred" }
|
|
2123
|
+
);
|
|
2228
2124
|
}
|
|
2229
2125
|
async link(existingPath, newPath) {
|
|
2230
2126
|
const srcNormalized = this.#normalizePath(existingPath);
|
|
@@ -2232,7 +2128,7 @@ var SqliteFs = class {
|
|
|
2232
2128
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2233
2129
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2234
2130
|
const srcEntry = entryRow.optional().parse(
|
|
2235
|
-
this.#
|
|
2131
|
+
this.#sql.get`SELECT * FROM fs_entries WHERE path = ${srcPrefixed}`
|
|
2236
2132
|
);
|
|
2237
2133
|
if (!srcEntry) {
|
|
2238
2134
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
@@ -2240,33 +2136,29 @@ var SqliteFs = class {
|
|
|
2240
2136
|
if (srcEntry.type !== "file") {
|
|
2241
2137
|
throw new Error(`link: not supported for directories: ${existingPath}`);
|
|
2242
2138
|
}
|
|
2243
|
-
const existing = this.#
|
|
2244
|
-
destPrefixed
|
|
2245
|
-
);
|
|
2139
|
+
const existing = this.#sql.get`SELECT 1 FROM fs_entries WHERE path = ${destPrefixed}`;
|
|
2246
2140
|
if (existing) {
|
|
2247
2141
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
2248
2142
|
}
|
|
2249
|
-
|
|
2250
|
-
this.#
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
}
|
|
2261
|
-
|
|
2143
|
+
transaction(
|
|
2144
|
+
this.#db,
|
|
2145
|
+
() => {
|
|
2146
|
+
this.#ensureParentExists(destPrefixed);
|
|
2147
|
+
this.#sql.run`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
2148
|
+
VALUES (${destPrefixed}, 'file', ${srcEntry.mode}, ${srcEntry.size}, ${Date.now()})`;
|
|
2149
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2150
|
+
for (const chunk of chunks) {
|
|
2151
|
+
this.#sql.run`INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (${destPrefixed}, ${chunk.chunkIndex}, ${chunk.data})`;
|
|
2152
|
+
}
|
|
2153
|
+
},
|
|
2154
|
+
{ mode: "deferred" }
|
|
2155
|
+
);
|
|
2262
2156
|
}
|
|
2263
2157
|
async readlink(linkPath) {
|
|
2264
2158
|
const normalized = this.#normalizePath(linkPath);
|
|
2265
2159
|
const prefixed = this.#prefixPath(normalized);
|
|
2266
2160
|
const entry = linkRow.optional().parse(
|
|
2267
|
-
this.#
|
|
2268
|
-
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
2269
|
-
).get(prefixed)
|
|
2161
|
+
this.#sql.get`SELECT type, symlinkTarget FROM fs_entries WHERE path = ${prefixed}`
|
|
2270
2162
|
);
|
|
2271
2163
|
if (!entry) {
|
|
2272
2164
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
@@ -2313,6 +2205,38 @@ GO
|
|
|
2313
2205
|
`;
|
|
2314
2206
|
}
|
|
2315
2207
|
|
|
2208
|
+
// packages/text2sql/src/lib/fs/mssql/sqlserver-schema-lock.ts
|
|
2209
|
+
async function withSqlServerSchemaLock(mssql, pool, schema, run) {
|
|
2210
|
+
const holder = new mssql.Transaction(pool);
|
|
2211
|
+
await holder.begin();
|
|
2212
|
+
let result;
|
|
2213
|
+
try {
|
|
2214
|
+
const lock = new mssql.Request(holder);
|
|
2215
|
+
lock.input(
|
|
2216
|
+
"resource",
|
|
2217
|
+
mssql.NVarChar(255),
|
|
2218
|
+
`deepagents:schema-ddl:${schema}`
|
|
2219
|
+
);
|
|
2220
|
+
const { recordset } = await lock.query(`
|
|
2221
|
+
DECLARE @status int;
|
|
2222
|
+
EXEC @status = sp_getapplock @Resource = @resource, @LockMode = 'Exclusive', @LockOwner = 'Transaction', @LockTimeout = -1;
|
|
2223
|
+
SELECT @status AS status;
|
|
2224
|
+
`);
|
|
2225
|
+
if (recordset[0].status < 0) {
|
|
2226
|
+
throw new Error(
|
|
2227
|
+
`Could not lock the DDL of schema "${schema}": sp_getapplock returned ${recordset[0].status}.`
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
result = await run();
|
|
2231
|
+
} catch (error) {
|
|
2232
|
+
await holder.rollback().catch(() => {
|
|
2233
|
+
});
|
|
2234
|
+
throw error;
|
|
2235
|
+
}
|
|
2236
|
+
await holder.rollback();
|
|
2237
|
+
return result;
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2316
2240
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2317
2241
|
var entryRow2 = z7.object({
|
|
2318
2242
|
path: z7.string(),
|
|
@@ -2393,71 +2317,49 @@ var MssqlFs = class _MssqlFs {
|
|
|
2393
2317
|
if (this.#ownsPool) {
|
|
2394
2318
|
await this.#pool.connect();
|
|
2395
2319
|
}
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2320
|
+
await withSqlServerSchemaLock(
|
|
2321
|
+
_MssqlFs.#requireMssql(),
|
|
2322
|
+
this.#pool,
|
|
2323
|
+
this.#schema,
|
|
2324
|
+
async () => {
|
|
2325
|
+
const schemaReq = this.#pool.request();
|
|
2326
|
+
schemaReq.input("schema", this.#schema);
|
|
2327
|
+
await schemaReq.query(`
|
|
2328
|
+
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = @schema)
|
|
2329
|
+
BEGIN
|
|
2330
|
+
DECLARE @sql NVARCHAR(MAX) = N'CREATE SCHEMA ' + QUOTENAME(@schema);
|
|
2331
|
+
EXEC sp_executesql @sql;
|
|
2332
|
+
END
|
|
2333
|
+
`);
|
|
2334
|
+
const ddl = mssqlFsDDL(this.#schema);
|
|
2335
|
+
const batches = ddl.split(/\bGO\b/i).filter((b) => b.trim());
|
|
2336
|
+
for (const batch of batches) {
|
|
2337
|
+
await this.#pool.request().batch(batch);
|
|
2338
|
+
}
|
|
2339
|
+
await this.#ensureDirectory("/");
|
|
2340
|
+
if (this.#root) {
|
|
2341
|
+
await this.#createParentDirs(this.#root);
|
|
2342
|
+
await this.#ensureDirectory(this.#root);
|
|
2343
|
+
}
|
|
2410
2344
|
}
|
|
2411
|
-
}
|
|
2412
|
-
const rootSlashExists = rowsOf(
|
|
2413
|
-
existsRow,
|
|
2414
|
-
await this.#query(
|
|
2415
|
-
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') THEN 1 ELSE 0 END as [exists]`
|
|
2416
|
-
)
|
|
2417
2345
|
);
|
|
2418
|
-
if (rootSlashExists[0].exists === 0) {
|
|
2419
|
-
await this.#exec(
|
|
2420
|
-
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ('/', 'directory', 493, 0, @p0)`,
|
|
2421
|
-
[Date.now()]
|
|
2422
|
-
);
|
|
2423
|
-
}
|
|
2424
|
-
if (this.#root) {
|
|
2425
|
-
await this.#createParentDirs(this.#root);
|
|
2426
|
-
const rootExists = rowsOf(
|
|
2427
|
-
existsRow,
|
|
2428
|
-
await this.#query(
|
|
2429
|
-
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2430
|
-
[this.#root]
|
|
2431
|
-
)
|
|
2432
|
-
);
|
|
2433
|
-
if (rootExists[0].exists === 0) {
|
|
2434
|
-
await this.#exec(
|
|
2435
|
-
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES (@p0, 'directory', 493, 0, @p1)`,
|
|
2436
|
-
[this.#root, Date.now()]
|
|
2437
|
-
);
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
2346
|
}
|
|
2441
2347
|
async #createParentDirs(p) {
|
|
2442
2348
|
const segments = p.split("/").filter(Boolean);
|
|
2443
2349
|
let currentPath = "/";
|
|
2444
2350
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2445
2351
|
currentPath = path3.posix.join(currentPath, segments[i]);
|
|
2446
|
-
|
|
2447
|
-
existsRow,
|
|
2448
|
-
await this.#query(
|
|
2449
|
-
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2450
|
-
[currentPath]
|
|
2451
|
-
)
|
|
2452
|
-
);
|
|
2453
|
-
if (exists[0].exists === 0) {
|
|
2454
|
-
await this.#exec(
|
|
2455
|
-
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES (@p0, 'directory', 493, 0, @p1)`,
|
|
2456
|
-
[currentPath, Date.now()]
|
|
2457
|
-
);
|
|
2458
|
-
}
|
|
2352
|
+
await this.#ensureDirectory(currentPath);
|
|
2459
2353
|
}
|
|
2460
2354
|
}
|
|
2355
|
+
async #ensureDirectory(p) {
|
|
2356
|
+
await this.#exec(
|
|
2357
|
+
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime)
|
|
2358
|
+
SELECT @p0, 'directory', 493, 0, @p1
|
|
2359
|
+
WHERE NOT EXISTS (SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0)`,
|
|
2360
|
+
[p, Date.now()]
|
|
2361
|
+
);
|
|
2362
|
+
}
|
|
2461
2363
|
#query(sql, params) {
|
|
2462
2364
|
const request = this.#pool.request();
|
|
2463
2365
|
params?.forEach((value, index2) => {
|
|
@@ -2475,14 +2377,14 @@ var MssqlFs = class _MssqlFs {
|
|
|
2475
2377
|
}
|
|
2476
2378
|
async #useTransaction(fn) {
|
|
2477
2379
|
const mssql = _MssqlFs.#requireMssql();
|
|
2478
|
-
const
|
|
2380
|
+
const transaction2 = new mssql.Transaction(this.#pool);
|
|
2479
2381
|
try {
|
|
2480
|
-
await
|
|
2481
|
-
const result = await fn(
|
|
2482
|
-
await
|
|
2382
|
+
await transaction2.begin();
|
|
2383
|
+
const result = await fn(transaction2);
|
|
2384
|
+
await transaction2.commit();
|
|
2483
2385
|
return result;
|
|
2484
2386
|
} catch (error) {
|
|
2485
|
-
await
|
|
2387
|
+
await transaction2.rollback();
|
|
2486
2388
|
throw error;
|
|
2487
2389
|
}
|
|
2488
2390
|
}
|
|
@@ -2517,11 +2419,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2517
2419
|
const dir = path3.posix.dirname(p);
|
|
2518
2420
|
return dir === "" ? "/" : dir;
|
|
2519
2421
|
}
|
|
2520
|
-
async #ensureParentExists(filePath,
|
|
2422
|
+
async #ensureParentExists(filePath, transaction2) {
|
|
2521
2423
|
const parent = this.#dirname(filePath);
|
|
2522
2424
|
const rootPath = this.#root || "/";
|
|
2523
2425
|
if (parent === rootPath || parent === "/") return;
|
|
2524
|
-
const request =
|
|
2426
|
+
const request = transaction2.request();
|
|
2525
2427
|
request.input("p0", parent);
|
|
2526
2428
|
const [entry] = rowsOf(
|
|
2527
2429
|
typeRow2,
|
|
@@ -2530,8 +2432,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
2530
2432
|
)
|
|
2531
2433
|
);
|
|
2532
2434
|
if (!entry) {
|
|
2533
|
-
await this.#ensureParentExists(parent,
|
|
2534
|
-
const insertReq =
|
|
2435
|
+
await this.#ensureParentExists(parent, transaction2);
|
|
2436
|
+
const insertReq = transaction2.request();
|
|
2535
2437
|
insertReq.input("p0", parent);
|
|
2536
2438
|
insertReq.input("p1", Date.now());
|
|
2537
2439
|
await insertReq.query(
|
|
@@ -2541,8 +2443,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
2541
2443
|
throw new Error(`mkdir: parent is not a directory: ${parent}`);
|
|
2542
2444
|
}
|
|
2543
2445
|
}
|
|
2544
|
-
async #writeChunks(filePath, content,
|
|
2545
|
-
const deleteReq =
|
|
2446
|
+
async #writeChunks(filePath, content, transaction2) {
|
|
2447
|
+
const deleteReq = transaction2.request();
|
|
2546
2448
|
deleteReq.input("p0", filePath);
|
|
2547
2449
|
await deleteReq.query(
|
|
2548
2450
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
@@ -2552,7 +2454,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2552
2454
|
i,
|
|
2553
2455
|
Math.min(i + this.#chunkSize, content.length)
|
|
2554
2456
|
);
|
|
2555
|
-
const insertReq =
|
|
2457
|
+
const insertReq = transaction2.request();
|
|
2556
2458
|
insertReq.input("p0", filePath);
|
|
2557
2459
|
insertReq.input("p1", Math.floor(i / this.#chunkSize));
|
|
2558
2460
|
insertReq.input("p2", Buffer.from(chunk));
|
|
@@ -2561,11 +2463,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2561
2463
|
);
|
|
2562
2464
|
}
|
|
2563
2465
|
}
|
|
2564
|
-
async #readChunks(filePath,
|
|
2466
|
+
async #readChunks(filePath, transaction2) {
|
|
2565
2467
|
const sql = `SELECT data FROM ${this.#t("fs_chunks")} WHERE path = @p0 ORDER BY chunkIndex`;
|
|
2566
2468
|
const rows = rowsOf(
|
|
2567
2469
|
dataRow2,
|
|
2568
|
-
|
|
2470
|
+
transaction2 ? await transaction2.request().input("p0", filePath).query(sql) : await this.#query(sql, [filePath])
|
|
2569
2471
|
);
|
|
2570
2472
|
if (rows.length === 0) {
|
|
2571
2473
|
return new Uint8Array(0);
|
|
@@ -2661,9 +2563,9 @@ var MssqlFs = class _MssqlFs {
|
|
|
2661
2563
|
const prefixed = this.#prefixPath(normalized);
|
|
2662
2564
|
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
2663
2565
|
const data = this.#toUint8Array(content, encoding);
|
|
2664
|
-
await this.#useTransaction(async (
|
|
2665
|
-
await this.#ensureParentExists(prefixed,
|
|
2666
|
-
const request =
|
|
2566
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2567
|
+
await this.#ensureParentExists(prefixed, transaction2);
|
|
2568
|
+
const request = transaction2.request();
|
|
2667
2569
|
request.input("p0", prefixed);
|
|
2668
2570
|
request.input("p1", data.length);
|
|
2669
2571
|
request.input("p2", Date.now());
|
|
@@ -2677,7 +2579,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2677
2579
|
INSERT (path, type, mode, size, mtime)
|
|
2678
2580
|
VALUES (@p0, 'file', 420, @p1, @p2);
|
|
2679
2581
|
`);
|
|
2680
|
-
await this.#writeChunks(prefixed, data,
|
|
2582
|
+
await this.#writeChunks(prefixed, data, transaction2);
|
|
2681
2583
|
});
|
|
2682
2584
|
}
|
|
2683
2585
|
async appendFile(filePath, content, options) {
|
|
@@ -2685,9 +2587,9 @@ var MssqlFs = class _MssqlFs {
|
|
|
2685
2587
|
const prefixed = this.#prefixPath(normalized);
|
|
2686
2588
|
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
2687
2589
|
const newData = this.#toUint8Array(content, encoding);
|
|
2688
|
-
await this.#useTransaction(async (
|
|
2689
|
-
await this.#ensureParentExists(prefixed,
|
|
2690
|
-
const checkReq =
|
|
2590
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2591
|
+
await this.#ensureParentExists(prefixed, transaction2);
|
|
2592
|
+
const checkReq = transaction2.request();
|
|
2691
2593
|
checkReq.input("p0", prefixed);
|
|
2692
2594
|
const [entry] = rowsOf(
|
|
2693
2595
|
typeRow2,
|
|
@@ -2698,11 +2600,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2698
2600
|
if (entry && entry.type !== "file") {
|
|
2699
2601
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
2700
2602
|
}
|
|
2701
|
-
const existing = entry ? await this.#readChunks(prefixed,
|
|
2603
|
+
const existing = entry ? await this.#readChunks(prefixed, transaction2) : new Uint8Array(0);
|
|
2702
2604
|
const combined = new Uint8Array(existing.length + newData.length);
|
|
2703
2605
|
combined.set(existing, 0);
|
|
2704
2606
|
combined.set(newData, existing.length);
|
|
2705
|
-
const upsertReq =
|
|
2607
|
+
const upsertReq = transaction2.request();
|
|
2706
2608
|
upsertReq.input("p0", prefixed);
|
|
2707
2609
|
upsertReq.input("p1", combined.length);
|
|
2708
2610
|
upsertReq.input("p2", Date.now());
|
|
@@ -2716,7 +2618,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2716
2618
|
INSERT (path, type, mode, size, mtime)
|
|
2717
2619
|
VALUES (@p0, 'file', 420, @p1, @p2);
|
|
2718
2620
|
`);
|
|
2719
|
-
await this.#writeChunks(prefixed, combined,
|
|
2621
|
+
await this.#writeChunks(prefixed, combined, transaction2);
|
|
2720
2622
|
});
|
|
2721
2623
|
}
|
|
2722
2624
|
async exists(filePath) {
|
|
@@ -2792,7 +2694,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2792
2694
|
}
|
|
2793
2695
|
throw new Error(`EEXIST: file already exists: ${dirPath}`);
|
|
2794
2696
|
}
|
|
2795
|
-
await this.#useTransaction(async (
|
|
2697
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2796
2698
|
if (options?.recursive) {
|
|
2797
2699
|
const rootPath = this.#root || "/";
|
|
2798
2700
|
const relativePath = path3.posix.relative(rootPath, prefixed);
|
|
@@ -2800,7 +2702,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2800
2702
|
let currentPath = rootPath;
|
|
2801
2703
|
for (const segment of segments) {
|
|
2802
2704
|
currentPath = path3.posix.join(currentPath, segment);
|
|
2803
|
-
const checkReq =
|
|
2705
|
+
const checkReq = transaction2.request();
|
|
2804
2706
|
checkReq.input("p0", currentPath);
|
|
2805
2707
|
const [exists] = rowsOf(
|
|
2806
2708
|
typeRow2,
|
|
@@ -2809,7 +2711,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2809
2711
|
)
|
|
2810
2712
|
);
|
|
2811
2713
|
if (!exists) {
|
|
2812
|
-
const insertReq =
|
|
2714
|
+
const insertReq = transaction2.request();
|
|
2813
2715
|
insertReq.input("p0", currentPath);
|
|
2814
2716
|
insertReq.input("p1", Date.now());
|
|
2815
2717
|
await insertReq.query(
|
|
@@ -2821,7 +2723,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2821
2723
|
}
|
|
2822
2724
|
} else {
|
|
2823
2725
|
const parent = this.#dirname(prefixed);
|
|
2824
|
-
const parentReq =
|
|
2726
|
+
const parentReq = transaction2.request();
|
|
2825
2727
|
parentReq.input("p0", parent);
|
|
2826
2728
|
const [parentEntry] = rowsOf(
|
|
2827
2729
|
typeRow2,
|
|
@@ -2835,7 +2737,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2835
2737
|
if (parentEntry.type !== "directory") {
|
|
2836
2738
|
throw new Error(`mkdir: parent is not a directory: ${parent}`);
|
|
2837
2739
|
}
|
|
2838
|
-
const insertReq =
|
|
2740
|
+
const insertReq = transaction2.request();
|
|
2839
2741
|
insertReq.input("p0", prefixed);
|
|
2840
2742
|
insertReq.input("p1", Date.now());
|
|
2841
2743
|
await insertReq.query(
|
|
@@ -2925,9 +2827,9 @@ var MssqlFs = class _MssqlFs {
|
|
|
2925
2827
|
}
|
|
2926
2828
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2927
2829
|
}
|
|
2928
|
-
await this.#useTransaction(async (
|
|
2830
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2929
2831
|
if (entry.type === "directory") {
|
|
2930
|
-
const childrenReq =
|
|
2832
|
+
const childrenReq = transaction2.request();
|
|
2931
2833
|
childrenReq.input("p0", prefixed);
|
|
2932
2834
|
const children = rowsOf(
|
|
2933
2835
|
existsRow,
|
|
@@ -2938,13 +2840,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2938
2840
|
if (children[0].exists === 1 && !options?.recursive) {
|
|
2939
2841
|
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
2940
2842
|
}
|
|
2941
|
-
const deleteReq =
|
|
2843
|
+
const deleteReq = transaction2.request();
|
|
2942
2844
|
deleteReq.input("p0", prefixed);
|
|
2943
2845
|
await deleteReq.query(
|
|
2944
2846
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
2945
2847
|
);
|
|
2946
2848
|
} else {
|
|
2947
|
-
const deleteReq =
|
|
2849
|
+
const deleteReq = transaction2.request();
|
|
2948
2850
|
deleteReq.input("p0", prefixed);
|
|
2949
2851
|
await deleteReq.query(
|
|
2950
2852
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
@@ -2970,10 +2872,10 @@ var MssqlFs = class _MssqlFs {
|
|
|
2970
2872
|
if (srcEntry.type === "directory" && !options?.recursive) {
|
|
2971
2873
|
throw new Error(`cp: -r not specified; omitting directory: ${src}`);
|
|
2972
2874
|
}
|
|
2973
|
-
await this.#useTransaction(async (
|
|
2974
|
-
await this.#ensureParentExists(destPrefixed,
|
|
2875
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2876
|
+
await this.#ensureParentExists(destPrefixed, transaction2);
|
|
2975
2877
|
if (srcEntry.type === "directory") {
|
|
2976
|
-
const allEntriesReq =
|
|
2878
|
+
const allEntriesReq = transaction2.request();
|
|
2977
2879
|
allEntriesReq.input("p0", srcPrefixed);
|
|
2978
2880
|
const allEntries = rowsOf(
|
|
2979
2881
|
entryRow2,
|
|
@@ -2984,7 +2886,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2984
2886
|
for (const entry of allEntries) {
|
|
2985
2887
|
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2986
2888
|
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2987
|
-
const insertReq =
|
|
2889
|
+
const insertReq = transaction2.request();
|
|
2988
2890
|
insertReq.input("p0", newPath);
|
|
2989
2891
|
insertReq.input("p1", entry.type);
|
|
2990
2892
|
insertReq.input("p2", entry.mode);
|
|
@@ -3002,12 +2904,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3002
2904
|
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
|
|
3003
2905
|
`);
|
|
3004
2906
|
if (entry.type === "file") {
|
|
3005
|
-
const deleteChunksReq =
|
|
2907
|
+
const deleteChunksReq = transaction2.request();
|
|
3006
2908
|
deleteChunksReq.input("p0", newPath);
|
|
3007
2909
|
await deleteChunksReq.query(
|
|
3008
2910
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3009
2911
|
);
|
|
3010
|
-
const chunksReq =
|
|
2912
|
+
const chunksReq = transaction2.request();
|
|
3011
2913
|
chunksReq.input("p0", entry.path);
|
|
3012
2914
|
const chunks = rowsOf(
|
|
3013
2915
|
chunkRow2,
|
|
@@ -3016,7 +2918,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3016
2918
|
)
|
|
3017
2919
|
);
|
|
3018
2920
|
for (const chunk of chunks) {
|
|
3019
|
-
const chunkInsertReq =
|
|
2921
|
+
const chunkInsertReq = transaction2.request();
|
|
3020
2922
|
chunkInsertReq.input("p0", newPath);
|
|
3021
2923
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
3022
2924
|
chunkInsertReq.input("p2", chunk.data);
|
|
@@ -3027,7 +2929,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3027
2929
|
}
|
|
3028
2930
|
}
|
|
3029
2931
|
} else {
|
|
3030
|
-
const insertReq =
|
|
2932
|
+
const insertReq = transaction2.request();
|
|
3031
2933
|
insertReq.input("p0", destPrefixed);
|
|
3032
2934
|
insertReq.input("p1", srcEntry.type);
|
|
3033
2935
|
insertReq.input("p2", srcEntry.mode);
|
|
@@ -3045,7 +2947,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3045
2947
|
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
|
|
3046
2948
|
`);
|
|
3047
2949
|
if (srcEntry.type === "file") {
|
|
3048
|
-
const chunksReq =
|
|
2950
|
+
const chunksReq = transaction2.request();
|
|
3049
2951
|
chunksReq.input("p0", srcPrefixed);
|
|
3050
2952
|
const chunks = rowsOf(
|
|
3051
2953
|
chunkRow2,
|
|
@@ -3053,13 +2955,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3053
2955
|
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3054
2956
|
)
|
|
3055
2957
|
);
|
|
3056
|
-
const deleteChunksReq =
|
|
2958
|
+
const deleteChunksReq = transaction2.request();
|
|
3057
2959
|
deleteChunksReq.input("p0", destPrefixed);
|
|
3058
2960
|
await deleteChunksReq.query(
|
|
3059
2961
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3060
2962
|
);
|
|
3061
2963
|
for (const chunk of chunks) {
|
|
3062
|
-
const chunkInsertReq =
|
|
2964
|
+
const chunkInsertReq = transaction2.request();
|
|
3063
2965
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3064
2966
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
3065
2967
|
chunkInsertReq.input("p2", chunk.data);
|
|
@@ -3086,10 +2988,10 @@ var MssqlFs = class _MssqlFs {
|
|
|
3086
2988
|
if (!srcEntry) {
|
|
3087
2989
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
3088
2990
|
}
|
|
3089
|
-
await this.#useTransaction(async (
|
|
3090
|
-
await this.#ensureParentExists(destPrefixed,
|
|
2991
|
+
await this.#useTransaction(async (transaction2) => {
|
|
2992
|
+
await this.#ensureParentExists(destPrefixed, transaction2);
|
|
3091
2993
|
if (srcEntry.type === "directory") {
|
|
3092
|
-
const allEntriesReq =
|
|
2994
|
+
const allEntriesReq = transaction2.request();
|
|
3093
2995
|
allEntriesReq.input("p0", srcPrefixed);
|
|
3094
2996
|
const allEntries = rowsOf(
|
|
3095
2997
|
entryRow2,
|
|
@@ -3097,7 +2999,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3097
2999
|
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%' ORDER BY path DESC`
|
|
3098
3000
|
)
|
|
3099
3001
|
);
|
|
3100
|
-
const destDeleteReq =
|
|
3002
|
+
const destDeleteReq = transaction2.request();
|
|
3101
3003
|
destDeleteReq.input("dp0", destPrefixed);
|
|
3102
3004
|
await destDeleteReq.query(
|
|
3103
3005
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @dp0 OR path LIKE @dp0 + '/%'`
|
|
@@ -3105,7 +3007,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3105
3007
|
for (const entry of [...allEntries].reverse()) {
|
|
3106
3008
|
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
3107
3009
|
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
3108
|
-
const insertReq =
|
|
3010
|
+
const insertReq = transaction2.request();
|
|
3109
3011
|
insertReq.input("p0", newPath);
|
|
3110
3012
|
insertReq.input("p1", entry.type);
|
|
3111
3013
|
insertReq.input("p2", entry.mode);
|
|
@@ -3123,12 +3025,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3123
3025
|
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
|
|
3124
3026
|
`);
|
|
3125
3027
|
if (entry.type === "file") {
|
|
3126
|
-
const deleteChunksReq =
|
|
3028
|
+
const deleteChunksReq = transaction2.request();
|
|
3127
3029
|
deleteChunksReq.input("p0", newPath);
|
|
3128
3030
|
await deleteChunksReq.query(
|
|
3129
3031
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3130
3032
|
);
|
|
3131
|
-
const chunksReq =
|
|
3033
|
+
const chunksReq = transaction2.request();
|
|
3132
3034
|
chunksReq.input("p0", entry.path);
|
|
3133
3035
|
const chunks = rowsOf(
|
|
3134
3036
|
chunkRow2,
|
|
@@ -3137,7 +3039,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3137
3039
|
)
|
|
3138
3040
|
);
|
|
3139
3041
|
for (const chunk of chunks) {
|
|
3140
|
-
const chunkInsertReq =
|
|
3042
|
+
const chunkInsertReq = transaction2.request();
|
|
3141
3043
|
chunkInsertReq.input("p0", newPath);
|
|
3142
3044
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
3143
3045
|
chunkInsertReq.input("p2", chunk.data);
|
|
@@ -3147,13 +3049,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3147
3049
|
}
|
|
3148
3050
|
}
|
|
3149
3051
|
}
|
|
3150
|
-
const deleteReq =
|
|
3052
|
+
const deleteReq = transaction2.request();
|
|
3151
3053
|
deleteReq.input("p0", srcPrefixed);
|
|
3152
3054
|
await deleteReq.query(
|
|
3153
3055
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
3154
3056
|
);
|
|
3155
3057
|
} else {
|
|
3156
|
-
const insertReq =
|
|
3058
|
+
const insertReq = transaction2.request();
|
|
3157
3059
|
insertReq.input("p0", destPrefixed);
|
|
3158
3060
|
insertReq.input("p1", srcEntry.type);
|
|
3159
3061
|
insertReq.input("p2", srcEntry.mode);
|
|
@@ -3171,12 +3073,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3171
3073
|
VALUES (@p0, @p1, @p2, @p3, @p4, @p5);
|
|
3172
3074
|
`);
|
|
3173
3075
|
if (srcEntry.type === "file") {
|
|
3174
|
-
const deleteChunksReq =
|
|
3076
|
+
const deleteChunksReq = transaction2.request();
|
|
3175
3077
|
deleteChunksReq.input("p0", destPrefixed);
|
|
3176
3078
|
await deleteChunksReq.query(
|
|
3177
3079
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3178
3080
|
);
|
|
3179
|
-
const chunksReq =
|
|
3081
|
+
const chunksReq = transaction2.request();
|
|
3180
3082
|
chunksReq.input("p0", srcPrefixed);
|
|
3181
3083
|
const chunks = rowsOf(
|
|
3182
3084
|
chunkRow2,
|
|
@@ -3185,7 +3087,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3185
3087
|
)
|
|
3186
3088
|
);
|
|
3187
3089
|
for (const chunk of chunks) {
|
|
3188
|
-
const chunkInsertReq =
|
|
3090
|
+
const chunkInsertReq = transaction2.request();
|
|
3189
3091
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3190
3092
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
3191
3093
|
chunkInsertReq.input("p2", chunk.data);
|
|
@@ -3194,7 +3096,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3194
3096
|
);
|
|
3195
3097
|
}
|
|
3196
3098
|
}
|
|
3197
|
-
const deleteReq =
|
|
3099
|
+
const deleteReq = transaction2.request();
|
|
3198
3100
|
deleteReq.input("p0", srcPrefixed);
|
|
3199
3101
|
await deleteReq.query(
|
|
3200
3102
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
@@ -3271,9 +3173,9 @@ var MssqlFs = class _MssqlFs {
|
|
|
3271
3173
|
if (existingRows[0].exists === 1) {
|
|
3272
3174
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
3273
3175
|
}
|
|
3274
|
-
await this.#useTransaction(async (
|
|
3275
|
-
await this.#ensureParentExists(prefixed,
|
|
3276
|
-
const insertReq =
|
|
3176
|
+
await this.#useTransaction(async (transaction2) => {
|
|
3177
|
+
await this.#ensureParentExists(prefixed, transaction2);
|
|
3178
|
+
const insertReq = transaction2.request();
|
|
3277
3179
|
insertReq.input("p0", prefixed);
|
|
3278
3180
|
insertReq.input("p1", Date.now());
|
|
3279
3181
|
insertReq.input("p2", target);
|
|
@@ -3311,9 +3213,9 @@ var MssqlFs = class _MssqlFs {
|
|
|
3311
3213
|
if (existingRows[0].exists === 1) {
|
|
3312
3214
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
3313
3215
|
}
|
|
3314
|
-
await this.#useTransaction(async (
|
|
3315
|
-
await this.#ensureParentExists(destPrefixed,
|
|
3316
|
-
const insertReq =
|
|
3216
|
+
await this.#useTransaction(async (transaction2) => {
|
|
3217
|
+
await this.#ensureParentExists(destPrefixed, transaction2);
|
|
3218
|
+
const insertReq = transaction2.request();
|
|
3317
3219
|
insertReq.input("p0", destPrefixed);
|
|
3318
3220
|
insertReq.input("p1", srcEntry.mode);
|
|
3319
3221
|
insertReq.input("p2", srcEntry.size);
|
|
@@ -3322,7 +3224,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3322
3224
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime)
|
|
3323
3225
|
VALUES (@p0, 'file', @p1, @p2, @p3)`
|
|
3324
3226
|
);
|
|
3325
|
-
const chunksReq =
|
|
3227
|
+
const chunksReq = transaction2.request();
|
|
3326
3228
|
chunksReq.input("p0", srcPrefixed);
|
|
3327
3229
|
const chunks = rowsOf(
|
|
3328
3230
|
chunkRow2,
|
|
@@ -3331,7 +3233,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3331
3233
|
)
|
|
3332
3234
|
);
|
|
3333
3235
|
for (const chunk of chunks) {
|
|
3334
|
-
const chunkInsertReq =
|
|
3236
|
+
const chunkInsertReq = transaction2.request();
|
|
3335
3237
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3336
3238
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
3337
3239
|
chunkInsertReq.input("p2", chunk.data);
|
|
@@ -3365,6 +3267,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3365
3267
|
import { createRequire as createRequire2 } from "node:module";
|
|
3366
3268
|
import * as path4 from "node:path";
|
|
3367
3269
|
import z8 from "zod";
|
|
3270
|
+
import { lockSchemaDDL } from "@deepagents/context";
|
|
3368
3271
|
|
|
3369
3272
|
// packages/text2sql/src/lib/fs/postgres/ddl.postgres-fs.ts
|
|
3370
3273
|
function postgresFsDDL(schema) {
|
|
@@ -3468,58 +3371,34 @@ var PostgresFs = class _PostgresFs {
|
|
|
3468
3371
|
}
|
|
3469
3372
|
return fs;
|
|
3470
3373
|
}
|
|
3374
|
+
// The schema lock is held until this transaction commits, so concurrent
|
|
3375
|
+
// openers also create the root directories one at a time.
|
|
3471
3376
|
async #initialize() {
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
existsRow2,
|
|
3476
|
-
await this.#query(
|
|
3477
|
-
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') AS exists`
|
|
3478
|
-
)
|
|
3479
|
-
);
|
|
3480
|
-
if (!rootSlashExists[0].exists) {
|
|
3481
|
-
await this.#exec(
|
|
3482
|
-
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ('/', 'directory', 493, 0, $1)`,
|
|
3483
|
-
[Date.now()]
|
|
3484
|
-
);
|
|
3485
|
-
}
|
|
3486
|
-
if (this.#root) {
|
|
3487
|
-
await this.#createParentDirs(this.#root);
|
|
3488
|
-
const rootExists = rowsOf2(
|
|
3489
|
-
existsRow2,
|
|
3490
|
-
await this.#query(
|
|
3491
|
-
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3492
|
-
[this.#root]
|
|
3493
|
-
)
|
|
3377
|
+
await this.#useTransaction(async (client) => {
|
|
3378
|
+
await client.query(
|
|
3379
|
+
lockSchemaDDL(postgresFsDDL(this.#schema), this.#schema)
|
|
3494
3380
|
);
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
);
|
|
3381
|
+
await this.#ensureDirectory(client, "/");
|
|
3382
|
+
if (this.#root) {
|
|
3383
|
+
await this.#createParentDirs(client, this.#root);
|
|
3384
|
+
await this.#ensureDirectory(client, this.#root);
|
|
3500
3385
|
}
|
|
3501
|
-
}
|
|
3386
|
+
});
|
|
3502
3387
|
}
|
|
3503
|
-
async #createParentDirs(p) {
|
|
3388
|
+
async #createParentDirs(client, p) {
|
|
3504
3389
|
const segments = p.split("/").filter(Boolean);
|
|
3505
3390
|
let currentPath = "/";
|
|
3506
3391
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3507
3392
|
currentPath = path4.posix.join(currentPath, segments[i]);
|
|
3508
|
-
|
|
3509
|
-
existsRow2,
|
|
3510
|
-
await this.#query(
|
|
3511
|
-
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3512
|
-
[currentPath]
|
|
3513
|
-
)
|
|
3514
|
-
);
|
|
3515
|
-
if (!exists[0].exists) {
|
|
3516
|
-
await this.#exec(
|
|
3517
|
-
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ($1, 'directory', 493, 0, $2)`,
|
|
3518
|
-
[currentPath, Date.now()]
|
|
3519
|
-
);
|
|
3520
|
-
}
|
|
3393
|
+
await this.#ensureDirectory(client, currentPath);
|
|
3521
3394
|
}
|
|
3522
3395
|
}
|
|
3396
|
+
async #ensureDirectory(client, p) {
|
|
3397
|
+
await client.query(
|
|
3398
|
+
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ($1, 'directory', 493, 0, $2) ON CONFLICT (path) DO NOTHING`,
|
|
3399
|
+
[p, Date.now()]
|
|
3400
|
+
);
|
|
3401
|
+
}
|
|
3523
3402
|
#query(sql, params) {
|
|
3524
3403
|
return this.#pool.query(sql, params);
|
|
3525
3404
|
}
|