@deepagents/text2sql 7.0.2 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/bin/sql.js +57 -32
- package/dist/index.js +793 -498
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/adapter.d.ts +23 -1
- package/dist/lib/adapters/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/bigquery-fk.d.ts +0 -11
- package/dist/lib/adapters/bigquery/bigquery-fk.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/bigquery-rows.d.ts +22 -0
- package/dist/lib/adapters/bigquery/bigquery-rows.d.ts.map +1 -0
- package/dist/lib/adapters/bigquery/bigquery.d.ts +1 -1
- package/dist/lib/adapters/bigquery/bigquery.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/constraint.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/index.d.ts +6 -13
- package/dist/lib/adapters/bigquery/index.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/index.js +244 -51
- package/dist/lib/adapters/bigquery/index.js.map +4 -4
- package/dist/lib/adapters/bigquery/indexes.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/row-count.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/table.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/bigquery/view.bigquery.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/clickhouse-rows.d.ts +7 -0
- package/dist/lib/adapters/clickhouse/clickhouse-rows.d.ts.map +1 -0
- package/dist/lib/adapters/clickhouse/clickhouse.d.ts +1 -1
- package/dist/lib/adapters/clickhouse/clickhouse.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/constraint.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/index.js +133 -44
- package/dist/lib/adapters/clickhouse/index.js.map +4 -4
- package/dist/lib/adapters/clickhouse/indexes.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/info.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/row-count.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/table.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/clickhouse/view.clickhouse.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/duckdb.d.ts +1 -1
- package/dist/lib/adapters/duckdb/duckdb.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/duckdb.groundings.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/index.d.ts +8 -10
- package/dist/lib/adapters/duckdb/index.d.ts.map +1 -1
- package/dist/lib/adapters/duckdb/index.js +1549 -1412
- package/dist/lib/adapters/duckdb/index.js.map +4 -4
- package/dist/lib/adapters/groundings/index.js.map +1 -1
- package/dist/lib/adapters/groundings/rows.d.ts +32 -0
- package/dist/lib/adapters/groundings/rows.d.ts.map +1 -0
- package/dist/lib/adapters/mysql/column-stats.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/column-values.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/constraint.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/index.d.ts +2 -4
- package/dist/lib/adapters/mysql/index.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/index.js +230 -76
- package/dist/lib/adapters/mysql/index.js.map +4 -4
- package/dist/lib/adapters/mysql/indexes.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/info.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/mysql-rows.d.ts +11 -0
- package/dist/lib/adapters/mysql/mysql-rows.d.ts.map +1 -0
- package/dist/lib/adapters/mysql/mysql.d.ts +1 -1
- package/dist/lib/adapters/mysql/mysql.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/row-count.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts +3 -2
- package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts +2 -2
- package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/column-stats.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/constraint.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/index.d.ts +2 -4
- package/dist/lib/adapters/postgres/index.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/index.js +266 -487
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/postgres/indexes.postgres.grounding.d.ts +1 -5
- package/dist/lib/adapters/postgres/indexes.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/info.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/postgres-rows.d.ts +7 -0
- package/dist/lib/adapters/postgres/postgres-rows.d.ts.map +1 -0
- package/dist/lib/adapters/postgres/postgres.d.ts +6 -1
- package/dist/lib/adapters/postgres/postgres.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/row-count.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/table.postgres.grounding.d.ts +5 -4
- package/dist/lib/adapters/postgres/table.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/postgres/view.postgres.grounding.d.ts +3 -3
- package/dist/lib/adapters/postgres/view.postgres.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/definitions.posthog.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/index.d.ts +4 -5
- package/dist/lib/adapters/posthog/index.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/index.js +349 -287
- package/dist/lib/adapters/posthog/index.js.map +4 -4
- package/dist/lib/adapters/posthog/posthog.d.ts +2 -2
- package/dist/lib/adapters/posthog/posthog.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/posthog.sql-policy.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/schema.posthog.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/transport.d.ts.map +1 -1
- package/dist/lib/adapters/posthog/types.d.ts +16 -6
- package/dist/lib/adapters/posthog/types.d.ts.map +1 -1
- package/dist/lib/adapters/spreadsheet/index.js +113 -34
- package/dist/lib/adapters/spreadsheet/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/column-stats.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/constraint.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/index.js +136 -49
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/indexes.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/info.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/row-count.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/sqlite-rows.d.ts +41 -0
- package/dist/lib/adapters/sqlite/sqlite-rows.d.ts.map +1 -0
- package/dist/lib/adapters/sqlite/sqlite.d.ts +1 -1
- package/dist/lib/adapters/sqlite/sqlite.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/table.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlite/view.sqlite.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/column-stats.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/constraint.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.d.ts +2 -4
- package/dist/lib/adapters/sqlserver/index.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.js +223 -455
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/indexes.sqlserver.grounding.d.ts +1 -5
- package/dist/lib/adapters/sqlserver/indexes.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/info.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/row-count.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/sqlserver-rows.d.ts +7 -0
- package/dist/lib/adapters/sqlserver/sqlserver-rows.d.ts.map +1 -0
- package/dist/lib/adapters/sqlserver/sqlserver.d.ts +6 -1
- package/dist/lib/adapters/sqlserver/sqlserver.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts +4 -3
- package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/view.sqlserver.grounding.d.ts +3 -3
- package/dist/lib/adapters/sqlserver/view.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/agents/sql-transform-plugins.d.ts.map +1 -1
- package/dist/lib/checkpoint.d.ts +34 -21
- package/dist/lib/checkpoint.d.ts.map +1 -1
- package/dist/lib/file-cache.d.ts +6 -1
- package/dist/lib/file-cache.d.ts.map +1 -1
- package/dist/lib/fs/columns.d.ts +14 -0
- package/dist/lib/fs/columns.d.ts.map +1 -0
- package/dist/lib/fs/mssql/mssql-fs.d.ts +4 -4
- package/dist/lib/fs/mssql/mssql-fs.d.ts.map +1 -1
- package/dist/lib/fs/postgres/postgres-fs.d.ts +4 -4
- package/dist/lib/fs/postgres/postgres-fs.d.ts.map +1 -1
- package/dist/lib/fs/sqlite/sqlite-fs.d.ts +4 -4
- package/dist/lib/fs/sqlite/sqlite-fs.d.ts.map +1 -1
- package/dist/lib/index-cache.d.ts +4 -3
- package/dist/lib/index-cache.d.ts.map +1 -1
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts +1 -2
- package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts.map +1 -1
- package/dist/lib/synthesis/decorators/filtered-producer.d.ts +0 -2
- package/dist/lib/synthesis/decorators/filtered-producer.d.ts.map +1 -1
- package/dist/lib/synthesis/decorators/validated-producer.d.ts +1 -3
- package/dist/lib/synthesis/decorators/validated-producer.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/tool-input.d.ts +6 -0
- package/dist/lib/synthesis/extractors/tool-input.d.ts.map +1 -0
- package/dist/lib/synthesis/index.js +124 -114
- package/dist/lib/synthesis/index.js.map +4 -4
- package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts +0 -2
- package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +0 -3
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +0 -2
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ function validateAdapterNames(names) {
|
|
|
20
20
|
|
|
21
21
|
// packages/text2sql/src/lib/adapters/adapter.ts
|
|
22
22
|
import { format as formatSql } from "sql-formatter";
|
|
23
|
+
import { z } from "zod";
|
|
23
24
|
|
|
24
25
|
// packages/text2sql/src/lib/agents/exceptions.ts
|
|
25
26
|
var sqlValidationMarker = /* @__PURE__ */ Symbol("SQLValidationError");
|
|
@@ -192,6 +193,16 @@ function createGroundingContext(options = {}) {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
// packages/text2sql/src/lib/adapters/adapter.ts
|
|
196
|
+
function groundingFor(adapterType, create) {
|
|
197
|
+
return (adapter) => {
|
|
198
|
+
if (!(adapter instanceof adapterType)) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`A ${adapterType.name} grounding needs a ${adapterType.name} adapter, not ${adapter.constructor.name}.`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return create(adapter);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
195
206
|
var Adapter = class {
|
|
196
207
|
#policyAnalyzer;
|
|
197
208
|
/**
|
|
@@ -452,6 +463,40 @@ var Adapter = class {
|
|
|
452
463
|
}
|
|
453
464
|
return decoded;
|
|
454
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* Run an introspection query and check every row against `row`, the shape
|
|
468
|
+
* the driver returns for that query. A row of any other shape throws.
|
|
469
|
+
*/
|
|
470
|
+
async runQuery(sql, row) {
|
|
471
|
+
const rows = z.array(row).safeParse(await this.queryRows(sql));
|
|
472
|
+
if (!rows.success) {
|
|
473
|
+
throw new Error(
|
|
474
|
+
`${this.constructor.name} introspection query returned rows of an unexpected shape:
|
|
475
|
+
${z.prettifyError(rows.error)}
|
|
476
|
+
SQL: ${sql.trim()}`,
|
|
477
|
+
{ cause: rows.error }
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
return rows.data;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* The rows in a driver's execute() result: the result itself when it is an
|
|
484
|
+
* array, otherwise the first array found at one of `paths` (dot-separated,
|
|
485
|
+
* so `recordsets.0` reads `result.recordsets[0]`).
|
|
486
|
+
*/
|
|
487
|
+
rowsFrom(result, paths) {
|
|
488
|
+
if (Array.isArray(result)) return result;
|
|
489
|
+
for (const path7 of paths) {
|
|
490
|
+
const rows = path7.split(".").reduce(
|
|
491
|
+
(value, key) => typeof value === "object" && value !== null ? Reflect.get(value, key) : void 0,
|
|
492
|
+
result
|
|
493
|
+
);
|
|
494
|
+
if (Array.isArray(rows)) return rows;
|
|
495
|
+
}
|
|
496
|
+
throw new Error(
|
|
497
|
+
`${this.constructor.name} execute() must return an array of rows or an object holding one at ${paths.map((path7) => `result.${path7}`).join(", ")}.`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
455
500
|
/**
|
|
456
501
|
* Convert unknown database value to number.
|
|
457
502
|
* Handles number, bigint, and string types.
|
|
@@ -586,7 +631,7 @@ import {
|
|
|
586
631
|
} from "ai";
|
|
587
632
|
import dedent from "dedent";
|
|
588
633
|
import pRetry from "p-retry";
|
|
589
|
-
import
|
|
634
|
+
import z2 from "zod";
|
|
590
635
|
import "@deepagents/agent";
|
|
591
636
|
import {
|
|
592
637
|
ContextEngine,
|
|
@@ -878,14 +923,14 @@ Question: ${options.input}
|
|
|
878
923
|
const sqlOutput = structuredOutput({
|
|
879
924
|
model,
|
|
880
925
|
context,
|
|
881
|
-
schema:
|
|
882
|
-
result:
|
|
883
|
-
|
|
884
|
-
sql:
|
|
885
|
-
reasoning:
|
|
926
|
+
schema: z2.object({
|
|
927
|
+
result: z2.union([
|
|
928
|
+
z2.object({
|
|
929
|
+
sql: z2.string().describe("The SQL query that answers the question"),
|
|
930
|
+
reasoning: z2.string().describe("The reasoning steps taken to generate the SQL")
|
|
886
931
|
}),
|
|
887
|
-
|
|
888
|
-
error:
|
|
932
|
+
z2.object({
|
|
933
|
+
error: z2.string().describe(
|
|
889
934
|
"Error message explaining why the question cannot be answered with the given schema"
|
|
890
935
|
)
|
|
891
936
|
})
|
|
@@ -936,11 +981,11 @@ Question: ${options.input}
|
|
|
936
981
|
const forcedSqlOutput = structuredOutput({
|
|
937
982
|
model,
|
|
938
983
|
context,
|
|
939
|
-
schema:
|
|
940
|
-
sql:
|
|
984
|
+
schema: z2.object({
|
|
985
|
+
sql: z2.string().describe(
|
|
941
986
|
"Best-effort SQL query that answers the core intent using only available schema entities."
|
|
942
987
|
),
|
|
943
|
-
reasoning:
|
|
988
|
+
reasoning: z2.string().describe("Reasoning steps for best-effort schema mapping.")
|
|
944
989
|
})
|
|
945
990
|
});
|
|
946
991
|
try {
|
|
@@ -1025,17 +1070,17 @@ async function withRetry(computation, options = { retries: 3 }) {
|
|
|
1025
1070
|
// packages/text2sql/src/lib/agents/suggestions.agents.ts
|
|
1026
1071
|
import { groq as groq2 } from "@ai-sdk/groq";
|
|
1027
1072
|
import dedent2 from "dedent";
|
|
1028
|
-
import
|
|
1073
|
+
import z3 from "zod";
|
|
1029
1074
|
import { agent, thirdPersonPrompt } from "@deepagents/agent";
|
|
1030
1075
|
var suggestionsAgent = agent({
|
|
1031
1076
|
name: "text2sql-suggestions",
|
|
1032
1077
|
model: groq2("openai/gpt-oss-20b"),
|
|
1033
|
-
output:
|
|
1034
|
-
suggestions:
|
|
1035
|
-
|
|
1036
|
-
question:
|
|
1037
|
-
sql:
|
|
1038
|
-
businessValue:
|
|
1078
|
+
output: z3.object({
|
|
1079
|
+
suggestions: z3.array(
|
|
1080
|
+
z3.object({
|
|
1081
|
+
question: z3.string().describe("A complex, high-impact business question."),
|
|
1082
|
+
sql: z3.string().describe("The SQL statement needed to answer the question."),
|
|
1083
|
+
businessValue: z3.string().describe("Why the question matters to stakeholders.")
|
|
1039
1084
|
})
|
|
1040
1085
|
).min(1).max(5).describe("A set of up to two advanced question + SQL pairs.")
|
|
1041
1086
|
}),
|
|
@@ -1077,6 +1122,12 @@ var suggestionsAgent = agent({
|
|
|
1077
1122
|
// packages/text2sql/src/lib/adapter-index.ts
|
|
1078
1123
|
import { fragment as fragment2 } from "@deepagents/context";
|
|
1079
1124
|
|
|
1125
|
+
// packages/text2sql/src/lib/index-cache.ts
|
|
1126
|
+
import {
|
|
1127
|
+
isFragment,
|
|
1128
|
+
isFragmentData
|
|
1129
|
+
} from "@deepagents/context";
|
|
1130
|
+
|
|
1080
1131
|
// packages/text2sql/src/lib/file-cache.ts
|
|
1081
1132
|
import { createHash, randomUUID } from "node:crypto";
|
|
1082
1133
|
import { existsSync } from "node:fs";
|
|
@@ -1103,8 +1154,14 @@ var FileCache = class {
|
|
|
1103
1154
|
}
|
|
1104
1155
|
};
|
|
1105
1156
|
var JsonCache = class extends FileCache {
|
|
1106
|
-
|
|
1157
|
+
#isValid;
|
|
1158
|
+
/**
|
|
1159
|
+
* @param isValid - Checks that a parsed cache file holds a T; a file that
|
|
1160
|
+
* fails it is read as a miss.
|
|
1161
|
+
*/
|
|
1162
|
+
constructor(watermark, isValid, baseDir) {
|
|
1107
1163
|
super(watermark, ".json", baseDir);
|
|
1164
|
+
this.#isValid = isValid;
|
|
1108
1165
|
}
|
|
1109
1166
|
async read() {
|
|
1110
1167
|
const content = await this.get();
|
|
@@ -1112,7 +1169,8 @@ var JsonCache = class extends FileCache {
|
|
|
1112
1169
|
return null;
|
|
1113
1170
|
}
|
|
1114
1171
|
try {
|
|
1115
|
-
|
|
1172
|
+
const value = JSON.parse(content);
|
|
1173
|
+
return this.#isValid(value) ? value : null;
|
|
1116
1174
|
} catch {
|
|
1117
1175
|
return null;
|
|
1118
1176
|
}
|
|
@@ -1138,9 +1196,12 @@ var FileIndexCache = class {
|
|
|
1138
1196
|
}
|
|
1139
1197
|
#cacheFor(key) {
|
|
1140
1198
|
const watermark = this.#namespace ? `${this.#namespace}-${key}` : key;
|
|
1141
|
-
return new JsonCache(watermark, this.#dir);
|
|
1199
|
+
return new JsonCache(watermark, isFragmentList, this.#dir);
|
|
1142
1200
|
}
|
|
1143
1201
|
};
|
|
1202
|
+
function isFragmentList(value) {
|
|
1203
|
+
return Array.isArray(value) && value.every((item) => isFragment(item) && isFragmentData(item));
|
|
1204
|
+
}
|
|
1144
1205
|
|
|
1145
1206
|
// packages/text2sql/src/lib/index-lock.ts
|
|
1146
1207
|
import { createHash as createHash2 } from "node:crypto";
|
|
@@ -1371,6 +1432,20 @@ function errorMessage(error) {
|
|
|
1371
1432
|
import { createHash as createHash3 } from "node:crypto";
|
|
1372
1433
|
import { existsSync as existsSync2, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1373
1434
|
import pLimit from "p-limit";
|
|
1435
|
+
import z4 from "zod";
|
|
1436
|
+
function jsonCodec(schema) {
|
|
1437
|
+
return { encode: (value) => value, decode: (stored) => schema.parse(stored) };
|
|
1438
|
+
}
|
|
1439
|
+
var pointData = z4.object({
|
|
1440
|
+
committed: z4.boolean(),
|
|
1441
|
+
entries: z4.array(
|
|
1442
|
+
z4.object({ inputHash: z4.string(), output: z4.unknown().optional() })
|
|
1443
|
+
)
|
|
1444
|
+
});
|
|
1445
|
+
var checkpointFile = z4.object({
|
|
1446
|
+
configHash: z4.string().optional(),
|
|
1447
|
+
points: z4.record(z4.string(), pointData)
|
|
1448
|
+
});
|
|
1374
1449
|
var Checkpoint = class _Checkpoint {
|
|
1375
1450
|
points;
|
|
1376
1451
|
path;
|
|
@@ -1389,12 +1464,12 @@ var Checkpoint = class _Checkpoint {
|
|
|
1389
1464
|
if (existsSync2(path7)) {
|
|
1390
1465
|
try {
|
|
1391
1466
|
const content = readFileSync(path7, "utf-8");
|
|
1392
|
-
const file = JSON.parse(content);
|
|
1467
|
+
const file = checkpointFile.parse(JSON.parse(content));
|
|
1393
1468
|
if (configHash && file.configHash && file.configHash !== configHash) {
|
|
1394
1469
|
console.log("\u26A0 Config changed, starting fresh");
|
|
1395
1470
|
return new _Checkpoint(path7, configHash, {});
|
|
1396
1471
|
}
|
|
1397
|
-
const points = file.points
|
|
1472
|
+
const points = file.points;
|
|
1398
1473
|
const totalEntries = Object.values(points).reduce(
|
|
1399
1474
|
(sum, p) => sum + p.entries.length,
|
|
1400
1475
|
0
|
|
@@ -1415,27 +1490,20 @@ var Checkpoint = class _Checkpoint {
|
|
|
1415
1490
|
*
|
|
1416
1491
|
* @param key - Unique identifier for this computation
|
|
1417
1492
|
* @param computation - Async function that produces the value
|
|
1418
|
-
* @param codec -
|
|
1493
|
+
* @param codec - Codec that stores the value and restores it on resume
|
|
1419
1494
|
*/
|
|
1420
1495
|
async run(key, computation, codec) {
|
|
1421
|
-
|
|
1422
|
-
return point.through(
|
|
1423
|
-
"single",
|
|
1424
|
-
async () => {
|
|
1425
|
-
const result = await computation();
|
|
1426
|
-
return codec ? codec.encode(result) : result;
|
|
1427
|
-
},
|
|
1428
|
-
codec
|
|
1429
|
-
);
|
|
1496
|
+
return this.point(key, codec).through("single", computation);
|
|
1430
1497
|
}
|
|
1431
1498
|
/**
|
|
1432
1499
|
* Create a resumable checkpoint point for iterative operations.
|
|
1433
1500
|
*
|
|
1434
1501
|
* @param step - Unique identifier for this checkpoint point
|
|
1502
|
+
* @param codec - Codec that stores each output and restores it on resume
|
|
1435
1503
|
*/
|
|
1436
|
-
point(step) {
|
|
1504
|
+
point(step, codec) {
|
|
1437
1505
|
this.points[step] ??= { committed: false, entries: [] };
|
|
1438
|
-
return new Point(this.points[step], () => this.save());
|
|
1506
|
+
return new Point(this.points[step], codec, () => this.save());
|
|
1439
1507
|
}
|
|
1440
1508
|
/**
|
|
1441
1509
|
* Process each input with automatic checkpointing and concurrency.
|
|
@@ -1443,11 +1511,12 @@ var Checkpoint = class _Checkpoint {
|
|
|
1443
1511
|
* @param step - Unique identifier for this checkpoint
|
|
1444
1512
|
* @param inputs - Items to process
|
|
1445
1513
|
* @param process - Function to process each input
|
|
1514
|
+
* @param codec - Codec that stores each output and restores it on resume
|
|
1446
1515
|
* @param options - Optional settings like concurrency
|
|
1447
1516
|
* @returns All outputs (use `.flat()` if outputs are arrays)
|
|
1448
1517
|
*/
|
|
1449
|
-
async each(step, inputs, process, options) {
|
|
1450
|
-
const point = this.point(step);
|
|
1518
|
+
async each(step, inputs, process, codec, options) {
|
|
1519
|
+
const point = this.point(step, codec);
|
|
1451
1520
|
const limit = pLimit(options?.concurrency ?? 1);
|
|
1452
1521
|
const inputArray = Array.from(inputs);
|
|
1453
1522
|
await Promise.all(
|
|
@@ -1464,11 +1533,11 @@ var Checkpoint = class _Checkpoint {
|
|
|
1464
1533
|
*/
|
|
1465
1534
|
getOutput() {
|
|
1466
1535
|
const output = {};
|
|
1467
|
-
for (const [key,
|
|
1468
|
-
if (
|
|
1469
|
-
output[key] =
|
|
1536
|
+
for (const [key, pointData2] of Object.entries(this.points)) {
|
|
1537
|
+
if (pointData2.entries.length === 1) {
|
|
1538
|
+
output[key] = pointData2.entries[0].output;
|
|
1470
1539
|
} else {
|
|
1471
|
-
output[key] =
|
|
1540
|
+
output[key] = pointData2.entries.map((e) => e.output);
|
|
1472
1541
|
}
|
|
1473
1542
|
}
|
|
1474
1543
|
return output;
|
|
@@ -1492,31 +1561,32 @@ function hash(value) {
|
|
|
1492
1561
|
return createHash3("md5").update(JSON.stringify(value)).digest("hex");
|
|
1493
1562
|
}
|
|
1494
1563
|
var Point = class {
|
|
1495
|
-
#
|
|
1564
|
+
#stored;
|
|
1496
1565
|
data;
|
|
1566
|
+
codec;
|
|
1497
1567
|
persist;
|
|
1498
|
-
constructor(data, persist) {
|
|
1499
|
-
this.#
|
|
1500
|
-
data.entries.map((e) => [e.inputHash, e.output])
|
|
1501
|
-
);
|
|
1568
|
+
constructor(data, codec, persist) {
|
|
1569
|
+
this.#stored = new Map(data.entries.map((e) => [e.inputHash, e.output]));
|
|
1502
1570
|
this.data = data;
|
|
1571
|
+
this.codec = codec;
|
|
1503
1572
|
this.persist = persist;
|
|
1504
1573
|
}
|
|
1505
1574
|
/**
|
|
1506
1575
|
* Execute computation if input wasn't processed before.
|
|
1507
|
-
* Returns
|
|
1576
|
+
* Returns the decoded stored output if input hash exists, otherwise
|
|
1577
|
+
* executes, saves the encoded output, and returns the computed value.
|
|
1508
1578
|
*/
|
|
1509
|
-
async through(input, compute
|
|
1579
|
+
async through(input, compute) {
|
|
1510
1580
|
const inputHash = hash(input);
|
|
1511
|
-
if (this.#
|
|
1512
|
-
|
|
1513
|
-
return codec ? codec.decode(cached) : cached;
|
|
1581
|
+
if (this.#stored.has(inputHash)) {
|
|
1582
|
+
return this.codec.decode(this.#stored.get(inputHash));
|
|
1514
1583
|
}
|
|
1515
|
-
const
|
|
1584
|
+
const value = await compute();
|
|
1585
|
+
const output = this.codec.encode(value);
|
|
1516
1586
|
this.data.entries.push({ inputHash, output });
|
|
1517
|
-
this.#
|
|
1587
|
+
this.#stored.set(inputHash, output);
|
|
1518
1588
|
await this.persist();
|
|
1519
|
-
return
|
|
1589
|
+
return value;
|
|
1520
1590
|
}
|
|
1521
1591
|
/** Mark this point as complete. */
|
|
1522
1592
|
async commit() {
|
|
@@ -1529,7 +1599,7 @@ var Point = class {
|
|
|
1529
1599
|
}
|
|
1530
1600
|
/** Get all outputs from this point. */
|
|
1531
1601
|
values() {
|
|
1532
|
-
return this.data.entries.map((e) => e.output);
|
|
1602
|
+
return this.data.entries.map((e) => this.codec.decode(e.output));
|
|
1533
1603
|
}
|
|
1534
1604
|
};
|
|
1535
1605
|
function hashConfig(config) {
|
|
@@ -1539,11 +1609,40 @@ function hashConfig(config) {
|
|
|
1539
1609
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1540
1610
|
import * as path3 from "node:path";
|
|
1541
1611
|
import { DatabaseSync } from "node:sqlite";
|
|
1612
|
+
import z6 from "zod";
|
|
1613
|
+
|
|
1614
|
+
// packages/text2sql/src/lib/fs/columns.ts
|
|
1615
|
+
import z5 from "zod";
|
|
1616
|
+
var entryType = z5.enum(["file", "directory", "symlink"]);
|
|
1617
|
+
var bigintColumn = z5.union([z5.number(), z5.string().regex(/^-?\d+$/)]).transform(Number);
|
|
1542
1618
|
|
|
1543
1619
|
// packages/text2sql/src/lib/fs/sqlite/ddl.sqlite-fs.sql
|
|
1544
1620
|
var ddl_sqlite_fs_default = "-- SQLite-based filesystem schema for artifact storage\n-- Tables: fs_entries (file/directory metadata), fs_chunks (file content)\n\n-- Performance PRAGMAs (session-level, run on each connection)\nPRAGMA journal_mode = WAL;\nPRAGMA synchronous = NORMAL;\nPRAGMA cache_size = -64000;\nPRAGMA temp_store = MEMORY;\nPRAGMA mmap_size = 268435456;\n\n-- Integrity\nPRAGMA foreign_keys = ON;\n\n-- Filesystem entries table (files, directories, symlinks)\nCREATE TABLE IF NOT EXISTS fs_entries (\n path TEXT PRIMARY KEY, -- Normalized absolute path (e.g., '/results/uuid.json')\n type TEXT NOT NULL, -- 'file' | 'directory' | 'symlink'\n mode INTEGER NOT NULL, -- Unix permissions (e.g., 0o644 = 420)\n size INTEGER NOT NULL, -- File size in bytes (0 for directories)\n mtime INTEGER NOT NULL, -- Modified time (milliseconds since epoch)\n symlinkTarget TEXT -- Target path for symlinks (NULL for files/dirs)\n);\n\nCREATE INDEX IF NOT EXISTS idx_fs_entries_type ON fs_entries(type);\n\n-- File content chunks table (for handling large files)\n-- Files are split into 1MB chunks to avoid SQLite BLOB performance issues\nCREATE TABLE IF NOT EXISTS fs_chunks (\n path TEXT NOT NULL, -- Reference to fs_entries.path\n chunkIndex INTEGER NOT NULL, -- 0-based chunk sequence\n data BLOB NOT NULL, -- Chunk content (up to 1MB default)\n PRIMARY KEY (path, chunkIndex),\n FOREIGN KEY (path) REFERENCES fs_entries(path) ON DELETE CASCADE ON UPDATE CASCADE\n);\n";
|
|
1545
1621
|
|
|
1546
1622
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1623
|
+
var entryRow = z6.object({
|
|
1624
|
+
path: z6.string(),
|
|
1625
|
+
type: entryType,
|
|
1626
|
+
mode: z6.number(),
|
|
1627
|
+
size: z6.number(),
|
|
1628
|
+
mtime: z6.number(),
|
|
1629
|
+
symlinkTarget: z6.string().nullable()
|
|
1630
|
+
});
|
|
1631
|
+
var typeRow = entryRow.pick({ type: true });
|
|
1632
|
+
var pathRow = entryRow.pick({ path: true });
|
|
1633
|
+
var pathTypeRow = entryRow.pick({ path: true, type: true });
|
|
1634
|
+
var linkRow = z6.discriminatedUnion("type", [
|
|
1635
|
+
z6.object({ type: z6.literal("symlink"), symlinkTarget: z6.string() }),
|
|
1636
|
+
z6.object({
|
|
1637
|
+
type: z6.enum(["file", "directory"]),
|
|
1638
|
+
symlinkTarget: z6.string().nullable()
|
|
1639
|
+
})
|
|
1640
|
+
]);
|
|
1641
|
+
var chunkRow = z6.object({
|
|
1642
|
+
chunkIndex: z6.number(),
|
|
1643
|
+
data: z6.instanceof(Uint8Array)
|
|
1644
|
+
});
|
|
1645
|
+
var dataRow = chunkRow.pick({ data: true });
|
|
1547
1646
|
var SqliteFs = class {
|
|
1548
1647
|
#db;
|
|
1549
1648
|
#statements = /* @__PURE__ */ new Map();
|
|
@@ -1651,8 +1750,8 @@ var SqliteFs = class {
|
|
|
1651
1750
|
const parent = this.#dirname(filePath);
|
|
1652
1751
|
const rootPath = this.#root || "/";
|
|
1653
1752
|
if (parent === rootPath || parent === "/") return;
|
|
1654
|
-
const entry =
|
|
1655
|
-
parent
|
|
1753
|
+
const entry = typeRow.optional().parse(
|
|
1754
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(parent)
|
|
1656
1755
|
);
|
|
1657
1756
|
if (!entry) {
|
|
1658
1757
|
this.#ensureParentExists(parent);
|
|
@@ -1676,10 +1775,19 @@ var SqliteFs = class {
|
|
|
1676
1775
|
).run(filePath, Math.floor(i / this.#chunkSize), chunk);
|
|
1677
1776
|
}
|
|
1678
1777
|
}
|
|
1778
|
+
#chunks(filePath) {
|
|
1779
|
+
return z6.array(chunkRow).parse(
|
|
1780
|
+
this.#stmt("SELECT chunkIndex, data FROM fs_chunks WHERE path = ?").all(
|
|
1781
|
+
filePath
|
|
1782
|
+
)
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1679
1785
|
#readChunks(filePath) {
|
|
1680
|
-
const rows =
|
|
1681
|
-
|
|
1682
|
-
|
|
1786
|
+
const rows = z6.array(dataRow).parse(
|
|
1787
|
+
this.#stmt(
|
|
1788
|
+
"SELECT data FROM fs_chunks WHERE path = ? ORDER BY chunkIndex"
|
|
1789
|
+
).all(filePath)
|
|
1790
|
+
);
|
|
1683
1791
|
if (rows.length === 0) {
|
|
1684
1792
|
return new Uint8Array(0);
|
|
1685
1793
|
}
|
|
@@ -1696,9 +1804,11 @@ var SqliteFs = class {
|
|
|
1696
1804
|
if (seen.has(p)) {
|
|
1697
1805
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
1698
1806
|
}
|
|
1699
|
-
const entry =
|
|
1700
|
-
|
|
1701
|
-
|
|
1807
|
+
const entry = linkRow.optional().parse(
|
|
1808
|
+
this.#stmt(
|
|
1809
|
+
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
1810
|
+
).get(p)
|
|
1811
|
+
);
|
|
1702
1812
|
if (!entry) {
|
|
1703
1813
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
1704
1814
|
}
|
|
@@ -1715,8 +1825,7 @@ var SqliteFs = class {
|
|
|
1715
1825
|
if (content instanceof Uint8Array) {
|
|
1716
1826
|
return content;
|
|
1717
1827
|
}
|
|
1718
|
-
|
|
1719
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
1828
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
1720
1829
|
}
|
|
1721
1830
|
// ============================================================================
|
|
1722
1831
|
// IFileSystem Implementation
|
|
@@ -1725,8 +1834,8 @@ var SqliteFs = class {
|
|
|
1725
1834
|
const normalized = this.#normalizePath(filePath);
|
|
1726
1835
|
const prefixed = this.#prefixPath(normalized);
|
|
1727
1836
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1728
|
-
const entry =
|
|
1729
|
-
resolved
|
|
1837
|
+
const entry = typeRow.optional().parse(
|
|
1838
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1730
1839
|
);
|
|
1731
1840
|
if (!entry) {
|
|
1732
1841
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1742,8 +1851,8 @@ var SqliteFs = class {
|
|
|
1742
1851
|
const normalized = this.#normalizePath(filePath);
|
|
1743
1852
|
const prefixed = this.#prefixPath(normalized);
|
|
1744
1853
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1745
|
-
const entry =
|
|
1746
|
-
resolved
|
|
1854
|
+
const entry = typeRow.optional().parse(
|
|
1855
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1747
1856
|
);
|
|
1748
1857
|
if (!entry) {
|
|
1749
1858
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1778,9 +1887,11 @@ var SqliteFs = class {
|
|
|
1778
1887
|
const newData = this.#toUint8Array(content, encoding);
|
|
1779
1888
|
this.#useTransaction(() => {
|
|
1780
1889
|
this.#ensureParentExists(prefixed);
|
|
1781
|
-
const entry =
|
|
1782
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1783
|
-
|
|
1890
|
+
const entry = typeRow.optional().parse(
|
|
1891
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1892
|
+
prefixed
|
|
1893
|
+
)
|
|
1894
|
+
);
|
|
1784
1895
|
if (entry && entry.type !== "file") {
|
|
1785
1896
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
1786
1897
|
}
|
|
@@ -1810,8 +1921,8 @@ var SqliteFs = class {
|
|
|
1810
1921
|
const normalized = this.#normalizePath(filePath);
|
|
1811
1922
|
const prefixed = this.#prefixPath(normalized);
|
|
1812
1923
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1813
|
-
const entry =
|
|
1814
|
-
resolved
|
|
1924
|
+
const entry = entryRow.optional().parse(
|
|
1925
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(resolved)
|
|
1815
1926
|
);
|
|
1816
1927
|
if (!entry) {
|
|
1817
1928
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1829,8 +1940,8 @@ var SqliteFs = class {
|
|
|
1829
1940
|
async lstat(filePath) {
|
|
1830
1941
|
const normalized = this.#normalizePath(filePath);
|
|
1831
1942
|
const prefixed = this.#prefixPath(normalized);
|
|
1832
|
-
const entry =
|
|
1833
|
-
prefixed
|
|
1943
|
+
const entry = entryRow.optional().parse(
|
|
1944
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1834
1945
|
);
|
|
1835
1946
|
if (!entry) {
|
|
1836
1947
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1847,9 +1958,9 @@ var SqliteFs = class {
|
|
|
1847
1958
|
async mkdir(dirPath, options) {
|
|
1848
1959
|
const normalized = this.#normalizePath(dirPath);
|
|
1849
1960
|
const prefixed = this.#prefixPath(normalized);
|
|
1850
|
-
const existing =
|
|
1851
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1852
|
-
)
|
|
1961
|
+
const existing = typeRow.optional().parse(
|
|
1962
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1963
|
+
);
|
|
1853
1964
|
if (existing) {
|
|
1854
1965
|
if (options?.recursive) {
|
|
1855
1966
|
return;
|
|
@@ -1864,9 +1975,11 @@ var SqliteFs = class {
|
|
|
1864
1975
|
let currentPath = rootPath;
|
|
1865
1976
|
for (const segment of segments) {
|
|
1866
1977
|
currentPath = path3.posix.join(currentPath, segment);
|
|
1867
|
-
const exists =
|
|
1868
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1869
|
-
|
|
1978
|
+
const exists = typeRow.optional().parse(
|
|
1979
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1980
|
+
currentPath
|
|
1981
|
+
)
|
|
1982
|
+
);
|
|
1870
1983
|
if (!exists) {
|
|
1871
1984
|
this.#stmt(
|
|
1872
1985
|
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
@@ -1878,9 +1991,11 @@ var SqliteFs = class {
|
|
|
1878
1991
|
}
|
|
1879
1992
|
} else {
|
|
1880
1993
|
const parent = this.#dirname(prefixed);
|
|
1881
|
-
const parentEntry =
|
|
1882
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1883
|
-
|
|
1994
|
+
const parentEntry = typeRow.optional().parse(
|
|
1995
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1996
|
+
parent
|
|
1997
|
+
)
|
|
1998
|
+
);
|
|
1884
1999
|
if (!parentEntry) {
|
|
1885
2000
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
1886
2001
|
}
|
|
@@ -1898,8 +2013,8 @@ var SqliteFs = class {
|
|
|
1898
2013
|
const normalized = this.#normalizePath(dirPath);
|
|
1899
2014
|
const prefixed = this.#prefixPath(normalized);
|
|
1900
2015
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1901
|
-
const entry =
|
|
1902
|
-
resolved
|
|
2016
|
+
const entry = typeRow.optional().parse(
|
|
2017
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1903
2018
|
);
|
|
1904
2019
|
if (!entry) {
|
|
1905
2020
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1908,20 +2023,22 @@ var SqliteFs = class {
|
|
|
1908
2023
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
1909
2024
|
}
|
|
1910
2025
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1911
|
-
const rows =
|
|
1912
|
-
|
|
2026
|
+
const rows = z6.array(pathRow).parse(
|
|
2027
|
+
this.#stmt(
|
|
2028
|
+
`SELECT path FROM fs_entries
|
|
1913
2029
|
WHERE path LIKE ? || '%'
|
|
1914
2030
|
AND path != ?
|
|
1915
2031
|
AND path NOT LIKE ? || '%/%'`
|
|
1916
|
-
|
|
2032
|
+
).all(prefix, resolved, prefix)
|
|
2033
|
+
);
|
|
1917
2034
|
return rows.map((row) => path3.posix.basename(row.path));
|
|
1918
2035
|
}
|
|
1919
2036
|
async readdirWithFileTypes(dirPath) {
|
|
1920
2037
|
const normalized = this.#normalizePath(dirPath);
|
|
1921
2038
|
const prefixed = this.#prefixPath(normalized);
|
|
1922
2039
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1923
|
-
const entry =
|
|
1924
|
-
resolved
|
|
2040
|
+
const entry = typeRow.optional().parse(
|
|
2041
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1925
2042
|
);
|
|
1926
2043
|
if (!entry) {
|
|
1927
2044
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1930,12 +2047,14 @@ var SqliteFs = class {
|
|
|
1930
2047
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
1931
2048
|
}
|
|
1932
2049
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1933
|
-
const rows =
|
|
1934
|
-
|
|
2050
|
+
const rows = z6.array(pathTypeRow).parse(
|
|
2051
|
+
this.#stmt(
|
|
2052
|
+
`SELECT path, type FROM fs_entries
|
|
1935
2053
|
WHERE path LIKE ? || '%'
|
|
1936
2054
|
AND path != ?
|
|
1937
2055
|
AND path NOT LIKE ? || '%/%'`
|
|
1938
|
-
|
|
2056
|
+
).all(prefix, resolved, prefix)
|
|
2057
|
+
);
|
|
1939
2058
|
return rows.map((row) => ({
|
|
1940
2059
|
name: path3.posix.basename(row.path),
|
|
1941
2060
|
isFile: row.type === "file",
|
|
@@ -1946,8 +2065,8 @@ var SqliteFs = class {
|
|
|
1946
2065
|
async rm(filePath, options) {
|
|
1947
2066
|
const normalized = this.#normalizePath(filePath);
|
|
1948
2067
|
const prefixed = this.#prefixPath(normalized);
|
|
1949
|
-
const entry =
|
|
1950
|
-
prefixed
|
|
2068
|
+
const entry = typeRow.optional().parse(
|
|
2069
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1951
2070
|
);
|
|
1952
2071
|
if (!entry) {
|
|
1953
2072
|
if (options?.force) {
|
|
@@ -1976,8 +2095,8 @@ var SqliteFs = class {
|
|
|
1976
2095
|
const destNormalized = this.#normalizePath(dest);
|
|
1977
2096
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
1978
2097
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
1979
|
-
const srcEntry =
|
|
1980
|
-
srcPrefixed
|
|
2098
|
+
const srcEntry = entryRow.optional().parse(
|
|
2099
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
1981
2100
|
);
|
|
1982
2101
|
if (!srcEntry) {
|
|
1983
2102
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
@@ -1988,9 +2107,11 @@ var SqliteFs = class {
|
|
|
1988
2107
|
this.#useTransaction(() => {
|
|
1989
2108
|
this.#ensureParentExists(destPrefixed);
|
|
1990
2109
|
if (srcEntry.type === "directory") {
|
|
1991
|
-
const allEntries =
|
|
1992
|
-
|
|
1993
|
-
|
|
2110
|
+
const allEntries = z6.array(entryRow).parse(
|
|
2111
|
+
this.#stmt(
|
|
2112
|
+
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%'`
|
|
2113
|
+
).all(srcPrefixed, srcPrefixed)
|
|
2114
|
+
);
|
|
1994
2115
|
for (const entry of allEntries) {
|
|
1995
2116
|
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
1996
2117
|
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
@@ -2006,9 +2127,7 @@ var SqliteFs = class {
|
|
|
2006
2127
|
entry.symlinkTarget
|
|
2007
2128
|
);
|
|
2008
2129
|
if (entry.type === "file") {
|
|
2009
|
-
const chunks = this.#
|
|
2010
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2011
|
-
).all(entry.path);
|
|
2130
|
+
const chunks = this.#chunks(entry.path);
|
|
2012
2131
|
for (const chunk of chunks) {
|
|
2013
2132
|
this.#stmt(
|
|
2014
2133
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2029,9 +2148,7 @@ var SqliteFs = class {
|
|
|
2029
2148
|
srcEntry.symlinkTarget
|
|
2030
2149
|
);
|
|
2031
2150
|
if (srcEntry.type === "file") {
|
|
2032
|
-
const chunks = this.#
|
|
2033
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2034
|
-
).all(srcPrefixed);
|
|
2151
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2035
2152
|
this.#stmt("DELETE FROM fs_chunks WHERE path = ?").run(destPrefixed);
|
|
2036
2153
|
for (const chunk of chunks) {
|
|
2037
2154
|
this.#stmt(
|
|
@@ -2047,8 +2164,8 @@ var SqliteFs = class {
|
|
|
2047
2164
|
const destNormalized = this.#normalizePath(dest);
|
|
2048
2165
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2049
2166
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2050
|
-
const srcEntry =
|
|
2051
|
-
srcPrefixed
|
|
2167
|
+
const srcEntry = entryRow.optional().parse(
|
|
2168
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
2052
2169
|
);
|
|
2053
2170
|
if (!srcEntry) {
|
|
2054
2171
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
@@ -2056,9 +2173,11 @@ var SqliteFs = class {
|
|
|
2056
2173
|
this.#useTransaction(() => {
|
|
2057
2174
|
this.#ensureParentExists(destPrefixed);
|
|
2058
2175
|
if (srcEntry.type === "directory") {
|
|
2059
|
-
const allEntries =
|
|
2060
|
-
|
|
2061
|
-
|
|
2176
|
+
const allEntries = z6.array(entryRow).parse(
|
|
2177
|
+
this.#stmt(
|
|
2178
|
+
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%' ORDER BY path DESC`
|
|
2179
|
+
).all(srcPrefixed, srcPrefixed)
|
|
2180
|
+
);
|
|
2062
2181
|
for (const entry of [...allEntries].reverse()) {
|
|
2063
2182
|
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2064
2183
|
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
@@ -2074,9 +2193,7 @@ var SqliteFs = class {
|
|
|
2074
2193
|
entry.symlinkTarget
|
|
2075
2194
|
);
|
|
2076
2195
|
if (entry.type === "file") {
|
|
2077
|
-
const chunks = this.#
|
|
2078
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2079
|
-
).all(entry.path);
|
|
2196
|
+
const chunks = this.#chunks(entry.path);
|
|
2080
2197
|
for (const chunk of chunks) {
|
|
2081
2198
|
this.#stmt(
|
|
2082
2199
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2100,9 +2217,7 @@ var SqliteFs = class {
|
|
|
2100
2217
|
srcEntry.symlinkTarget
|
|
2101
2218
|
);
|
|
2102
2219
|
if (srcEntry.type === "file") {
|
|
2103
|
-
const chunks = this.#
|
|
2104
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2105
|
-
).all(srcPrefixed);
|
|
2220
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2106
2221
|
for (const chunk of chunks) {
|
|
2107
2222
|
this.#stmt(
|
|
2108
2223
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2117,9 +2232,7 @@ var SqliteFs = class {
|
|
|
2117
2232
|
return path3.posix.resolve(base, relativePath);
|
|
2118
2233
|
}
|
|
2119
2234
|
getAllPaths() {
|
|
2120
|
-
const rows = this.#stmt(
|
|
2121
|
-
"SELECT path FROM fs_entries ORDER BY path"
|
|
2122
|
-
).all();
|
|
2235
|
+
const rows = z6.array(pathRow).parse(this.#stmt("SELECT path FROM fs_entries ORDER BY path").all());
|
|
2123
2236
|
return rows.map((row) => row.path);
|
|
2124
2237
|
}
|
|
2125
2238
|
async realpath(filePath) {
|
|
@@ -2177,8 +2290,8 @@ var SqliteFs = class {
|
|
|
2177
2290
|
const destNormalized = this.#normalizePath(newPath);
|
|
2178
2291
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2179
2292
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2180
|
-
const srcEntry =
|
|
2181
|
-
srcPrefixed
|
|
2293
|
+
const srcEntry = entryRow.optional().parse(
|
|
2294
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
2182
2295
|
);
|
|
2183
2296
|
if (!srcEntry) {
|
|
2184
2297
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
@@ -2198,9 +2311,7 @@ var SqliteFs = class {
|
|
|
2198
2311
|
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
2199
2312
|
VALUES (?, 'file', ?, ?, ?)`
|
|
2200
2313
|
).run(destPrefixed, srcEntry.mode, srcEntry.size, Date.now());
|
|
2201
|
-
const chunks = this.#
|
|
2202
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2203
|
-
).all(srcPrefixed);
|
|
2314
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2204
2315
|
for (const chunk of chunks) {
|
|
2205
2316
|
this.#stmt(
|
|
2206
2317
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2211,9 +2322,11 @@ var SqliteFs = class {
|
|
|
2211
2322
|
async readlink(linkPath) {
|
|
2212
2323
|
const normalized = this.#normalizePath(linkPath);
|
|
2213
2324
|
const prefixed = this.#prefixPath(normalized);
|
|
2214
|
-
const entry =
|
|
2215
|
-
|
|
2216
|
-
|
|
2325
|
+
const entry = linkRow.optional().parse(
|
|
2326
|
+
this.#stmt(
|
|
2327
|
+
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
2328
|
+
).get(prefixed)
|
|
2329
|
+
);
|
|
2217
2330
|
if (!entry) {
|
|
2218
2331
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
2219
2332
|
}
|
|
@@ -2227,6 +2340,7 @@ var SqliteFs = class {
|
|
|
2227
2340
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2228
2341
|
import { createRequire } from "node:module";
|
|
2229
2342
|
import * as path4 from "node:path";
|
|
2343
|
+
import z7 from "zod";
|
|
2230
2344
|
|
|
2231
2345
|
// packages/text2sql/src/lib/fs/mssql/ddl.mssql-fs.ts
|
|
2232
2346
|
function mssqlFsDDL(schema) {
|
|
@@ -2259,6 +2373,33 @@ GO
|
|
|
2259
2373
|
}
|
|
2260
2374
|
|
|
2261
2375
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2376
|
+
var entryRow2 = z7.object({
|
|
2377
|
+
path: z7.string(),
|
|
2378
|
+
type: entryType,
|
|
2379
|
+
mode: z7.number(),
|
|
2380
|
+
size: bigintColumn,
|
|
2381
|
+
mtime: bigintColumn,
|
|
2382
|
+
symlinkTarget: z7.string().nullable()
|
|
2383
|
+
});
|
|
2384
|
+
var typeRow2 = entryRow2.pick({ type: true });
|
|
2385
|
+
var pathRow2 = entryRow2.pick({ path: true });
|
|
2386
|
+
var pathTypeRow2 = entryRow2.pick({ path: true, type: true });
|
|
2387
|
+
var linkRow2 = z7.discriminatedUnion("type", [
|
|
2388
|
+
z7.object({ type: z7.literal("symlink"), symlinkTarget: z7.string() }),
|
|
2389
|
+
z7.object({
|
|
2390
|
+
type: z7.enum(["file", "directory"]),
|
|
2391
|
+
symlinkTarget: z7.string().nullable()
|
|
2392
|
+
})
|
|
2393
|
+
]);
|
|
2394
|
+
var existsRow = z7.object({ exists: z7.union([z7.literal(0), z7.literal(1)]) });
|
|
2395
|
+
var chunkRow2 = z7.object({
|
|
2396
|
+
chunkIndex: z7.number(),
|
|
2397
|
+
data: z7.instanceof(Buffer)
|
|
2398
|
+
});
|
|
2399
|
+
var dataRow2 = chunkRow2.pick({ data: true });
|
|
2400
|
+
function rowsOf(row, result) {
|
|
2401
|
+
return z7.array(row).parse(result.recordset);
|
|
2402
|
+
}
|
|
2262
2403
|
var MssqlFs = class _MssqlFs {
|
|
2263
2404
|
#pool;
|
|
2264
2405
|
#chunkSize;
|
|
@@ -2317,8 +2458,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2317
2458
|
await this.#pool.request().batch(batch);
|
|
2318
2459
|
}
|
|
2319
2460
|
}
|
|
2320
|
-
const rootSlashExists =
|
|
2321
|
-
|
|
2461
|
+
const rootSlashExists = rowsOf(
|
|
2462
|
+
existsRow,
|
|
2463
|
+
await this.#rawQuery(
|
|
2464
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') THEN 1 ELSE 0 END as [exists]`
|
|
2465
|
+
)
|
|
2322
2466
|
);
|
|
2323
2467
|
if (rootSlashExists[0].exists === 0) {
|
|
2324
2468
|
await this.#rawExec(
|
|
@@ -2328,9 +2472,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2328
2472
|
}
|
|
2329
2473
|
if (this.#root) {
|
|
2330
2474
|
await this.#createParentDirs(this.#root);
|
|
2331
|
-
const rootExists =
|
|
2332
|
-
|
|
2333
|
-
|
|
2475
|
+
const rootExists = rowsOf(
|
|
2476
|
+
existsRow,
|
|
2477
|
+
await this.#rawQuery(
|
|
2478
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2479
|
+
[this.#root]
|
|
2480
|
+
)
|
|
2334
2481
|
);
|
|
2335
2482
|
if (rootExists[0].exists === 0) {
|
|
2336
2483
|
await this.#rawExec(
|
|
@@ -2353,9 +2500,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2353
2500
|
let currentPath = "/";
|
|
2354
2501
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2355
2502
|
currentPath = path4.posix.join(currentPath, segments[i]);
|
|
2356
|
-
const exists =
|
|
2357
|
-
|
|
2358
|
-
|
|
2503
|
+
const exists = rowsOf(
|
|
2504
|
+
existsRow,
|
|
2505
|
+
await this.#rawQuery(
|
|
2506
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2507
|
+
[currentPath]
|
|
2508
|
+
)
|
|
2359
2509
|
);
|
|
2360
2510
|
if (exists[0].exists === 0) {
|
|
2361
2511
|
await this.#rawExec(
|
|
@@ -2365,13 +2515,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2365
2515
|
}
|
|
2366
2516
|
}
|
|
2367
2517
|
}
|
|
2368
|
-
|
|
2518
|
+
#rawQuery(sql, params) {
|
|
2369
2519
|
const request = this.#pool.request();
|
|
2370
2520
|
params?.forEach((value, index2) => {
|
|
2371
2521
|
request.input(`p${index2}`, value);
|
|
2372
2522
|
});
|
|
2373
|
-
|
|
2374
|
-
return result.recordset;
|
|
2523
|
+
return request.query(sql);
|
|
2375
2524
|
}
|
|
2376
2525
|
async #rawExec(sql, params) {
|
|
2377
2526
|
const request = this.#pool.request();
|
|
@@ -2440,10 +2589,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2440
2589
|
if (parent === rootPath || parent === "/") return;
|
|
2441
2590
|
const request = transaction.request();
|
|
2442
2591
|
request.input("p0", parent);
|
|
2443
|
-
const
|
|
2444
|
-
|
|
2592
|
+
const [entry] = rowsOf(
|
|
2593
|
+
typeRow2,
|
|
2594
|
+
await request.query(
|
|
2595
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2596
|
+
)
|
|
2445
2597
|
);
|
|
2446
|
-
const entry = result.recordset[0];
|
|
2447
2598
|
if (!entry) {
|
|
2448
2599
|
await this.#ensureParentExists(parent, transaction);
|
|
2449
2600
|
const insertReq = transaction.request();
|
|
@@ -2477,20 +2628,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2477
2628
|
}
|
|
2478
2629
|
}
|
|
2479
2630
|
async #readChunks(filePath, transaction) {
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
`SELECT data FROM ${this.#t("fs_chunks")} WHERE path = @p0 ORDER BY chunkIndex`
|
|
2486
|
-
);
|
|
2487
|
-
rows = result2.recordset;
|
|
2488
|
-
} else {
|
|
2489
|
-
rows = await this.#query(
|
|
2490
|
-
`SELECT data FROM ${this.#t("fs_chunks")} WHERE path = @p0 ORDER BY chunkIndex`,
|
|
2491
|
-
[filePath]
|
|
2492
|
-
);
|
|
2493
|
-
}
|
|
2631
|
+
const sql = `SELECT data FROM ${this.#t("fs_chunks")} WHERE path = @p0 ORDER BY chunkIndex`;
|
|
2632
|
+
const rows = rowsOf(
|
|
2633
|
+
dataRow2,
|
|
2634
|
+
transaction ? await transaction.request().input("p0", filePath).query(sql) : await this.#query(sql, [filePath])
|
|
2635
|
+
);
|
|
2494
2636
|
if (rows.length === 0) {
|
|
2495
2637
|
return new Uint8Array(0);
|
|
2496
2638
|
}
|
|
@@ -2507,11 +2649,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2507
2649
|
if (seen.has(p)) {
|
|
2508
2650
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
2509
2651
|
}
|
|
2510
|
-
const
|
|
2511
|
-
|
|
2512
|
-
|
|
2652
|
+
const [entry] = rowsOf(
|
|
2653
|
+
linkRow2,
|
|
2654
|
+
await this.#query(
|
|
2655
|
+
`SELECT type, symlinkTarget FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2656
|
+
[p]
|
|
2657
|
+
)
|
|
2513
2658
|
);
|
|
2514
|
-
const entry = rows[0];
|
|
2515
2659
|
if (!entry) {
|
|
2516
2660
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
2517
2661
|
}
|
|
@@ -2528,8 +2672,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2528
2672
|
if (content instanceof Uint8Array) {
|
|
2529
2673
|
return content;
|
|
2530
2674
|
}
|
|
2531
|
-
|
|
2532
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
2675
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
2533
2676
|
}
|
|
2534
2677
|
async close() {
|
|
2535
2678
|
if (this.#ownsPool) {
|
|
@@ -2543,11 +2686,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2543
2686
|
const normalized = this.#normalizePath(filePath);
|
|
2544
2687
|
const prefixed = this.#prefixPath(normalized);
|
|
2545
2688
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2546
|
-
const
|
|
2547
|
-
|
|
2548
|
-
|
|
2689
|
+
const [entry] = rowsOf(
|
|
2690
|
+
typeRow2,
|
|
2691
|
+
await this.#query(
|
|
2692
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2693
|
+
[resolved]
|
|
2694
|
+
)
|
|
2549
2695
|
);
|
|
2550
|
-
const entry = rows[0];
|
|
2551
2696
|
if (!entry) {
|
|
2552
2697
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2553
2698
|
}
|
|
@@ -2562,11 +2707,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2562
2707
|
const normalized = this.#normalizePath(filePath);
|
|
2563
2708
|
const prefixed = this.#prefixPath(normalized);
|
|
2564
2709
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2565
|
-
const
|
|
2566
|
-
|
|
2567
|
-
|
|
2710
|
+
const [entry] = rowsOf(
|
|
2711
|
+
typeRow2,
|
|
2712
|
+
await this.#query(
|
|
2713
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2714
|
+
[resolved]
|
|
2715
|
+
)
|
|
2568
2716
|
);
|
|
2569
|
-
const entry = rows[0];
|
|
2570
2717
|
if (!entry) {
|
|
2571
2718
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2572
2719
|
}
|
|
@@ -2608,10 +2755,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2608
2755
|
await this.#ensureParentExists(prefixed, transaction);
|
|
2609
2756
|
const checkReq = transaction.request();
|
|
2610
2757
|
checkReq.input("p0", prefixed);
|
|
2611
|
-
const
|
|
2612
|
-
|
|
2758
|
+
const [entry] = rowsOf(
|
|
2759
|
+
typeRow2,
|
|
2760
|
+
await checkReq.query(
|
|
2761
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2762
|
+
)
|
|
2613
2763
|
);
|
|
2614
|
-
const entry = result.recordset[0];
|
|
2615
2764
|
if (entry && entry.type !== "file") {
|
|
2616
2765
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
2617
2766
|
}
|
|
@@ -2639,9 +2788,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2639
2788
|
async exists(filePath) {
|
|
2640
2789
|
const normalized = this.#normalizePath(filePath);
|
|
2641
2790
|
const prefixed = this.#prefixPath(normalized);
|
|
2642
|
-
const rows =
|
|
2643
|
-
|
|
2644
|
-
|
|
2791
|
+
const rows = rowsOf(
|
|
2792
|
+
existsRow,
|
|
2793
|
+
await this.#query(
|
|
2794
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2795
|
+
[prefixed]
|
|
2796
|
+
)
|
|
2645
2797
|
);
|
|
2646
2798
|
return rows[0].exists === 1;
|
|
2647
2799
|
}
|
|
@@ -2649,11 +2801,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2649
2801
|
const normalized = this.#normalizePath(filePath);
|
|
2650
2802
|
const prefixed = this.#prefixPath(normalized);
|
|
2651
2803
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2652
|
-
const
|
|
2653
|
-
|
|
2654
|
-
|
|
2804
|
+
const [entry] = rowsOf(
|
|
2805
|
+
entryRow2,
|
|
2806
|
+
await this.#query(
|
|
2807
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2808
|
+
[resolved]
|
|
2809
|
+
)
|
|
2655
2810
|
);
|
|
2656
|
-
const entry = rows[0];
|
|
2657
2811
|
if (!entry) {
|
|
2658
2812
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2659
2813
|
}
|
|
@@ -2661,19 +2815,21 @@ var MssqlFs = class _MssqlFs {
|
|
|
2661
2815
|
isFile: entry.type === "file",
|
|
2662
2816
|
isDirectory: entry.type === "directory",
|
|
2663
2817
|
isSymbolicLink: false,
|
|
2664
|
-
mode:
|
|
2665
|
-
size:
|
|
2666
|
-
mtime: new Date(
|
|
2818
|
+
mode: entry.mode,
|
|
2819
|
+
size: entry.size,
|
|
2820
|
+
mtime: new Date(entry.mtime)
|
|
2667
2821
|
};
|
|
2668
2822
|
}
|
|
2669
2823
|
async lstat(filePath) {
|
|
2670
2824
|
const normalized = this.#normalizePath(filePath);
|
|
2671
2825
|
const prefixed = this.#prefixPath(normalized);
|
|
2672
|
-
const
|
|
2673
|
-
|
|
2674
|
-
|
|
2826
|
+
const [entry] = rowsOf(
|
|
2827
|
+
entryRow2,
|
|
2828
|
+
await this.#query(
|
|
2829
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2830
|
+
[prefixed]
|
|
2831
|
+
)
|
|
2675
2832
|
);
|
|
2676
|
-
const entry = rows[0];
|
|
2677
2833
|
if (!entry) {
|
|
2678
2834
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2679
2835
|
}
|
|
@@ -2681,19 +2837,21 @@ var MssqlFs = class _MssqlFs {
|
|
|
2681
2837
|
isFile: entry.type === "file",
|
|
2682
2838
|
isDirectory: entry.type === "directory",
|
|
2683
2839
|
isSymbolicLink: entry.type === "symlink",
|
|
2684
|
-
mode:
|
|
2685
|
-
size:
|
|
2686
|
-
mtime: new Date(
|
|
2840
|
+
mode: entry.mode,
|
|
2841
|
+
size: entry.size,
|
|
2842
|
+
mtime: new Date(entry.mtime)
|
|
2687
2843
|
};
|
|
2688
2844
|
}
|
|
2689
2845
|
async mkdir(dirPath, options) {
|
|
2690
2846
|
const normalized = this.#normalizePath(dirPath);
|
|
2691
2847
|
const prefixed = this.#prefixPath(normalized);
|
|
2692
|
-
const
|
|
2693
|
-
|
|
2694
|
-
|
|
2848
|
+
const [existing] = rowsOf(
|
|
2849
|
+
typeRow2,
|
|
2850
|
+
await this.#query(
|
|
2851
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2852
|
+
[prefixed]
|
|
2853
|
+
)
|
|
2695
2854
|
);
|
|
2696
|
-
const existing = existingRows[0];
|
|
2697
2855
|
if (existing) {
|
|
2698
2856
|
if (options?.recursive) {
|
|
2699
2857
|
return;
|
|
@@ -2710,10 +2868,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2710
2868
|
currentPath = path4.posix.join(currentPath, segment);
|
|
2711
2869
|
const checkReq = transaction.request();
|
|
2712
2870
|
checkReq.input("p0", currentPath);
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2871
|
+
const [exists] = rowsOf(
|
|
2872
|
+
typeRow2,
|
|
2873
|
+
await checkReq.query(
|
|
2874
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2875
|
+
)
|
|
2715
2876
|
);
|
|
2716
|
-
const exists = result.recordset[0];
|
|
2717
2877
|
if (!exists) {
|
|
2718
2878
|
const insertReq = transaction.request();
|
|
2719
2879
|
insertReq.input("p0", currentPath);
|
|
@@ -2729,10 +2889,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2729
2889
|
const parent = this.#dirname(prefixed);
|
|
2730
2890
|
const parentReq = transaction.request();
|
|
2731
2891
|
parentReq.input("p0", parent);
|
|
2732
|
-
const
|
|
2733
|
-
|
|
2892
|
+
const [parentEntry] = rowsOf(
|
|
2893
|
+
typeRow2,
|
|
2894
|
+
await parentReq.query(
|
|
2895
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2896
|
+
)
|
|
2734
2897
|
);
|
|
2735
|
-
const parentEntry = parentResult.recordset[0];
|
|
2736
2898
|
if (!parentEntry) {
|
|
2737
2899
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
2738
2900
|
}
|
|
@@ -2752,11 +2914,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2752
2914
|
const normalized = this.#normalizePath(dirPath);
|
|
2753
2915
|
const prefixed = this.#prefixPath(normalized);
|
|
2754
2916
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2755
|
-
const
|
|
2756
|
-
|
|
2757
|
-
|
|
2917
|
+
const [entry] = rowsOf(
|
|
2918
|
+
typeRow2,
|
|
2919
|
+
await this.#query(
|
|
2920
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2921
|
+
[resolved]
|
|
2922
|
+
)
|
|
2758
2923
|
);
|
|
2759
|
-
const entry = entryRows[0];
|
|
2760
2924
|
if (!entry) {
|
|
2761
2925
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
2762
2926
|
}
|
|
@@ -2764,12 +2928,15 @@ var MssqlFs = class _MssqlFs {
|
|
|
2764
2928
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
2765
2929
|
}
|
|
2766
2930
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
2767
|
-
const rows =
|
|
2768
|
-
|
|
2931
|
+
const rows = rowsOf(
|
|
2932
|
+
pathRow2,
|
|
2933
|
+
await this.#query(
|
|
2934
|
+
`SELECT path FROM ${this.#t("fs_entries")}
|
|
2769
2935
|
WHERE path LIKE @p0 + '%'
|
|
2770
2936
|
AND path != @p1
|
|
2771
2937
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
2772
|
-
|
|
2938
|
+
[prefix, resolved]
|
|
2939
|
+
)
|
|
2773
2940
|
);
|
|
2774
2941
|
return rows.map((row) => path4.posix.basename(row.path));
|
|
2775
2942
|
}
|
|
@@ -2777,11 +2944,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2777
2944
|
const normalized = this.#normalizePath(dirPath);
|
|
2778
2945
|
const prefixed = this.#prefixPath(normalized);
|
|
2779
2946
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2782
|
-
|
|
2947
|
+
const [entry] = rowsOf(
|
|
2948
|
+
typeRow2,
|
|
2949
|
+
await this.#query(
|
|
2950
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2951
|
+
[resolved]
|
|
2952
|
+
)
|
|
2783
2953
|
);
|
|
2784
|
-
const entry = entryRows[0];
|
|
2785
2954
|
if (!entry) {
|
|
2786
2955
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
2787
2956
|
}
|
|
@@ -2789,12 +2958,15 @@ var MssqlFs = class _MssqlFs {
|
|
|
2789
2958
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
2790
2959
|
}
|
|
2791
2960
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
2792
|
-
const rows =
|
|
2793
|
-
|
|
2961
|
+
const rows = rowsOf(
|
|
2962
|
+
pathTypeRow2,
|
|
2963
|
+
await this.#query(
|
|
2964
|
+
`SELECT path, type FROM ${this.#t("fs_entries")}
|
|
2794
2965
|
WHERE path LIKE @p0 + '%'
|
|
2795
2966
|
AND path != @p1
|
|
2796
2967
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
2797
|
-
|
|
2968
|
+
[prefix, resolved]
|
|
2969
|
+
)
|
|
2798
2970
|
);
|
|
2799
2971
|
return rows.map((row) => ({
|
|
2800
2972
|
name: path4.posix.basename(row.path),
|
|
@@ -2806,11 +2978,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2806
2978
|
async rm(filePath, options) {
|
|
2807
2979
|
const normalized = this.#normalizePath(filePath);
|
|
2808
2980
|
const prefixed = this.#prefixPath(normalized);
|
|
2809
|
-
const
|
|
2810
|
-
|
|
2811
|
-
|
|
2981
|
+
const [entry] = rowsOf(
|
|
2982
|
+
typeRow2,
|
|
2983
|
+
await this.#query(
|
|
2984
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2985
|
+
[prefixed]
|
|
2986
|
+
)
|
|
2812
2987
|
);
|
|
2813
|
-
const entry = rows[0];
|
|
2814
2988
|
if (!entry) {
|
|
2815
2989
|
if (options?.force) {
|
|
2816
2990
|
return;
|
|
@@ -2821,10 +2995,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2821
2995
|
if (entry.type === "directory") {
|
|
2822
2996
|
const childrenReq = transaction.request();
|
|
2823
2997
|
childrenReq.input("p0", prefixed);
|
|
2824
|
-
const
|
|
2825
|
-
|
|
2998
|
+
const children = rowsOf(
|
|
2999
|
+
existsRow,
|
|
3000
|
+
await childrenReq.query(
|
|
3001
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path LIKE @p0 + '/%') THEN 1 ELSE 0 END as [exists]`
|
|
3002
|
+
)
|
|
2826
3003
|
);
|
|
2827
|
-
if (
|
|
3004
|
+
if (children[0].exists === 1 && !options?.recursive) {
|
|
2828
3005
|
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
2829
3006
|
}
|
|
2830
3007
|
const deleteReq = transaction.request();
|
|
@@ -2846,11 +3023,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2846
3023
|
const destNormalized = this.#normalizePath(dest);
|
|
2847
3024
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2848
3025
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2849
|
-
const
|
|
2850
|
-
|
|
2851
|
-
|
|
3026
|
+
const [srcEntry] = rowsOf(
|
|
3027
|
+
entryRow2,
|
|
3028
|
+
await this.#query(
|
|
3029
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3030
|
+
[srcPrefixed]
|
|
3031
|
+
)
|
|
2852
3032
|
);
|
|
2853
|
-
const srcEntry = srcRows[0];
|
|
2854
3033
|
if (!srcEntry) {
|
|
2855
3034
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
2856
3035
|
}
|
|
@@ -2862,10 +3041,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2862
3041
|
if (srcEntry.type === "directory") {
|
|
2863
3042
|
const allEntriesReq = transaction.request();
|
|
2864
3043
|
allEntriesReq.input("p0", srcPrefixed);
|
|
2865
|
-
const
|
|
2866
|
-
|
|
3044
|
+
const allEntries = rowsOf(
|
|
3045
|
+
entryRow2,
|
|
3046
|
+
await allEntriesReq.query(
|
|
3047
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
3048
|
+
)
|
|
2867
3049
|
);
|
|
2868
|
-
for (const entry of
|
|
3050
|
+
for (const entry of allEntries) {
|
|
2869
3051
|
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
2870
3052
|
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
2871
3053
|
const insertReq = transaction.request();
|
|
@@ -2893,10 +3075,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2893
3075
|
);
|
|
2894
3076
|
const chunksReq = transaction.request();
|
|
2895
3077
|
chunksReq.input("p0", entry.path);
|
|
2896
|
-
const
|
|
2897
|
-
|
|
3078
|
+
const chunks = rowsOf(
|
|
3079
|
+
chunkRow2,
|
|
3080
|
+
await chunksReq.query(
|
|
3081
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3082
|
+
)
|
|
2898
3083
|
);
|
|
2899
|
-
for (const chunk of
|
|
3084
|
+
for (const chunk of chunks) {
|
|
2900
3085
|
const chunkInsertReq = transaction.request();
|
|
2901
3086
|
chunkInsertReq.input("p0", newPath);
|
|
2902
3087
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -2928,15 +3113,18 @@ var MssqlFs = class _MssqlFs {
|
|
|
2928
3113
|
if (srcEntry.type === "file") {
|
|
2929
3114
|
const chunksReq = transaction.request();
|
|
2930
3115
|
chunksReq.input("p0", srcPrefixed);
|
|
2931
|
-
const
|
|
2932
|
-
|
|
3116
|
+
const chunks = rowsOf(
|
|
3117
|
+
chunkRow2,
|
|
3118
|
+
await chunksReq.query(
|
|
3119
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3120
|
+
)
|
|
2933
3121
|
);
|
|
2934
3122
|
const deleteChunksReq = transaction.request();
|
|
2935
3123
|
deleteChunksReq.input("p0", destPrefixed);
|
|
2936
3124
|
await deleteChunksReq.query(
|
|
2937
3125
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
2938
3126
|
);
|
|
2939
|
-
for (const chunk of
|
|
3127
|
+
for (const chunk of chunks) {
|
|
2940
3128
|
const chunkInsertReq = transaction.request();
|
|
2941
3129
|
chunkInsertReq.input("p0", destPrefixed);
|
|
2942
3130
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -2954,11 +3142,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2954
3142
|
const destNormalized = this.#normalizePath(dest);
|
|
2955
3143
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2956
3144
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2957
|
-
const
|
|
2958
|
-
|
|
2959
|
-
|
|
3145
|
+
const [srcEntry] = rowsOf(
|
|
3146
|
+
entryRow2,
|
|
3147
|
+
await this.#query(
|
|
3148
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3149
|
+
[srcPrefixed]
|
|
3150
|
+
)
|
|
2960
3151
|
);
|
|
2961
|
-
const srcEntry = srcRows[0];
|
|
2962
3152
|
if (!srcEntry) {
|
|
2963
3153
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
2964
3154
|
}
|
|
@@ -2967,15 +3157,18 @@ var MssqlFs = class _MssqlFs {
|
|
|
2967
3157
|
if (srcEntry.type === "directory") {
|
|
2968
3158
|
const allEntriesReq = transaction.request();
|
|
2969
3159
|
allEntriesReq.input("p0", srcPrefixed);
|
|
2970
|
-
const
|
|
2971
|
-
|
|
3160
|
+
const allEntries = rowsOf(
|
|
3161
|
+
entryRow2,
|
|
3162
|
+
await allEntriesReq.query(
|
|
3163
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%' ORDER BY path DESC`
|
|
3164
|
+
)
|
|
2972
3165
|
);
|
|
2973
3166
|
const destDeleteReq = transaction.request();
|
|
2974
3167
|
destDeleteReq.input("dp0", destPrefixed);
|
|
2975
3168
|
await destDeleteReq.query(
|
|
2976
3169
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @dp0 OR path LIKE @dp0 + '/%'`
|
|
2977
3170
|
);
|
|
2978
|
-
for (const entry of [...
|
|
3171
|
+
for (const entry of [...allEntries].reverse()) {
|
|
2979
3172
|
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
2980
3173
|
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
2981
3174
|
const insertReq = transaction.request();
|
|
@@ -3003,10 +3196,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3003
3196
|
);
|
|
3004
3197
|
const chunksReq = transaction.request();
|
|
3005
3198
|
chunksReq.input("p0", entry.path);
|
|
3006
|
-
const
|
|
3007
|
-
|
|
3199
|
+
const chunks = rowsOf(
|
|
3200
|
+
chunkRow2,
|
|
3201
|
+
await chunksReq.query(
|
|
3202
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3203
|
+
)
|
|
3008
3204
|
);
|
|
3009
|
-
for (const chunk of
|
|
3205
|
+
for (const chunk of chunks) {
|
|
3010
3206
|
const chunkInsertReq = transaction.request();
|
|
3011
3207
|
chunkInsertReq.input("p0", newPath);
|
|
3012
3208
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3048,10 +3244,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3048
3244
|
);
|
|
3049
3245
|
const chunksReq = transaction.request();
|
|
3050
3246
|
chunksReq.input("p0", srcPrefixed);
|
|
3051
|
-
const
|
|
3052
|
-
|
|
3247
|
+
const chunks = rowsOf(
|
|
3248
|
+
chunkRow2,
|
|
3249
|
+
await chunksReq.query(
|
|
3250
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3251
|
+
)
|
|
3053
3252
|
);
|
|
3054
|
-
for (const chunk of
|
|
3253
|
+
for (const chunk of chunks) {
|
|
3055
3254
|
const chunkInsertReq = transaction.request();
|
|
3056
3255
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3057
3256
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3078,8 +3277,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
3078
3277
|
);
|
|
3079
3278
|
}
|
|
3080
3279
|
async getAllPathsAsync() {
|
|
3081
|
-
const rows =
|
|
3082
|
-
|
|
3280
|
+
const rows = rowsOf(
|
|
3281
|
+
pathRow2,
|
|
3282
|
+
await this.#query(
|
|
3283
|
+
`SELECT path FROM ${this.#t("fs_entries")} ORDER BY path`
|
|
3284
|
+
)
|
|
3083
3285
|
);
|
|
3084
3286
|
return rows.map((row) => row.path);
|
|
3085
3287
|
}
|
|
@@ -3087,9 +3289,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3087
3289
|
const normalized = this.#normalizePath(filePath);
|
|
3088
3290
|
const prefixed = this.#prefixPath(normalized);
|
|
3089
3291
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3090
|
-
const rows =
|
|
3091
|
-
|
|
3092
|
-
|
|
3292
|
+
const rows = rowsOf(
|
|
3293
|
+
existsRow,
|
|
3294
|
+
await this.#query(
|
|
3295
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3296
|
+
[resolved]
|
|
3297
|
+
)
|
|
3093
3298
|
);
|
|
3094
3299
|
if (rows[0].exists !== 1) {
|
|
3095
3300
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -3122,9 +3327,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3122
3327
|
async symlink(target, linkPath) {
|
|
3123
3328
|
const normalized = this.#normalizePath(linkPath);
|
|
3124
3329
|
const prefixed = this.#prefixPath(normalized);
|
|
3125
|
-
const existingRows =
|
|
3126
|
-
|
|
3127
|
-
|
|
3330
|
+
const existingRows = rowsOf(
|
|
3331
|
+
existsRow,
|
|
3332
|
+
await this.#query(
|
|
3333
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3334
|
+
[prefixed]
|
|
3335
|
+
)
|
|
3128
3336
|
);
|
|
3129
3337
|
if (existingRows[0].exists === 1) {
|
|
3130
3338
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
@@ -3146,20 +3354,25 @@ var MssqlFs = class _MssqlFs {
|
|
|
3146
3354
|
const destNormalized = this.#normalizePath(newPath);
|
|
3147
3355
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3148
3356
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3357
|
+
const [srcEntry] = rowsOf(
|
|
3358
|
+
entryRow2,
|
|
3359
|
+
await this.#query(
|
|
3360
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3361
|
+
[srcPrefixed]
|
|
3362
|
+
)
|
|
3152
3363
|
);
|
|
3153
|
-
const srcEntry = srcRows[0];
|
|
3154
3364
|
if (!srcEntry) {
|
|
3155
3365
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
3156
3366
|
}
|
|
3157
3367
|
if (srcEntry.type !== "file") {
|
|
3158
3368
|
throw new Error(`link: not supported for directories: ${existingPath}`);
|
|
3159
3369
|
}
|
|
3160
|
-
const existingRows =
|
|
3161
|
-
|
|
3162
|
-
|
|
3370
|
+
const existingRows = rowsOf(
|
|
3371
|
+
existsRow,
|
|
3372
|
+
await this.#query(
|
|
3373
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3374
|
+
[destPrefixed]
|
|
3375
|
+
)
|
|
3163
3376
|
);
|
|
3164
3377
|
if (existingRows[0].exists === 1) {
|
|
3165
3378
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
@@ -3177,10 +3390,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3177
3390
|
);
|
|
3178
3391
|
const chunksReq = transaction.request();
|
|
3179
3392
|
chunksReq.input("p0", srcPrefixed);
|
|
3180
|
-
const
|
|
3181
|
-
|
|
3393
|
+
const chunks = rowsOf(
|
|
3394
|
+
chunkRow2,
|
|
3395
|
+
await chunksReq.query(
|
|
3396
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3397
|
+
)
|
|
3182
3398
|
);
|
|
3183
|
-
for (const chunk of
|
|
3399
|
+
for (const chunk of chunks) {
|
|
3184
3400
|
const chunkInsertReq = transaction.request();
|
|
3185
3401
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3186
3402
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3194,11 +3410,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3194
3410
|
async readlink(linkPath) {
|
|
3195
3411
|
const normalized = this.#normalizePath(linkPath);
|
|
3196
3412
|
const prefixed = this.#prefixPath(normalized);
|
|
3197
|
-
const
|
|
3198
|
-
|
|
3199
|
-
|
|
3413
|
+
const [entry] = rowsOf(
|
|
3414
|
+
linkRow2,
|
|
3415
|
+
await this.#query(
|
|
3416
|
+
`SELECT type, symlinkTarget FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3417
|
+
[prefixed]
|
|
3418
|
+
)
|
|
3200
3419
|
);
|
|
3201
|
-
const entry = rows[0];
|
|
3202
3420
|
if (!entry) {
|
|
3203
3421
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
3204
3422
|
}
|
|
@@ -3212,6 +3430,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3212
3430
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
3213
3431
|
import { createRequire as createRequire2 } from "node:module";
|
|
3214
3432
|
import * as path5 from "node:path";
|
|
3433
|
+
import z8 from "zod";
|
|
3215
3434
|
|
|
3216
3435
|
// packages/text2sql/src/lib/fs/postgres/ddl.postgres-fs.ts
|
|
3217
3436
|
function postgresFsDDL(schema) {
|
|
@@ -3240,6 +3459,33 @@ CREATE TABLE IF NOT EXISTS "${schema}"."fs_chunks" (
|
|
|
3240
3459
|
}
|
|
3241
3460
|
|
|
3242
3461
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
3462
|
+
var entryRow3 = z8.object({
|
|
3463
|
+
path: z8.string(),
|
|
3464
|
+
type: entryType,
|
|
3465
|
+
mode: z8.number(),
|
|
3466
|
+
size: bigintColumn,
|
|
3467
|
+
mtime: bigintColumn,
|
|
3468
|
+
symlink_target: z8.string().nullable()
|
|
3469
|
+
});
|
|
3470
|
+
var typeRow3 = entryRow3.pick({ type: true });
|
|
3471
|
+
var pathRow3 = entryRow3.pick({ path: true });
|
|
3472
|
+
var pathTypeRow3 = entryRow3.pick({ path: true, type: true });
|
|
3473
|
+
var linkRow3 = z8.discriminatedUnion("type", [
|
|
3474
|
+
z8.object({ type: z8.literal("symlink"), symlink_target: z8.string() }),
|
|
3475
|
+
z8.object({
|
|
3476
|
+
type: z8.enum(["file", "directory"]),
|
|
3477
|
+
symlink_target: z8.string().nullable()
|
|
3478
|
+
})
|
|
3479
|
+
]);
|
|
3480
|
+
var existsRow2 = z8.object({ exists: z8.boolean() });
|
|
3481
|
+
var chunkRow3 = z8.object({
|
|
3482
|
+
chunk_index: z8.number(),
|
|
3483
|
+
data: z8.instanceof(Buffer)
|
|
3484
|
+
});
|
|
3485
|
+
var dataRow3 = chunkRow3.pick({ data: true });
|
|
3486
|
+
function rowsOf2(row, result) {
|
|
3487
|
+
return z8.array(row).parse(result.rows);
|
|
3488
|
+
}
|
|
3243
3489
|
var PostgresFs = class _PostgresFs {
|
|
3244
3490
|
#pool;
|
|
3245
3491
|
#chunkSize;
|
|
@@ -3281,8 +3527,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3281
3527
|
async initialize() {
|
|
3282
3528
|
const ddl = postgresFsDDL(this.#schema);
|
|
3283
3529
|
await this.#pool.query(ddl);
|
|
3284
|
-
const rootSlashExists =
|
|
3285
|
-
|
|
3530
|
+
const rootSlashExists = rowsOf2(
|
|
3531
|
+
existsRow2,
|
|
3532
|
+
await this.#rawQuery(
|
|
3533
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') AS exists`
|
|
3534
|
+
)
|
|
3286
3535
|
);
|
|
3287
3536
|
if (!rootSlashExists[0].exists) {
|
|
3288
3537
|
await this.#rawExec(
|
|
@@ -3292,9 +3541,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3292
3541
|
}
|
|
3293
3542
|
if (this.#root) {
|
|
3294
3543
|
await this.#createParentDirs(this.#root);
|
|
3295
|
-
const rootExists =
|
|
3296
|
-
|
|
3297
|
-
|
|
3544
|
+
const rootExists = rowsOf2(
|
|
3545
|
+
existsRow2,
|
|
3546
|
+
await this.#rawQuery(
|
|
3547
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3548
|
+
[this.#root]
|
|
3549
|
+
)
|
|
3298
3550
|
);
|
|
3299
3551
|
if (!rootExists[0].exists) {
|
|
3300
3552
|
await this.#rawExec(
|
|
@@ -3317,9 +3569,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3317
3569
|
let currentPath = "/";
|
|
3318
3570
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3319
3571
|
currentPath = path5.posix.join(currentPath, segments[i]);
|
|
3320
|
-
const exists =
|
|
3321
|
-
|
|
3322
|
-
|
|
3572
|
+
const exists = rowsOf2(
|
|
3573
|
+
existsRow2,
|
|
3574
|
+
await this.#rawQuery(
|
|
3575
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3576
|
+
[currentPath]
|
|
3577
|
+
)
|
|
3323
3578
|
);
|
|
3324
3579
|
if (!exists[0].exists) {
|
|
3325
3580
|
await this.#rawExec(
|
|
@@ -3329,9 +3584,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
3329
3584
|
}
|
|
3330
3585
|
}
|
|
3331
3586
|
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
return result.rows;
|
|
3587
|
+
#rawQuery(sql, params) {
|
|
3588
|
+
return this.#pool.query(sql, params);
|
|
3335
3589
|
}
|
|
3336
3590
|
async #rawExec(sql, params) {
|
|
3337
3591
|
const result = await this.#pool.query(sql, params);
|
|
@@ -3395,11 +3649,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3395
3649
|
const parent = this.#dirname(filePath);
|
|
3396
3650
|
const rootPath = this.#root || "/";
|
|
3397
3651
|
if (parent === rootPath || parent === "/") return;
|
|
3398
|
-
const
|
|
3399
|
-
|
|
3400
|
-
|
|
3652
|
+
const [entry] = rowsOf2(
|
|
3653
|
+
typeRow3,
|
|
3654
|
+
await client.query(
|
|
3655
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3656
|
+
[parent]
|
|
3657
|
+
)
|
|
3401
3658
|
);
|
|
3402
|
-
const entry = result.rows[0];
|
|
3403
3659
|
if (!entry) {
|
|
3404
3660
|
await this.#ensureParentExists(parent, client);
|
|
3405
3661
|
await client.query(
|
|
@@ -3426,19 +3682,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3426
3682
|
}
|
|
3427
3683
|
}
|
|
3428
3684
|
async #readChunks(filePath, client) {
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
);
|
|
3435
|
-
rows = result2.rows;
|
|
3436
|
-
} else {
|
|
3437
|
-
rows = await this.#query(
|
|
3438
|
-
`SELECT data FROM ${this.#t("fs_chunks")} WHERE path = $1 ORDER BY chunk_index`,
|
|
3439
|
-
[filePath]
|
|
3440
|
-
);
|
|
3441
|
-
}
|
|
3685
|
+
const sql = `SELECT data FROM ${this.#t("fs_chunks")} WHERE path = $1 ORDER BY chunk_index`;
|
|
3686
|
+
const rows = rowsOf2(
|
|
3687
|
+
dataRow3,
|
|
3688
|
+
client ? await client.query(sql, [filePath]) : await this.#query(sql, [filePath])
|
|
3689
|
+
);
|
|
3442
3690
|
if (rows.length === 0) {
|
|
3443
3691
|
return new Uint8Array(0);
|
|
3444
3692
|
}
|
|
@@ -3455,11 +3703,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3455
3703
|
if (seen.has(p)) {
|
|
3456
3704
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
3457
3705
|
}
|
|
3458
|
-
const
|
|
3459
|
-
|
|
3460
|
-
|
|
3706
|
+
const [entry] = rowsOf2(
|
|
3707
|
+
linkRow3,
|
|
3708
|
+
await this.#query(
|
|
3709
|
+
`SELECT type, symlink_target FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3710
|
+
[p]
|
|
3711
|
+
)
|
|
3461
3712
|
);
|
|
3462
|
-
const entry = rows[0];
|
|
3463
3713
|
if (!entry) {
|
|
3464
3714
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
3465
3715
|
}
|
|
@@ -3476,8 +3726,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3476
3726
|
if (content instanceof Uint8Array) {
|
|
3477
3727
|
return content;
|
|
3478
3728
|
}
|
|
3479
|
-
|
|
3480
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
3729
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
3481
3730
|
}
|
|
3482
3731
|
async close() {
|
|
3483
3732
|
if (this.#ownsPool) {
|
|
@@ -3491,11 +3740,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3491
3740
|
const normalized = this.#normalizePath(filePath);
|
|
3492
3741
|
const prefixed = this.#prefixPath(normalized);
|
|
3493
3742
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3494
|
-
const
|
|
3495
|
-
|
|
3496
|
-
|
|
3743
|
+
const [entry] = rowsOf2(
|
|
3744
|
+
typeRow3,
|
|
3745
|
+
await this.#query(
|
|
3746
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3747
|
+
[resolved]
|
|
3748
|
+
)
|
|
3497
3749
|
);
|
|
3498
|
-
const entry = rows[0];
|
|
3499
3750
|
if (!entry) {
|
|
3500
3751
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3501
3752
|
}
|
|
@@ -3510,11 +3761,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3510
3761
|
const normalized = this.#normalizePath(filePath);
|
|
3511
3762
|
const prefixed = this.#prefixPath(normalized);
|
|
3512
3763
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3513
|
-
const
|
|
3514
|
-
|
|
3515
|
-
|
|
3764
|
+
const [entry] = rowsOf2(
|
|
3765
|
+
typeRow3,
|
|
3766
|
+
await this.#query(
|
|
3767
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3768
|
+
[resolved]
|
|
3769
|
+
)
|
|
3516
3770
|
);
|
|
3517
|
-
const entry = rows[0];
|
|
3518
3771
|
if (!entry) {
|
|
3519
3772
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3520
3773
|
}
|
|
@@ -3546,11 +3799,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3546
3799
|
const newData = this.#toUint8Array(content, encoding);
|
|
3547
3800
|
await this.#useTransaction(async (client) => {
|
|
3548
3801
|
await this.#ensureParentExists(prefixed, client);
|
|
3549
|
-
const
|
|
3550
|
-
|
|
3551
|
-
|
|
3802
|
+
const [entry] = rowsOf2(
|
|
3803
|
+
typeRow3,
|
|
3804
|
+
await client.query(
|
|
3805
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3806
|
+
[prefixed]
|
|
3807
|
+
)
|
|
3552
3808
|
);
|
|
3553
|
-
const entry = result.rows[0];
|
|
3554
3809
|
if (entry && entry.type !== "file") {
|
|
3555
3810
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
3556
3811
|
}
|
|
@@ -3570,9 +3825,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3570
3825
|
async exists(filePath) {
|
|
3571
3826
|
const normalized = this.#normalizePath(filePath);
|
|
3572
3827
|
const prefixed = this.#prefixPath(normalized);
|
|
3573
|
-
const rows =
|
|
3574
|
-
|
|
3575
|
-
|
|
3828
|
+
const rows = rowsOf2(
|
|
3829
|
+
existsRow2,
|
|
3830
|
+
await this.#query(
|
|
3831
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3832
|
+
[prefixed]
|
|
3833
|
+
)
|
|
3576
3834
|
);
|
|
3577
3835
|
return rows[0].exists;
|
|
3578
3836
|
}
|
|
@@ -3580,11 +3838,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3580
3838
|
const normalized = this.#normalizePath(filePath);
|
|
3581
3839
|
const prefixed = this.#prefixPath(normalized);
|
|
3582
3840
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3583
|
-
const
|
|
3584
|
-
|
|
3585
|
-
|
|
3841
|
+
const [entry] = rowsOf2(
|
|
3842
|
+
entryRow3,
|
|
3843
|
+
await this.#query(
|
|
3844
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3845
|
+
[resolved]
|
|
3846
|
+
)
|
|
3586
3847
|
);
|
|
3587
|
-
const entry = rows[0];
|
|
3588
3848
|
if (!entry) {
|
|
3589
3849
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3590
3850
|
}
|
|
@@ -3592,19 +3852,21 @@ var PostgresFs = class _PostgresFs {
|
|
|
3592
3852
|
isFile: entry.type === "file",
|
|
3593
3853
|
isDirectory: entry.type === "directory",
|
|
3594
3854
|
isSymbolicLink: false,
|
|
3595
|
-
mode:
|
|
3596
|
-
size:
|
|
3597
|
-
mtime: new Date(
|
|
3855
|
+
mode: entry.mode,
|
|
3856
|
+
size: entry.size,
|
|
3857
|
+
mtime: new Date(entry.mtime)
|
|
3598
3858
|
};
|
|
3599
3859
|
}
|
|
3600
3860
|
async lstat(filePath) {
|
|
3601
3861
|
const normalized = this.#normalizePath(filePath);
|
|
3602
3862
|
const prefixed = this.#prefixPath(normalized);
|
|
3603
|
-
const
|
|
3604
|
-
|
|
3605
|
-
|
|
3863
|
+
const [entry] = rowsOf2(
|
|
3864
|
+
entryRow3,
|
|
3865
|
+
await this.#query(
|
|
3866
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3867
|
+
[prefixed]
|
|
3868
|
+
)
|
|
3606
3869
|
);
|
|
3607
|
-
const entry = rows[0];
|
|
3608
3870
|
if (!entry) {
|
|
3609
3871
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3610
3872
|
}
|
|
@@ -3612,19 +3874,21 @@ var PostgresFs = class _PostgresFs {
|
|
|
3612
3874
|
isFile: entry.type === "file",
|
|
3613
3875
|
isDirectory: entry.type === "directory",
|
|
3614
3876
|
isSymbolicLink: entry.type === "symlink",
|
|
3615
|
-
mode:
|
|
3616
|
-
size:
|
|
3617
|
-
mtime: new Date(
|
|
3877
|
+
mode: entry.mode,
|
|
3878
|
+
size: entry.size,
|
|
3879
|
+
mtime: new Date(entry.mtime)
|
|
3618
3880
|
};
|
|
3619
3881
|
}
|
|
3620
3882
|
async mkdir(dirPath, options) {
|
|
3621
3883
|
const normalized = this.#normalizePath(dirPath);
|
|
3622
3884
|
const prefixed = this.#prefixPath(normalized);
|
|
3623
|
-
const
|
|
3624
|
-
|
|
3625
|
-
|
|
3885
|
+
const [existing] = rowsOf2(
|
|
3886
|
+
typeRow3,
|
|
3887
|
+
await this.#query(
|
|
3888
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3889
|
+
[prefixed]
|
|
3890
|
+
)
|
|
3626
3891
|
);
|
|
3627
|
-
const existing = existingRows[0];
|
|
3628
3892
|
if (existing) {
|
|
3629
3893
|
if (options?.recursive) {
|
|
3630
3894
|
return;
|
|
@@ -3639,11 +3903,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3639
3903
|
let currentPath = rootPath;
|
|
3640
3904
|
for (const segment of segments) {
|
|
3641
3905
|
currentPath = path5.posix.join(currentPath, segment);
|
|
3642
|
-
const
|
|
3643
|
-
|
|
3644
|
-
|
|
3906
|
+
const [exists] = rowsOf2(
|
|
3907
|
+
typeRow3,
|
|
3908
|
+
await client.query(
|
|
3909
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3910
|
+
[currentPath]
|
|
3911
|
+
)
|
|
3645
3912
|
);
|
|
3646
|
-
const exists = result.rows[0];
|
|
3647
3913
|
if (!exists) {
|
|
3648
3914
|
await client.query(
|
|
3649
3915
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ($1, 'directory', 493, 0, $2)`,
|
|
@@ -3655,11 +3921,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3655
3921
|
}
|
|
3656
3922
|
} else {
|
|
3657
3923
|
const parent = this.#dirname(prefixed);
|
|
3658
|
-
const
|
|
3659
|
-
|
|
3660
|
-
|
|
3924
|
+
const [parentEntry] = rowsOf2(
|
|
3925
|
+
typeRow3,
|
|
3926
|
+
await client.query(
|
|
3927
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3928
|
+
[parent]
|
|
3929
|
+
)
|
|
3661
3930
|
);
|
|
3662
|
-
const parentEntry = parentResult.rows[0];
|
|
3663
3931
|
if (!parentEntry) {
|
|
3664
3932
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
3665
3933
|
}
|
|
@@ -3677,11 +3945,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3677
3945
|
const normalized = this.#normalizePath(dirPath);
|
|
3678
3946
|
const prefixed = this.#prefixPath(normalized);
|
|
3679
3947
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3680
|
-
const
|
|
3681
|
-
|
|
3682
|
-
|
|
3948
|
+
const [entry] = rowsOf2(
|
|
3949
|
+
typeRow3,
|
|
3950
|
+
await this.#query(
|
|
3951
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3952
|
+
[resolved]
|
|
3953
|
+
)
|
|
3683
3954
|
);
|
|
3684
|
-
const entry = entryRows[0];
|
|
3685
3955
|
if (!entry) {
|
|
3686
3956
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
3687
3957
|
}
|
|
@@ -3689,12 +3959,15 @@ var PostgresFs = class _PostgresFs {
|
|
|
3689
3959
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
3690
3960
|
}
|
|
3691
3961
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
3692
|
-
const rows =
|
|
3693
|
-
|
|
3962
|
+
const rows = rowsOf2(
|
|
3963
|
+
pathRow3,
|
|
3964
|
+
await this.#query(
|
|
3965
|
+
`SELECT path FROM ${this.#t("fs_entries")}
|
|
3694
3966
|
WHERE path LIKE $1 || '%'
|
|
3695
3967
|
AND path != $2
|
|
3696
3968
|
AND path NOT LIKE $1 || '%/%'`,
|
|
3697
|
-
|
|
3969
|
+
[prefix, resolved]
|
|
3970
|
+
)
|
|
3698
3971
|
);
|
|
3699
3972
|
return rows.map((row) => path5.posix.basename(row.path));
|
|
3700
3973
|
}
|
|
@@ -3702,11 +3975,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3702
3975
|
const normalized = this.#normalizePath(dirPath);
|
|
3703
3976
|
const prefixed = this.#prefixPath(normalized);
|
|
3704
3977
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3705
|
-
const
|
|
3706
|
-
|
|
3707
|
-
|
|
3978
|
+
const [entry] = rowsOf2(
|
|
3979
|
+
typeRow3,
|
|
3980
|
+
await this.#query(
|
|
3981
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3982
|
+
[resolved]
|
|
3983
|
+
)
|
|
3708
3984
|
);
|
|
3709
|
-
const entry = entryRows[0];
|
|
3710
3985
|
if (!entry) {
|
|
3711
3986
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
3712
3987
|
}
|
|
@@ -3714,12 +3989,15 @@ var PostgresFs = class _PostgresFs {
|
|
|
3714
3989
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
3715
3990
|
}
|
|
3716
3991
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
3717
|
-
const rows =
|
|
3718
|
-
|
|
3992
|
+
const rows = rowsOf2(
|
|
3993
|
+
pathTypeRow3,
|
|
3994
|
+
await this.#query(
|
|
3995
|
+
`SELECT path, type FROM ${this.#t("fs_entries")}
|
|
3719
3996
|
WHERE path LIKE $1 || '%'
|
|
3720
3997
|
AND path != $2
|
|
3721
3998
|
AND path NOT LIKE $1 || '%/%'`,
|
|
3722
|
-
|
|
3999
|
+
[prefix, resolved]
|
|
4000
|
+
)
|
|
3723
4001
|
);
|
|
3724
4002
|
return rows.map((row) => ({
|
|
3725
4003
|
name: path5.posix.basename(row.path),
|
|
@@ -3731,11 +4009,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3731
4009
|
async rm(filePath, options) {
|
|
3732
4010
|
const normalized = this.#normalizePath(filePath);
|
|
3733
4011
|
const prefixed = this.#prefixPath(normalized);
|
|
3734
|
-
const
|
|
3735
|
-
|
|
3736
|
-
|
|
4012
|
+
const [entry] = rowsOf2(
|
|
4013
|
+
typeRow3,
|
|
4014
|
+
await this.#query(
|
|
4015
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4016
|
+
[prefixed]
|
|
4017
|
+
)
|
|
3737
4018
|
);
|
|
3738
|
-
const entry = rows[0];
|
|
3739
4019
|
if (!entry) {
|
|
3740
4020
|
if (options?.force) {
|
|
3741
4021
|
return;
|
|
@@ -3744,11 +4024,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3744
4024
|
}
|
|
3745
4025
|
await this.#useTransaction(async (client) => {
|
|
3746
4026
|
if (entry.type === "directory") {
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3749
|
-
|
|
4027
|
+
const children = rowsOf2(
|
|
4028
|
+
existsRow2,
|
|
4029
|
+
await client.query(
|
|
4030
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path LIKE $1 || '/%') AS exists`,
|
|
4031
|
+
[prefixed]
|
|
4032
|
+
)
|
|
3750
4033
|
);
|
|
3751
|
-
if (
|
|
4034
|
+
if (children[0].exists && !options?.recursive) {
|
|
3752
4035
|
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
3753
4036
|
}
|
|
3754
4037
|
await client.query(
|
|
@@ -3768,11 +4051,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3768
4051
|
const destNormalized = this.#normalizePath(dest);
|
|
3769
4052
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3770
4053
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3771
|
-
const
|
|
3772
|
-
|
|
3773
|
-
|
|
4054
|
+
const [srcEntry] = rowsOf2(
|
|
4055
|
+
entryRow3,
|
|
4056
|
+
await this.#query(
|
|
4057
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4058
|
+
[srcPrefixed]
|
|
4059
|
+
)
|
|
3774
4060
|
);
|
|
3775
|
-
const srcEntry = srcRows[0];
|
|
3776
4061
|
if (!srcEntry) {
|
|
3777
4062
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
3778
4063
|
}
|
|
@@ -3782,11 +4067,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3782
4067
|
await this.#useTransaction(async (client) => {
|
|
3783
4068
|
await this.#ensureParentExists(destPrefixed, client);
|
|
3784
4069
|
if (srcEntry.type === "directory") {
|
|
3785
|
-
const
|
|
3786
|
-
|
|
3787
|
-
|
|
4070
|
+
const allEntries = rowsOf2(
|
|
4071
|
+
entryRow3,
|
|
4072
|
+
await client.query(
|
|
4073
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%'`,
|
|
4074
|
+
[srcPrefixed]
|
|
4075
|
+
)
|
|
3788
4076
|
);
|
|
3789
|
-
for (const entry of
|
|
4077
|
+
for (const entry of allEntries) {
|
|
3790
4078
|
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
3791
4079
|
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
3792
4080
|
await client.query(
|
|
@@ -3807,11 +4095,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3807
4095
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3808
4096
|
[newPath]
|
|
3809
4097
|
);
|
|
3810
|
-
const
|
|
3811
|
-
|
|
3812
|
-
|
|
4098
|
+
const chunks = rowsOf2(
|
|
4099
|
+
chunkRow3,
|
|
4100
|
+
await client.query(
|
|
4101
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4102
|
+
[entry.path]
|
|
4103
|
+
)
|
|
3813
4104
|
);
|
|
3814
|
-
for (const chunk of
|
|
4105
|
+
for (const chunk of chunks) {
|
|
3815
4106
|
await client.query(
|
|
3816
4107
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3817
4108
|
[newPath, chunk.chunk_index, chunk.data]
|
|
@@ -3834,15 +4125,18 @@ var PostgresFs = class _PostgresFs {
|
|
|
3834
4125
|
]
|
|
3835
4126
|
);
|
|
3836
4127
|
if (srcEntry.type === "file") {
|
|
3837
|
-
const
|
|
3838
|
-
|
|
3839
|
-
|
|
4128
|
+
const chunks = rowsOf2(
|
|
4129
|
+
chunkRow3,
|
|
4130
|
+
await client.query(
|
|
4131
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4132
|
+
[srcPrefixed]
|
|
4133
|
+
)
|
|
3840
4134
|
);
|
|
3841
4135
|
await client.query(
|
|
3842
4136
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3843
4137
|
[destPrefixed]
|
|
3844
4138
|
);
|
|
3845
|
-
for (const chunk of
|
|
4139
|
+
for (const chunk of chunks) {
|
|
3846
4140
|
await client.query(
|
|
3847
4141
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3848
4142
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -3857,26 +4151,31 @@ var PostgresFs = class _PostgresFs {
|
|
|
3857
4151
|
const destNormalized = this.#normalizePath(dest);
|
|
3858
4152
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3859
4153
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3860
|
-
const
|
|
3861
|
-
|
|
3862
|
-
|
|
4154
|
+
const [srcEntry] = rowsOf2(
|
|
4155
|
+
entryRow3,
|
|
4156
|
+
await this.#query(
|
|
4157
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4158
|
+
[srcPrefixed]
|
|
4159
|
+
)
|
|
3863
4160
|
);
|
|
3864
|
-
const srcEntry = srcRows[0];
|
|
3865
4161
|
if (!srcEntry) {
|
|
3866
4162
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
3867
4163
|
}
|
|
3868
4164
|
await this.#useTransaction(async (client) => {
|
|
3869
4165
|
await this.#ensureParentExists(destPrefixed, client);
|
|
3870
4166
|
if (srcEntry.type === "directory") {
|
|
3871
|
-
const
|
|
3872
|
-
|
|
3873
|
-
|
|
4167
|
+
const allEntries = rowsOf2(
|
|
4168
|
+
entryRow3,
|
|
4169
|
+
await client.query(
|
|
4170
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%' ORDER BY path DESC`,
|
|
4171
|
+
[srcPrefixed]
|
|
4172
|
+
)
|
|
3874
4173
|
);
|
|
3875
4174
|
await client.query(
|
|
3876
4175
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%'`,
|
|
3877
4176
|
[destPrefixed]
|
|
3878
4177
|
);
|
|
3879
|
-
for (const entry of [...
|
|
4178
|
+
for (const entry of [...allEntries].reverse()) {
|
|
3880
4179
|
const relativePath = path5.posix.relative(srcPrefixed, entry.path);
|
|
3881
4180
|
const newPath = path5.posix.join(destPrefixed, relativePath);
|
|
3882
4181
|
await client.query(
|
|
@@ -3897,11 +4196,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3897
4196
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3898
4197
|
[newPath]
|
|
3899
4198
|
);
|
|
3900
|
-
const
|
|
3901
|
-
|
|
3902
|
-
|
|
4199
|
+
const chunks = rowsOf2(
|
|
4200
|
+
chunkRow3,
|
|
4201
|
+
await client.query(
|
|
4202
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4203
|
+
[entry.path]
|
|
4204
|
+
)
|
|
3903
4205
|
);
|
|
3904
|
-
for (const chunk of
|
|
4206
|
+
for (const chunk of chunks) {
|
|
3905
4207
|
await client.query(
|
|
3906
4208
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3907
4209
|
[newPath, chunk.chunk_index, chunk.data]
|
|
@@ -3932,11 +4234,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3932
4234
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3933
4235
|
[destPrefixed]
|
|
3934
4236
|
);
|
|
3935
|
-
const
|
|
3936
|
-
|
|
3937
|
-
|
|
4237
|
+
const chunks = rowsOf2(
|
|
4238
|
+
chunkRow3,
|
|
4239
|
+
await client.query(
|
|
4240
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4241
|
+
[srcPrefixed]
|
|
4242
|
+
)
|
|
3938
4243
|
);
|
|
3939
|
-
for (const chunk of
|
|
4244
|
+
for (const chunk of chunks) {
|
|
3940
4245
|
await client.query(
|
|
3941
4246
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3942
4247
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -3959,8 +4264,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3959
4264
|
);
|
|
3960
4265
|
}
|
|
3961
4266
|
async getAllPathsAsync() {
|
|
3962
|
-
const rows =
|
|
3963
|
-
|
|
4267
|
+
const rows = rowsOf2(
|
|
4268
|
+
pathRow3,
|
|
4269
|
+
await this.#query(
|
|
4270
|
+
`SELECT path FROM ${this.#t("fs_entries")} ORDER BY path`
|
|
4271
|
+
)
|
|
3964
4272
|
);
|
|
3965
4273
|
return rows.map((row) => row.path);
|
|
3966
4274
|
}
|
|
@@ -3968,9 +4276,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3968
4276
|
const normalized = this.#normalizePath(filePath);
|
|
3969
4277
|
const prefixed = this.#prefixPath(normalized);
|
|
3970
4278
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3971
|
-
const rows =
|
|
3972
|
-
|
|
3973
|
-
|
|
4279
|
+
const rows = rowsOf2(
|
|
4280
|
+
existsRow2,
|
|
4281
|
+
await this.#query(
|
|
4282
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4283
|
+
[resolved]
|
|
4284
|
+
)
|
|
3974
4285
|
);
|
|
3975
4286
|
if (!rows[0].exists) {
|
|
3976
4287
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -4003,9 +4314,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
4003
4314
|
async symlink(target, linkPath) {
|
|
4004
4315
|
const normalized = this.#normalizePath(linkPath);
|
|
4005
4316
|
const prefixed = this.#prefixPath(normalized);
|
|
4006
|
-
const existingRows =
|
|
4007
|
-
|
|
4008
|
-
|
|
4317
|
+
const existingRows = rowsOf2(
|
|
4318
|
+
existsRow2,
|
|
4319
|
+
await this.#query(
|
|
4320
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4321
|
+
[prefixed]
|
|
4322
|
+
)
|
|
4009
4323
|
);
|
|
4010
4324
|
if (existingRows[0].exists) {
|
|
4011
4325
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
@@ -4024,20 +4338,25 @@ var PostgresFs = class _PostgresFs {
|
|
|
4024
4338
|
const destNormalized = this.#normalizePath(newPath);
|
|
4025
4339
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
4026
4340
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
4027
|
-
const
|
|
4028
|
-
|
|
4029
|
-
|
|
4341
|
+
const [srcEntry] = rowsOf2(
|
|
4342
|
+
entryRow3,
|
|
4343
|
+
await this.#query(
|
|
4344
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4345
|
+
[srcPrefixed]
|
|
4346
|
+
)
|
|
4030
4347
|
);
|
|
4031
|
-
const srcEntry = srcRows[0];
|
|
4032
4348
|
if (!srcEntry) {
|
|
4033
4349
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
4034
4350
|
}
|
|
4035
4351
|
if (srcEntry.type !== "file") {
|
|
4036
4352
|
throw new Error(`link: not supported for directories: ${existingPath}`);
|
|
4037
4353
|
}
|
|
4038
|
-
const existingRows =
|
|
4039
|
-
|
|
4040
|
-
|
|
4354
|
+
const existingRows = rowsOf2(
|
|
4355
|
+
existsRow2,
|
|
4356
|
+
await this.#query(
|
|
4357
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4358
|
+
[destPrefixed]
|
|
4359
|
+
)
|
|
4041
4360
|
);
|
|
4042
4361
|
if (existingRows[0].exists) {
|
|
4043
4362
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
@@ -4049,11 +4368,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
4049
4368
|
VALUES ($1, 'file', $2, $3, $4)`,
|
|
4050
4369
|
[destPrefixed, srcEntry.mode, srcEntry.size, Date.now()]
|
|
4051
4370
|
);
|
|
4052
|
-
const
|
|
4053
|
-
|
|
4054
|
-
|
|
4371
|
+
const chunks = rowsOf2(
|
|
4372
|
+
chunkRow3,
|
|
4373
|
+
await client.query(
|
|
4374
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4375
|
+
[srcPrefixed]
|
|
4376
|
+
)
|
|
4055
4377
|
);
|
|
4056
|
-
for (const chunk of
|
|
4378
|
+
for (const chunk of chunks) {
|
|
4057
4379
|
await client.query(
|
|
4058
4380
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
4059
4381
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -4064,11 +4386,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
4064
4386
|
async readlink(linkPath) {
|
|
4065
4387
|
const normalized = this.#normalizePath(linkPath);
|
|
4066
4388
|
const prefixed = this.#prefixPath(normalized);
|
|
4067
|
-
const
|
|
4068
|
-
|
|
4069
|
-
|
|
4389
|
+
const [entry] = rowsOf2(
|
|
4390
|
+
linkRow3,
|
|
4391
|
+
await this.#query(
|
|
4392
|
+
`SELECT type, symlink_target FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4393
|
+
[prefixed]
|
|
4394
|
+
)
|
|
4070
4395
|
);
|
|
4071
|
-
const entry = rows[0];
|
|
4072
4396
|
if (!entry) {
|
|
4073
4397
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
4074
4398
|
}
|
|
@@ -4583,12 +4907,11 @@ import {
|
|
|
4583
4907
|
BashException,
|
|
4584
4908
|
asStaticWordText as asStaticWordText2
|
|
4585
4909
|
} from "@deepagents/context";
|
|
4910
|
+
function isRecord(value) {
|
|
4911
|
+
return typeof value === "object" && value !== null;
|
|
4912
|
+
}
|
|
4586
4913
|
function isScriptNode(value) {
|
|
4587
|
-
|
|
4588
|
-
return false;
|
|
4589
|
-
}
|
|
4590
|
-
const node = value;
|
|
4591
|
-
return node.type === "Script" && Array.isArray(node.statements);
|
|
4914
|
+
return isRecord(value) && value.type === "Script" && Array.isArray(value.statements);
|
|
4592
4915
|
}
|
|
4593
4916
|
var BLOCKED_DB_CLIENT_COMMANDS = /* @__PURE__ */ new Set([
|
|
4594
4917
|
"psql",
|
|
@@ -4678,11 +5001,7 @@ function wordContainsBlockedCommand(word, context, mode) {
|
|
|
4678
5001
|
if (!word) {
|
|
4679
5002
|
return false;
|
|
4680
5003
|
}
|
|
4681
|
-
return wordPartContainsBlockedCommand(
|
|
4682
|
-
word.parts,
|
|
4683
|
-
context,
|
|
4684
|
-
mode
|
|
4685
|
-
);
|
|
5004
|
+
return wordPartContainsBlockedCommand(word.parts, context, mode);
|
|
4686
5005
|
}
|
|
4687
5006
|
function wordPartContainsBlockedCommand(parts, context, mode) {
|
|
4688
5007
|
for (const part of parts) {
|
|
@@ -4693,6 +5012,9 @@ function wordPartContainsBlockedCommand(parts, context, mode) {
|
|
|
4693
5012
|
return false;
|
|
4694
5013
|
}
|
|
4695
5014
|
function partContainsBlockedCommand(node, context, mode) {
|
|
5015
|
+
if (!isRecord(node)) {
|
|
5016
|
+
return false;
|
|
5017
|
+
}
|
|
4696
5018
|
const type = node.type;
|
|
4697
5019
|
if (type === "CommandSubstitution" || type === "ProcessSubstitution") {
|
|
4698
5020
|
if (isScriptNode(node.body)) {
|
|
@@ -4709,27 +5031,13 @@ function partContainsBlockedCommand(node, context, mode) {
|
|
|
4709
5031
|
}
|
|
4710
5032
|
for (const value of Object.values(node)) {
|
|
4711
5033
|
if (Array.isArray(value)) {
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
if (partContainsBlockedCommand(
|
|
4715
|
-
item,
|
|
4716
|
-
context,
|
|
4717
|
-
mode
|
|
4718
|
-
)) {
|
|
4719
|
-
return true;
|
|
4720
|
-
}
|
|
4721
|
-
}
|
|
5034
|
+
if (wordPartContainsBlockedCommand(value, context, mode)) {
|
|
5035
|
+
return true;
|
|
4722
5036
|
}
|
|
4723
5037
|
continue;
|
|
4724
5038
|
}
|
|
4725
|
-
if (
|
|
4726
|
-
|
|
4727
|
-
value,
|
|
4728
|
-
context,
|
|
4729
|
-
mode
|
|
4730
|
-
)) {
|
|
4731
|
-
return true;
|
|
4732
|
-
}
|
|
5039
|
+
if (partContainsBlockedCommand(value, context, mode)) {
|
|
5040
|
+
return true;
|
|
4733
5041
|
}
|
|
4734
5042
|
}
|
|
4735
5043
|
return false;
|
|
@@ -5072,11 +5380,7 @@ function isBlockedSimpleCommand(command, context, mode, options) {
|
|
|
5072
5380
|
}
|
|
5073
5381
|
if (command.redirections.some((redirection) => {
|
|
5074
5382
|
if (redirection.target.type === "Word") {
|
|
5075
|
-
return wordContainsBlockedCommand(
|
|
5076
|
-
redirection.target,
|
|
5077
|
-
context,
|
|
5078
|
-
mode
|
|
5079
|
-
);
|
|
5383
|
+
return wordContainsBlockedCommand(redirection.target, context, mode);
|
|
5080
5384
|
}
|
|
5081
5385
|
if (redirection.target.type === "HereDoc" && redirection.target.content) {
|
|
5082
5386
|
return wordContainsBlockedCommand(
|
|
@@ -5213,10 +5517,8 @@ function wordPartsContainExpansion(parts) {
|
|
|
5213
5517
|
if (part.type === "CommandSubstitution" || part.type === "ParameterExpansion" || part.type === "ArithmeticExpansion") {
|
|
5214
5518
|
return true;
|
|
5215
5519
|
}
|
|
5216
|
-
if (part.type === "DoubleQuoted" &&
|
|
5217
|
-
|
|
5218
|
-
return true;
|
|
5219
|
-
}
|
|
5520
|
+
if (part.type === "DoubleQuoted" && wordPartsContainExpansion(part.parts)) {
|
|
5521
|
+
return true;
|
|
5220
5522
|
}
|
|
5221
5523
|
}
|
|
5222
5524
|
return false;
|
|
@@ -5232,38 +5534,33 @@ function isSqlCommandRequiringRewrite(cmd) {
|
|
|
5232
5534
|
if (!isValidAdapterName(dbName)) return false;
|
|
5233
5535
|
const sqlArgs = cmd.args.slice(2);
|
|
5234
5536
|
if (sqlArgs.length > 1) return true;
|
|
5235
|
-
return sqlArgs.some(
|
|
5236
|
-
(arg) => wordPartsContainExpansion(
|
|
5237
|
-
arg.parts
|
|
5238
|
-
)
|
|
5239
|
-
);
|
|
5537
|
+
return sqlArgs.some((arg) => wordPartsContainExpansion(arg.parts));
|
|
5240
5538
|
}
|
|
5241
5539
|
function extractWordPartText(parts) {
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5540
|
+
return parts.map(wordPartText).join("");
|
|
5541
|
+
}
|
|
5542
|
+
function wordPartText(part) {
|
|
5543
|
+
switch (part.type) {
|
|
5544
|
+
case "Literal":
|
|
5545
|
+
case "SingleQuoted":
|
|
5546
|
+
case "Escaped":
|
|
5547
|
+
return part.value;
|
|
5548
|
+
case "DoubleQuoted":
|
|
5549
|
+
return extractWordPartText(part.parts);
|
|
5550
|
+
case "CommandSubstitution":
|
|
5551
|
+
return part.legacy ? "`" + serialize(part.body).trim() + "`" : "$(" + serialize(part.body).trim() + ")";
|
|
5552
|
+
case "ParameterExpansion":
|
|
5553
|
+
return emitParameterExpansion(part);
|
|
5554
|
+
case "ArithmeticExpansion":
|
|
5555
|
+
return "$((" + (part.expression.originalText ?? "") + "))";
|
|
5556
|
+
default:
|
|
5557
|
+
return "";
|
|
5558
|
+
}
|
|
5261
5559
|
}
|
|
5262
5560
|
function emitParameterExpansion(part) {
|
|
5263
|
-
const parameter = part
|
|
5264
|
-
const operation = part.operation;
|
|
5561
|
+
const { parameter, operation } = part;
|
|
5265
5562
|
if (!operation) return "$" + parameter;
|
|
5266
|
-
if (operation.type === "DefaultValue"
|
|
5563
|
+
if (operation.type === "DefaultValue") {
|
|
5267
5564
|
const fallback = extractWordPartText(operation.word.parts);
|
|
5268
5565
|
const separator = operation.checkEmpty ? ":-" : "-";
|
|
5269
5566
|
return "${" + parameter + separator + fallback + "}";
|
|
@@ -5271,11 +5568,7 @@ function emitParameterExpansion(part) {
|
|
|
5271
5568
|
return "${" + parameter + "}";
|
|
5272
5569
|
}
|
|
5273
5570
|
function extractSqlText(args) {
|
|
5274
|
-
return args.map(
|
|
5275
|
-
(arg) => extractWordPartText(
|
|
5276
|
-
arg.parts
|
|
5277
|
-
)
|
|
5278
|
-
).join(" ");
|
|
5571
|
+
return args.map((arg) => extractWordPartText(arg.parts)).join(" ");
|
|
5279
5572
|
}
|
|
5280
5573
|
function rewriteSqlCommand(cmd, ast) {
|
|
5281
5574
|
const subcommand = asStaticWordText2(cmd.args[0]);
|
|
@@ -5514,8 +5807,10 @@ var Text2Sql = class {
|
|
|
5514
5807
|
if (!Array.isArray(result)) {
|
|
5515
5808
|
throw new Error("adapter.execute must return an array of rows");
|
|
5516
5809
|
}
|
|
5517
|
-
const
|
|
5518
|
-
|
|
5810
|
+
const rows = result;
|
|
5811
|
+
const [first] = rows;
|
|
5812
|
+
const columns = typeof first === "object" && first !== null ? Object.keys(first) : [];
|
|
5813
|
+
return { rows, columns };
|
|
5519
5814
|
}
|
|
5520
5815
|
async #validateWith(adapter, sql) {
|
|
5521
5816
|
const formatted = adapter.format(sql);
|
|
@@ -5679,15 +5974,13 @@ function extractSqlInvocation(command) {
|
|
|
5679
5974
|
return parseSqlQueryInvocation(repairSqlCommand(command));
|
|
5680
5975
|
}
|
|
5681
5976
|
function inputCommand(input) {
|
|
5682
|
-
return input
|
|
5977
|
+
return typeof input === "object" && input !== null && "command" in input ? input.command : void 0;
|
|
5683
5978
|
}
|
|
5684
5979
|
function alreadyValidated(messages, run) {
|
|
5685
5980
|
for (const message of messages ?? []) {
|
|
5686
5981
|
for (const part of message.parts) {
|
|
5687
5982
|
if (!isToolUIPart(part)) continue;
|
|
5688
|
-
const invocation = extractSqlInvocation(
|
|
5689
|
-
inputCommand(part.input)
|
|
5690
|
-
);
|
|
5983
|
+
const invocation = extractSqlInvocation(inputCommand(part.input));
|
|
5691
5984
|
if (invocation?.subcommand === "validate" && invocation.dbName === run.dbName && invocation.sql === run.sql) {
|
|
5692
5985
|
return true;
|
|
5693
5986
|
}
|
|
@@ -5745,10 +6038,12 @@ export {
|
|
|
5745
6038
|
filterRelationshipsByTables,
|
|
5746
6039
|
filterTablesByName,
|
|
5747
6040
|
getTablesWithRelated,
|
|
6041
|
+
groundingFor,
|
|
5748
6042
|
hashConfig,
|
|
5749
6043
|
index,
|
|
5750
6044
|
instructions,
|
|
5751
6045
|
isValidAdapterName,
|
|
6046
|
+
jsonCodec,
|
|
5752
6047
|
matchesFilter,
|
|
5753
6048
|
relationship,
|
|
5754
6049
|
repairSqlCommand,
|