@deepagents/text2sql 7.0.2 → 7.1.1
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 +63 -75
- package/dist/bin/sql.js +82 -599
- package/dist/eval/src/evals/models.d.ts +12 -0
- package/dist/eval/src/evals/models.d.ts.map +1 -0
- package/dist/eval/src/evals/sql-create-context/sql-create-context.eval.d.ts +2 -0
- package/dist/eval/src/evals/sql-create-context/sql-create-context.eval.d.ts.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +920 -706
- package/dist/index.js.map +4 -4
- package/dist/lib/adapter-index.d.ts +0 -2
- package/dist/lib/adapter-index.d.ts.map +1 -1
- 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 +117 -38
- 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 -52
- 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 +255 -503
- 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 +5 -4
- 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/question.agent.d.ts.map +1 -1
- package/dist/lib/agents/sql-transform-plugins.d.ts.map +1 -1
- package/dist/lib/agents/suggestions.agents.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 +6 -6
- package/dist/lib/index-cache.d.ts.map +1 -1
- package/dist/lib/sql-command.d.ts +1 -4
- package/dist/lib/sql-command.d.ts.map +1 -1
- package/dist/lib/sql.d.ts +0 -5
- 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/segmented-context-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/sql-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/persona-generator.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/dist/scripts/scripts/bigquery-test.d.ts +2 -0
- package/dist/scripts/scripts/bigquery-test.d.ts.map +1 -0
- package/package.json +4 -6
- package/dist/lib/index-lock.d.ts +0 -60
- package/dist/lib/index-lock.d.ts.map +0 -1
- package/dist/lib/prompt.d.ts +0 -2
- package/dist/lib/prompt.d.ts.map +0 -1
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 path6 of paths) {
|
|
490
|
+
const rows = path6.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((path6) => `result.${path6}`).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,54 +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);
|
|
1142
|
-
}
|
|
1143
|
-
};
|
|
1144
|
-
|
|
1145
|
-
// packages/text2sql/src/lib/index-lock.ts
|
|
1146
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
1147
|
-
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
1148
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
1149
|
-
import * as path2 from "node:path";
|
|
1150
|
-
import { lock as acquireLock } from "proper-lockfile";
|
|
1151
|
-
var DEFAULT_STALE_MS = 3e4;
|
|
1152
|
-
var DEFAULT_RETRIES = {
|
|
1153
|
-
retries: 10,
|
|
1154
|
-
factor: 2,
|
|
1155
|
-
minTimeout: 100,
|
|
1156
|
-
maxTimeout: 2e3
|
|
1157
|
-
};
|
|
1158
|
-
var FileIndexLock = class {
|
|
1159
|
-
#dir;
|
|
1160
|
-
#namespace;
|
|
1161
|
-
#stale;
|
|
1162
|
-
#retries;
|
|
1163
|
-
constructor(options = {}) {
|
|
1164
|
-
this.#dir = options.dir ?? tmpdir2();
|
|
1165
|
-
this.#namespace = options.namespace;
|
|
1166
|
-
this.#stale = options.stale ?? DEFAULT_STALE_MS;
|
|
1167
|
-
this.#retries = options.retries ?? DEFAULT_RETRIES;
|
|
1168
|
-
}
|
|
1169
|
-
async run(key, fn) {
|
|
1170
|
-
await mkdir2(this.#dir, { recursive: true });
|
|
1171
|
-
const release = await acquireLock(this.#lockPathFor(key), {
|
|
1172
|
-
realpath: false,
|
|
1173
|
-
stale: this.#stale,
|
|
1174
|
-
retries: this.#retries
|
|
1175
|
-
});
|
|
1176
|
-
try {
|
|
1177
|
-
return await fn();
|
|
1178
|
-
} finally {
|
|
1179
|
-
await release().catch(() => {
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
#lockPathFor(key) {
|
|
1184
|
-
const watermark = this.#namespace ? `${this.#namespace}-${key}` : key;
|
|
1185
|
-
const hash2 = createHash2("md5").update(watermark).digest("hex");
|
|
1186
|
-
return path2.join(this.#dir, `text2sql-lock-${hash2}`);
|
|
1199
|
+
return new JsonCache(watermark, isFragmentList, this.#dir);
|
|
1187
1200
|
}
|
|
1188
1201
|
};
|
|
1202
|
+
function isFragmentList(value) {
|
|
1203
|
+
return Array.isArray(value) && value.every((item) => isFragment(item) && isFragmentData(item));
|
|
1204
|
+
}
|
|
1189
1205
|
|
|
1190
1206
|
// packages/text2sql/src/lib/adapter-index.ts
|
|
1191
1207
|
var TEXT2SQL_INDEX_PROGRESS_CHUNK = "data-text2sql-index-progress";
|
|
@@ -1206,7 +1222,6 @@ function databaseNameFragment(name) {
|
|
|
1206
1222
|
var AdapterIndexer = class {
|
|
1207
1223
|
#adapters;
|
|
1208
1224
|
#cache;
|
|
1209
|
-
#lock;
|
|
1210
1225
|
constructor(options) {
|
|
1211
1226
|
const adapterNames = Object.keys(options.adapters);
|
|
1212
1227
|
if (adapterNames.length === 0) {
|
|
@@ -1215,7 +1230,6 @@ var AdapterIndexer = class {
|
|
|
1215
1230
|
validateAdapterNames(adapterNames);
|
|
1216
1231
|
this.#adapters = options.adapters;
|
|
1217
1232
|
this.#cache = options.cache;
|
|
1218
|
-
this.#lock = options.lock;
|
|
1219
1233
|
}
|
|
1220
1234
|
async index(options = {}) {
|
|
1221
1235
|
const progress = timestampProgressHandler(options.onProgress);
|
|
@@ -1273,41 +1287,15 @@ var AdapterIndexer = class {
|
|
|
1273
1287
|
message: `Indexing adapter "${name}"...`
|
|
1274
1288
|
});
|
|
1275
1289
|
const cache = this.#cache;
|
|
1276
|
-
const key = name;
|
|
1277
|
-
const emitCacheHit = () => progress({
|
|
1278
|
-
type: "adapter:cache-hit",
|
|
1279
|
-
adapter: name,
|
|
1280
|
-
message: `Using cached index for adapter "${name}".`,
|
|
1281
|
-
cached: true
|
|
1282
|
-
});
|
|
1283
|
-
const emitCacheMiss = () => progress({
|
|
1284
|
-
type: "adapter:cache-miss",
|
|
1285
|
-
adapter: name,
|
|
1286
|
-
message: `No cached index for adapter "${name}".`,
|
|
1287
|
-
cached: false
|
|
1288
|
-
});
|
|
1289
|
-
const introspect = async () => {
|
|
1290
|
-
const ctx = createGroundingContext({
|
|
1291
|
-
onProgress: (event) => progress(adapterProgressEvent(name, event))
|
|
1292
|
-
});
|
|
1293
|
-
const fragments = await adapter.introspect(ctx);
|
|
1294
|
-
await cache?.write(key, fragments);
|
|
1295
|
-
return fragments;
|
|
1296
|
-
};
|
|
1297
|
-
let servedFromCache = false;
|
|
1298
|
-
const populate = async () => {
|
|
1299
|
-
const recheck = await cache?.read(key);
|
|
1300
|
-
if (recheck) {
|
|
1301
|
-
servedFromCache = true;
|
|
1302
|
-
return recheck;
|
|
1303
|
-
}
|
|
1304
|
-
if (cache) emitCacheMiss();
|
|
1305
|
-
return introspect();
|
|
1306
|
-
};
|
|
1307
1290
|
try {
|
|
1308
|
-
const cached = await cache?.read(
|
|
1291
|
+
const cached = await cache?.read(name);
|
|
1309
1292
|
if (cached) {
|
|
1310
|
-
|
|
1293
|
+
progress({
|
|
1294
|
+
type: "adapter:cache-hit",
|
|
1295
|
+
adapter: name,
|
|
1296
|
+
message: `Using cached index for adapter "${name}".`,
|
|
1297
|
+
cached: true
|
|
1298
|
+
});
|
|
1311
1299
|
progress({
|
|
1312
1300
|
type: "adapter:end",
|
|
1313
1301
|
adapter: name,
|
|
@@ -1316,13 +1304,24 @@ var AdapterIndexer = class {
|
|
|
1316
1304
|
});
|
|
1317
1305
|
return cached;
|
|
1318
1306
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1307
|
+
if (cache) {
|
|
1308
|
+
progress({
|
|
1309
|
+
type: "adapter:cache-miss",
|
|
1310
|
+
adapter: name,
|
|
1311
|
+
message: `No cached index for adapter "${name}".`,
|
|
1312
|
+
cached: false
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
const ctx = createGroundingContext({
|
|
1316
|
+
onProgress: (event) => progress(adapterProgressEvent(name, event))
|
|
1317
|
+
});
|
|
1318
|
+
const fragments = await adapter.introspect(ctx);
|
|
1319
|
+
await cache?.write(name, fragments);
|
|
1321
1320
|
progress({
|
|
1322
1321
|
type: "adapter:end",
|
|
1323
1322
|
adapter: name,
|
|
1324
1323
|
message: `Finished indexing adapter "${name}".`,
|
|
1325
|
-
cached:
|
|
1324
|
+
cached: false
|
|
1326
1325
|
});
|
|
1327
1326
|
return fragments;
|
|
1328
1327
|
} catch (error) {
|
|
@@ -1368,16 +1367,30 @@ function errorMessage(error) {
|
|
|
1368
1367
|
}
|
|
1369
1368
|
|
|
1370
1369
|
// packages/text2sql/src/lib/checkpoint.ts
|
|
1371
|
-
import { createHash as
|
|
1370
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
1372
1371
|
import { existsSync as existsSync2, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1373
1372
|
import pLimit from "p-limit";
|
|
1373
|
+
import z4 from "zod";
|
|
1374
|
+
function jsonCodec(schema) {
|
|
1375
|
+
return { encode: (value) => value, decode: (stored) => schema.parse(stored) };
|
|
1376
|
+
}
|
|
1377
|
+
var pointData = z4.object({
|
|
1378
|
+
committed: z4.boolean(),
|
|
1379
|
+
entries: z4.array(
|
|
1380
|
+
z4.object({ inputHash: z4.string(), output: z4.unknown().optional() })
|
|
1381
|
+
)
|
|
1382
|
+
});
|
|
1383
|
+
var checkpointFile = z4.object({
|
|
1384
|
+
configHash: z4.string().optional(),
|
|
1385
|
+
points: z4.record(z4.string(), pointData)
|
|
1386
|
+
});
|
|
1374
1387
|
var Checkpoint = class _Checkpoint {
|
|
1375
1388
|
points;
|
|
1376
1389
|
path;
|
|
1377
1390
|
configHash;
|
|
1378
|
-
constructor(
|
|
1391
|
+
constructor(path6, configHash, points) {
|
|
1379
1392
|
this.points = points;
|
|
1380
|
-
this.path =
|
|
1393
|
+
this.path = path6;
|
|
1381
1394
|
this.configHash = configHash;
|
|
1382
1395
|
}
|
|
1383
1396
|
/**
|
|
@@ -1385,29 +1398,29 @@ var Checkpoint = class _Checkpoint {
|
|
|
1385
1398
|
* Handles corrupted files and config changes gracefully.
|
|
1386
1399
|
*/
|
|
1387
1400
|
static async load(options) {
|
|
1388
|
-
const { path:
|
|
1389
|
-
if (existsSync2(
|
|
1401
|
+
const { path: path6, configHash } = options;
|
|
1402
|
+
if (existsSync2(path6)) {
|
|
1390
1403
|
try {
|
|
1391
|
-
const content = readFileSync(
|
|
1392
|
-
const file = JSON.parse(content);
|
|
1404
|
+
const content = readFileSync(path6, "utf-8");
|
|
1405
|
+
const file = checkpointFile.parse(JSON.parse(content));
|
|
1393
1406
|
if (configHash && file.configHash && file.configHash !== configHash) {
|
|
1394
1407
|
console.log("\u26A0 Config changed, starting fresh");
|
|
1395
|
-
return new _Checkpoint(
|
|
1408
|
+
return new _Checkpoint(path6, configHash, {});
|
|
1396
1409
|
}
|
|
1397
|
-
const points = file.points
|
|
1410
|
+
const points = file.points;
|
|
1398
1411
|
const totalEntries = Object.values(points).reduce(
|
|
1399
1412
|
(sum, p) => sum + p.entries.length,
|
|
1400
1413
|
0
|
|
1401
1414
|
);
|
|
1402
1415
|
console.log(`\u2713 Resuming from checkpoint (${totalEntries} entries)`);
|
|
1403
|
-
return new _Checkpoint(
|
|
1416
|
+
return new _Checkpoint(path6, configHash, points);
|
|
1404
1417
|
} catch {
|
|
1405
1418
|
console.log("\u26A0 Checkpoint corrupted, starting fresh");
|
|
1406
|
-
return new _Checkpoint(
|
|
1419
|
+
return new _Checkpoint(path6, configHash, {});
|
|
1407
1420
|
}
|
|
1408
1421
|
}
|
|
1409
1422
|
console.log("Starting new checkpoint");
|
|
1410
|
-
return new _Checkpoint(
|
|
1423
|
+
return new _Checkpoint(path6, configHash, {});
|
|
1411
1424
|
}
|
|
1412
1425
|
/**
|
|
1413
1426
|
* Run a single computation with checkpointing.
|
|
@@ -1415,27 +1428,20 @@ var Checkpoint = class _Checkpoint {
|
|
|
1415
1428
|
*
|
|
1416
1429
|
* @param key - Unique identifier for this computation
|
|
1417
1430
|
* @param computation - Async function that produces the value
|
|
1418
|
-
* @param codec -
|
|
1431
|
+
* @param codec - Codec that stores the value and restores it on resume
|
|
1419
1432
|
*/
|
|
1420
1433
|
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
|
-
);
|
|
1434
|
+
return this.point(key, codec).through("single", computation);
|
|
1430
1435
|
}
|
|
1431
1436
|
/**
|
|
1432
1437
|
* Create a resumable checkpoint point for iterative operations.
|
|
1433
1438
|
*
|
|
1434
1439
|
* @param step - Unique identifier for this checkpoint point
|
|
1440
|
+
* @param codec - Codec that stores each output and restores it on resume
|
|
1435
1441
|
*/
|
|
1436
|
-
point(step) {
|
|
1442
|
+
point(step, codec) {
|
|
1437
1443
|
this.points[step] ??= { committed: false, entries: [] };
|
|
1438
|
-
return new Point(this.points[step], () => this.save());
|
|
1444
|
+
return new Point(this.points[step], codec, () => this.save());
|
|
1439
1445
|
}
|
|
1440
1446
|
/**
|
|
1441
1447
|
* Process each input with automatic checkpointing and concurrency.
|
|
@@ -1443,11 +1449,12 @@ var Checkpoint = class _Checkpoint {
|
|
|
1443
1449
|
* @param step - Unique identifier for this checkpoint
|
|
1444
1450
|
* @param inputs - Items to process
|
|
1445
1451
|
* @param process - Function to process each input
|
|
1452
|
+
* @param codec - Codec that stores each output and restores it on resume
|
|
1446
1453
|
* @param options - Optional settings like concurrency
|
|
1447
1454
|
* @returns All outputs (use `.flat()` if outputs are arrays)
|
|
1448
1455
|
*/
|
|
1449
|
-
async each(step, inputs, process, options) {
|
|
1450
|
-
const point = this.point(step);
|
|
1456
|
+
async each(step, inputs, process, codec, options) {
|
|
1457
|
+
const point = this.point(step, codec);
|
|
1451
1458
|
const limit = pLimit(options?.concurrency ?? 1);
|
|
1452
1459
|
const inputArray = Array.from(inputs);
|
|
1453
1460
|
await Promise.all(
|
|
@@ -1464,11 +1471,11 @@ var Checkpoint = class _Checkpoint {
|
|
|
1464
1471
|
*/
|
|
1465
1472
|
getOutput() {
|
|
1466
1473
|
const output = {};
|
|
1467
|
-
for (const [key,
|
|
1468
|
-
if (
|
|
1469
|
-
output[key] =
|
|
1474
|
+
for (const [key, pointData2] of Object.entries(this.points)) {
|
|
1475
|
+
if (pointData2.entries.length === 1) {
|
|
1476
|
+
output[key] = pointData2.entries[0].output;
|
|
1470
1477
|
} else {
|
|
1471
|
-
output[key] =
|
|
1478
|
+
output[key] = pointData2.entries.map((e) => e.output);
|
|
1472
1479
|
}
|
|
1473
1480
|
}
|
|
1474
1481
|
return output;
|
|
@@ -1489,34 +1496,35 @@ var Checkpoint = class _Checkpoint {
|
|
|
1489
1496
|
}
|
|
1490
1497
|
};
|
|
1491
1498
|
function hash(value) {
|
|
1492
|
-
return
|
|
1499
|
+
return createHash2("md5").update(JSON.stringify(value)).digest("hex");
|
|
1493
1500
|
}
|
|
1494
1501
|
var Point = class {
|
|
1495
|
-
#
|
|
1502
|
+
#stored;
|
|
1496
1503
|
data;
|
|
1504
|
+
codec;
|
|
1497
1505
|
persist;
|
|
1498
|
-
constructor(data, persist) {
|
|
1499
|
-
this.#
|
|
1500
|
-
data.entries.map((e) => [e.inputHash, e.output])
|
|
1501
|
-
);
|
|
1506
|
+
constructor(data, codec, persist) {
|
|
1507
|
+
this.#stored = new Map(data.entries.map((e) => [e.inputHash, e.output]));
|
|
1502
1508
|
this.data = data;
|
|
1509
|
+
this.codec = codec;
|
|
1503
1510
|
this.persist = persist;
|
|
1504
1511
|
}
|
|
1505
1512
|
/**
|
|
1506
1513
|
* Execute computation if input wasn't processed before.
|
|
1507
|
-
* Returns
|
|
1514
|
+
* Returns the decoded stored output if input hash exists, otherwise
|
|
1515
|
+
* executes, saves the encoded output, and returns the computed value.
|
|
1508
1516
|
*/
|
|
1509
|
-
async through(input, compute
|
|
1517
|
+
async through(input, compute) {
|
|
1510
1518
|
const inputHash = hash(input);
|
|
1511
|
-
if (this.#
|
|
1512
|
-
|
|
1513
|
-
return codec ? codec.decode(cached) : cached;
|
|
1519
|
+
if (this.#stored.has(inputHash)) {
|
|
1520
|
+
return this.codec.decode(this.#stored.get(inputHash));
|
|
1514
1521
|
}
|
|
1515
|
-
const
|
|
1522
|
+
const value = await compute();
|
|
1523
|
+
const output = this.codec.encode(value);
|
|
1516
1524
|
this.data.entries.push({ inputHash, output });
|
|
1517
|
-
this.#
|
|
1525
|
+
this.#stored.set(inputHash, output);
|
|
1518
1526
|
await this.persist();
|
|
1519
|
-
return
|
|
1527
|
+
return value;
|
|
1520
1528
|
}
|
|
1521
1529
|
/** Mark this point as complete. */
|
|
1522
1530
|
async commit() {
|
|
@@ -1529,21 +1537,50 @@ var Point = class {
|
|
|
1529
1537
|
}
|
|
1530
1538
|
/** Get all outputs from this point. */
|
|
1531
1539
|
values() {
|
|
1532
|
-
return this.data.entries.map((e) => e.output);
|
|
1540
|
+
return this.data.entries.map((e) => this.codec.decode(e.output));
|
|
1533
1541
|
}
|
|
1534
1542
|
};
|
|
1535
1543
|
function hashConfig(config) {
|
|
1536
|
-
return
|
|
1544
|
+
return createHash2("md5").update(JSON.stringify(config)).digest("hex");
|
|
1537
1545
|
}
|
|
1538
1546
|
|
|
1539
1547
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1540
|
-
import * as
|
|
1548
|
+
import * as path2 from "node:path";
|
|
1541
1549
|
import { DatabaseSync } from "node:sqlite";
|
|
1550
|
+
import z6 from "zod";
|
|
1551
|
+
|
|
1552
|
+
// packages/text2sql/src/lib/fs/columns.ts
|
|
1553
|
+
import z5 from "zod";
|
|
1554
|
+
var entryType = z5.enum(["file", "directory", "symlink"]);
|
|
1555
|
+
var bigintColumn = z5.union([z5.number(), z5.string().regex(/^-?\d+$/)]).transform(Number);
|
|
1542
1556
|
|
|
1543
1557
|
// packages/text2sql/src/lib/fs/sqlite/ddl.sqlite-fs.sql
|
|
1544
1558
|
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
1559
|
|
|
1546
1560
|
// packages/text2sql/src/lib/fs/sqlite/sqlite-fs.ts
|
|
1561
|
+
var entryRow = z6.object({
|
|
1562
|
+
path: z6.string(),
|
|
1563
|
+
type: entryType,
|
|
1564
|
+
mode: z6.number(),
|
|
1565
|
+
size: z6.number(),
|
|
1566
|
+
mtime: z6.number(),
|
|
1567
|
+
symlinkTarget: z6.string().nullable()
|
|
1568
|
+
});
|
|
1569
|
+
var typeRow = entryRow.pick({ type: true });
|
|
1570
|
+
var pathRow = entryRow.pick({ path: true });
|
|
1571
|
+
var pathTypeRow = entryRow.pick({ path: true, type: true });
|
|
1572
|
+
var linkRow = z6.discriminatedUnion("type", [
|
|
1573
|
+
z6.object({ type: z6.literal("symlink"), symlinkTarget: z6.string() }),
|
|
1574
|
+
z6.object({
|
|
1575
|
+
type: z6.enum(["file", "directory"]),
|
|
1576
|
+
symlinkTarget: z6.string().nullable()
|
|
1577
|
+
})
|
|
1578
|
+
]);
|
|
1579
|
+
var chunkRow = z6.object({
|
|
1580
|
+
chunkIndex: z6.number(),
|
|
1581
|
+
data: z6.instanceof(Uint8Array)
|
|
1582
|
+
});
|
|
1583
|
+
var dataRow = chunkRow.pick({ data: true });
|
|
1547
1584
|
var SqliteFs = class {
|
|
1548
1585
|
#db;
|
|
1549
1586
|
#statements = /* @__PURE__ */ new Map();
|
|
@@ -1585,7 +1622,7 @@ var SqliteFs = class {
|
|
|
1585
1622
|
const segments = p.split("/").filter(Boolean);
|
|
1586
1623
|
let currentPath = "/";
|
|
1587
1624
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
1588
|
-
currentPath =
|
|
1625
|
+
currentPath = path2.posix.join(currentPath, segments[i]);
|
|
1589
1626
|
const exists = this.#stmt("SELECT 1 FROM fs_entries WHERE path = ?").get(
|
|
1590
1627
|
currentPath
|
|
1591
1628
|
);
|
|
@@ -1606,7 +1643,7 @@ var SqliteFs = class {
|
|
|
1606
1643
|
return stmt;
|
|
1607
1644
|
}
|
|
1608
1645
|
#normalizeRoot(root) {
|
|
1609
|
-
return
|
|
1646
|
+
return path2.posix.resolve("/", root.trim());
|
|
1610
1647
|
}
|
|
1611
1648
|
#prefixPath(p) {
|
|
1612
1649
|
if (!this.#root) {
|
|
@@ -1615,7 +1652,7 @@ var SqliteFs = class {
|
|
|
1615
1652
|
if (p === "/") {
|
|
1616
1653
|
return this.#root;
|
|
1617
1654
|
}
|
|
1618
|
-
return
|
|
1655
|
+
return path2.posix.join(this.#root, p);
|
|
1619
1656
|
}
|
|
1620
1657
|
#unprefixPath(p) {
|
|
1621
1658
|
if (!this.#root) {
|
|
@@ -1636,23 +1673,26 @@ var SqliteFs = class {
|
|
|
1636
1673
|
this.#db.exec("COMMIT");
|
|
1637
1674
|
return result;
|
|
1638
1675
|
} catch (error) {
|
|
1639
|
-
|
|
1676
|
+
try {
|
|
1677
|
+
this.#db.exec("ROLLBACK");
|
|
1678
|
+
} catch {
|
|
1679
|
+
}
|
|
1640
1680
|
throw error;
|
|
1641
1681
|
}
|
|
1642
1682
|
}
|
|
1643
1683
|
#normalizePath(p) {
|
|
1644
|
-
return
|
|
1684
|
+
return path2.posix.resolve("/", p);
|
|
1645
1685
|
}
|
|
1646
1686
|
#dirname(p) {
|
|
1647
|
-
const dir =
|
|
1687
|
+
const dir = path2.posix.dirname(p);
|
|
1648
1688
|
return dir === "" ? "/" : dir;
|
|
1649
1689
|
}
|
|
1650
1690
|
#ensureParentExists(filePath) {
|
|
1651
1691
|
const parent = this.#dirname(filePath);
|
|
1652
1692
|
const rootPath = this.#root || "/";
|
|
1653
1693
|
if (parent === rootPath || parent === "/") return;
|
|
1654
|
-
const entry =
|
|
1655
|
-
parent
|
|
1694
|
+
const entry = typeRow.optional().parse(
|
|
1695
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(parent)
|
|
1656
1696
|
);
|
|
1657
1697
|
if (!entry) {
|
|
1658
1698
|
this.#ensureParentExists(parent);
|
|
@@ -1676,10 +1716,19 @@ var SqliteFs = class {
|
|
|
1676
1716
|
).run(filePath, Math.floor(i / this.#chunkSize), chunk);
|
|
1677
1717
|
}
|
|
1678
1718
|
}
|
|
1719
|
+
#chunks(filePath) {
|
|
1720
|
+
return z6.array(chunkRow).parse(
|
|
1721
|
+
this.#stmt("SELECT chunkIndex, data FROM fs_chunks WHERE path = ?").all(
|
|
1722
|
+
filePath
|
|
1723
|
+
)
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1679
1726
|
#readChunks(filePath) {
|
|
1680
|
-
const rows =
|
|
1681
|
-
|
|
1682
|
-
|
|
1727
|
+
const rows = z6.array(dataRow).parse(
|
|
1728
|
+
this.#stmt(
|
|
1729
|
+
"SELECT data FROM fs_chunks WHERE path = ? ORDER BY chunkIndex"
|
|
1730
|
+
).all(filePath)
|
|
1731
|
+
);
|
|
1683
1732
|
if (rows.length === 0) {
|
|
1684
1733
|
return new Uint8Array(0);
|
|
1685
1734
|
}
|
|
@@ -1696,9 +1745,11 @@ var SqliteFs = class {
|
|
|
1696
1745
|
if (seen.has(p)) {
|
|
1697
1746
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
1698
1747
|
}
|
|
1699
|
-
const entry =
|
|
1700
|
-
|
|
1701
|
-
|
|
1748
|
+
const entry = linkRow.optional().parse(
|
|
1749
|
+
this.#stmt(
|
|
1750
|
+
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
1751
|
+
).get(p)
|
|
1752
|
+
);
|
|
1702
1753
|
if (!entry) {
|
|
1703
1754
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
1704
1755
|
}
|
|
@@ -1707,7 +1758,7 @@ var SqliteFs = class {
|
|
|
1707
1758
|
}
|
|
1708
1759
|
seen.add(p);
|
|
1709
1760
|
const target = this.#normalizePath(
|
|
1710
|
-
|
|
1761
|
+
path2.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
1711
1762
|
);
|
|
1712
1763
|
return this.#resolveSymlink(target, seen);
|
|
1713
1764
|
}
|
|
@@ -1715,8 +1766,7 @@ var SqliteFs = class {
|
|
|
1715
1766
|
if (content instanceof Uint8Array) {
|
|
1716
1767
|
return content;
|
|
1717
1768
|
}
|
|
1718
|
-
|
|
1719
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
1769
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
1720
1770
|
}
|
|
1721
1771
|
// ============================================================================
|
|
1722
1772
|
// IFileSystem Implementation
|
|
@@ -1725,8 +1775,8 @@ var SqliteFs = class {
|
|
|
1725
1775
|
const normalized = this.#normalizePath(filePath);
|
|
1726
1776
|
const prefixed = this.#prefixPath(normalized);
|
|
1727
1777
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1728
|
-
const entry =
|
|
1729
|
-
resolved
|
|
1778
|
+
const entry = typeRow.optional().parse(
|
|
1779
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1730
1780
|
);
|
|
1731
1781
|
if (!entry) {
|
|
1732
1782
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1742,8 +1792,8 @@ var SqliteFs = class {
|
|
|
1742
1792
|
const normalized = this.#normalizePath(filePath);
|
|
1743
1793
|
const prefixed = this.#prefixPath(normalized);
|
|
1744
1794
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1745
|
-
const entry =
|
|
1746
|
-
resolved
|
|
1795
|
+
const entry = typeRow.optional().parse(
|
|
1796
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1747
1797
|
);
|
|
1748
1798
|
if (!entry) {
|
|
1749
1799
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1778,9 +1828,11 @@ var SqliteFs = class {
|
|
|
1778
1828
|
const newData = this.#toUint8Array(content, encoding);
|
|
1779
1829
|
this.#useTransaction(() => {
|
|
1780
1830
|
this.#ensureParentExists(prefixed);
|
|
1781
|
-
const entry =
|
|
1782
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1783
|
-
|
|
1831
|
+
const entry = typeRow.optional().parse(
|
|
1832
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1833
|
+
prefixed
|
|
1834
|
+
)
|
|
1835
|
+
);
|
|
1784
1836
|
if (entry && entry.type !== "file") {
|
|
1785
1837
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
1786
1838
|
}
|
|
@@ -1810,8 +1862,8 @@ var SqliteFs = class {
|
|
|
1810
1862
|
const normalized = this.#normalizePath(filePath);
|
|
1811
1863
|
const prefixed = this.#prefixPath(normalized);
|
|
1812
1864
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1813
|
-
const entry =
|
|
1814
|
-
resolved
|
|
1865
|
+
const entry = entryRow.optional().parse(
|
|
1866
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(resolved)
|
|
1815
1867
|
);
|
|
1816
1868
|
if (!entry) {
|
|
1817
1869
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1829,8 +1881,8 @@ var SqliteFs = class {
|
|
|
1829
1881
|
async lstat(filePath) {
|
|
1830
1882
|
const normalized = this.#normalizePath(filePath);
|
|
1831
1883
|
const prefixed = this.#prefixPath(normalized);
|
|
1832
|
-
const entry =
|
|
1833
|
-
prefixed
|
|
1884
|
+
const entry = entryRow.optional().parse(
|
|
1885
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1834
1886
|
);
|
|
1835
1887
|
if (!entry) {
|
|
1836
1888
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -1847,9 +1899,9 @@ var SqliteFs = class {
|
|
|
1847
1899
|
async mkdir(dirPath, options) {
|
|
1848
1900
|
const normalized = this.#normalizePath(dirPath);
|
|
1849
1901
|
const prefixed = this.#prefixPath(normalized);
|
|
1850
|
-
const existing =
|
|
1851
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1852
|
-
)
|
|
1902
|
+
const existing = typeRow.optional().parse(
|
|
1903
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1904
|
+
);
|
|
1853
1905
|
if (existing) {
|
|
1854
1906
|
if (options?.recursive) {
|
|
1855
1907
|
return;
|
|
@@ -1859,14 +1911,16 @@ var SqliteFs = class {
|
|
|
1859
1911
|
this.#useTransaction(() => {
|
|
1860
1912
|
if (options?.recursive) {
|
|
1861
1913
|
const rootPath = this.#root || "/";
|
|
1862
|
-
const relativePath =
|
|
1914
|
+
const relativePath = path2.posix.relative(rootPath, prefixed);
|
|
1863
1915
|
const segments = relativePath.split("/").filter(Boolean);
|
|
1864
1916
|
let currentPath = rootPath;
|
|
1865
1917
|
for (const segment of segments) {
|
|
1866
|
-
currentPath =
|
|
1867
|
-
const exists =
|
|
1868
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1869
|
-
|
|
1918
|
+
currentPath = path2.posix.join(currentPath, segment);
|
|
1919
|
+
const exists = typeRow.optional().parse(
|
|
1920
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1921
|
+
currentPath
|
|
1922
|
+
)
|
|
1923
|
+
);
|
|
1870
1924
|
if (!exists) {
|
|
1871
1925
|
this.#stmt(
|
|
1872
1926
|
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
@@ -1878,9 +1932,11 @@ var SqliteFs = class {
|
|
|
1878
1932
|
}
|
|
1879
1933
|
} else {
|
|
1880
1934
|
const parent = this.#dirname(prefixed);
|
|
1881
|
-
const parentEntry =
|
|
1882
|
-
"SELECT type FROM fs_entries WHERE path = ?"
|
|
1883
|
-
|
|
1935
|
+
const parentEntry = typeRow.optional().parse(
|
|
1936
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(
|
|
1937
|
+
parent
|
|
1938
|
+
)
|
|
1939
|
+
);
|
|
1884
1940
|
if (!parentEntry) {
|
|
1885
1941
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
1886
1942
|
}
|
|
@@ -1898,8 +1954,8 @@ var SqliteFs = class {
|
|
|
1898
1954
|
const normalized = this.#normalizePath(dirPath);
|
|
1899
1955
|
const prefixed = this.#prefixPath(normalized);
|
|
1900
1956
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1901
|
-
const entry =
|
|
1902
|
-
resolved
|
|
1957
|
+
const entry = typeRow.optional().parse(
|
|
1958
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1903
1959
|
);
|
|
1904
1960
|
if (!entry) {
|
|
1905
1961
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1908,20 +1964,22 @@ var SqliteFs = class {
|
|
|
1908
1964
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
1909
1965
|
}
|
|
1910
1966
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1911
|
-
const rows =
|
|
1912
|
-
|
|
1967
|
+
const rows = z6.array(pathRow).parse(
|
|
1968
|
+
this.#stmt(
|
|
1969
|
+
`SELECT path FROM fs_entries
|
|
1913
1970
|
WHERE path LIKE ? || '%'
|
|
1914
1971
|
AND path != ?
|
|
1915
1972
|
AND path NOT LIKE ? || '%/%'`
|
|
1916
|
-
|
|
1917
|
-
|
|
1973
|
+
).all(prefix, resolved, prefix)
|
|
1974
|
+
);
|
|
1975
|
+
return rows.map((row) => path2.posix.basename(row.path));
|
|
1918
1976
|
}
|
|
1919
1977
|
async readdirWithFileTypes(dirPath) {
|
|
1920
1978
|
const normalized = this.#normalizePath(dirPath);
|
|
1921
1979
|
const prefixed = this.#prefixPath(normalized);
|
|
1922
1980
|
const resolved = this.#resolveSymlink(prefixed);
|
|
1923
|
-
const entry =
|
|
1924
|
-
resolved
|
|
1981
|
+
const entry = typeRow.optional().parse(
|
|
1982
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(resolved)
|
|
1925
1983
|
);
|
|
1926
1984
|
if (!entry) {
|
|
1927
1985
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
@@ -1930,14 +1988,16 @@ var SqliteFs = class {
|
|
|
1930
1988
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
1931
1989
|
}
|
|
1932
1990
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
1933
|
-
const rows =
|
|
1934
|
-
|
|
1991
|
+
const rows = z6.array(pathTypeRow).parse(
|
|
1992
|
+
this.#stmt(
|
|
1993
|
+
`SELECT path, type FROM fs_entries
|
|
1935
1994
|
WHERE path LIKE ? || '%'
|
|
1936
1995
|
AND path != ?
|
|
1937
1996
|
AND path NOT LIKE ? || '%/%'`
|
|
1938
|
-
|
|
1997
|
+
).all(prefix, resolved, prefix)
|
|
1998
|
+
);
|
|
1939
1999
|
return rows.map((row) => ({
|
|
1940
|
-
name:
|
|
2000
|
+
name: path2.posix.basename(row.path),
|
|
1941
2001
|
isFile: row.type === "file",
|
|
1942
2002
|
isDirectory: row.type === "directory",
|
|
1943
2003
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -1946,8 +2006,8 @@ var SqliteFs = class {
|
|
|
1946
2006
|
async rm(filePath, options) {
|
|
1947
2007
|
const normalized = this.#normalizePath(filePath);
|
|
1948
2008
|
const prefixed = this.#prefixPath(normalized);
|
|
1949
|
-
const entry =
|
|
1950
|
-
prefixed
|
|
2009
|
+
const entry = typeRow.optional().parse(
|
|
2010
|
+
this.#stmt("SELECT type FROM fs_entries WHERE path = ?").get(prefixed)
|
|
1951
2011
|
);
|
|
1952
2012
|
if (!entry) {
|
|
1953
2013
|
if (options?.force) {
|
|
@@ -1976,8 +2036,8 @@ var SqliteFs = class {
|
|
|
1976
2036
|
const destNormalized = this.#normalizePath(dest);
|
|
1977
2037
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
1978
2038
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
1979
|
-
const srcEntry =
|
|
1980
|
-
srcPrefixed
|
|
2039
|
+
const srcEntry = entryRow.optional().parse(
|
|
2040
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
1981
2041
|
);
|
|
1982
2042
|
if (!srcEntry) {
|
|
1983
2043
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
@@ -1988,12 +2048,14 @@ var SqliteFs = class {
|
|
|
1988
2048
|
this.#useTransaction(() => {
|
|
1989
2049
|
this.#ensureParentExists(destPrefixed);
|
|
1990
2050
|
if (srcEntry.type === "directory") {
|
|
1991
|
-
const allEntries =
|
|
1992
|
-
|
|
1993
|
-
|
|
2051
|
+
const allEntries = z6.array(entryRow).parse(
|
|
2052
|
+
this.#stmt(
|
|
2053
|
+
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%'`
|
|
2054
|
+
).all(srcPrefixed, srcPrefixed)
|
|
2055
|
+
);
|
|
1994
2056
|
for (const entry of allEntries) {
|
|
1995
|
-
const relativePath =
|
|
1996
|
-
const newPath =
|
|
2057
|
+
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2058
|
+
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
1997
2059
|
this.#stmt(
|
|
1998
2060
|
`INSERT OR REPLACE INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
1999
2061
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -2006,9 +2068,7 @@ var SqliteFs = class {
|
|
|
2006
2068
|
entry.symlinkTarget
|
|
2007
2069
|
);
|
|
2008
2070
|
if (entry.type === "file") {
|
|
2009
|
-
const chunks = this.#
|
|
2010
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2011
|
-
).all(entry.path);
|
|
2071
|
+
const chunks = this.#chunks(entry.path);
|
|
2012
2072
|
for (const chunk of chunks) {
|
|
2013
2073
|
this.#stmt(
|
|
2014
2074
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2029,9 +2089,7 @@ var SqliteFs = class {
|
|
|
2029
2089
|
srcEntry.symlinkTarget
|
|
2030
2090
|
);
|
|
2031
2091
|
if (srcEntry.type === "file") {
|
|
2032
|
-
const chunks = this.#
|
|
2033
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2034
|
-
).all(srcPrefixed);
|
|
2092
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2035
2093
|
this.#stmt("DELETE FROM fs_chunks WHERE path = ?").run(destPrefixed);
|
|
2036
2094
|
for (const chunk of chunks) {
|
|
2037
2095
|
this.#stmt(
|
|
@@ -2047,8 +2105,8 @@ var SqliteFs = class {
|
|
|
2047
2105
|
const destNormalized = this.#normalizePath(dest);
|
|
2048
2106
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2049
2107
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2050
|
-
const srcEntry =
|
|
2051
|
-
srcPrefixed
|
|
2108
|
+
const srcEntry = entryRow.optional().parse(
|
|
2109
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
2052
2110
|
);
|
|
2053
2111
|
if (!srcEntry) {
|
|
2054
2112
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
@@ -2056,12 +2114,14 @@ var SqliteFs = class {
|
|
|
2056
2114
|
this.#useTransaction(() => {
|
|
2057
2115
|
this.#ensureParentExists(destPrefixed);
|
|
2058
2116
|
if (srcEntry.type === "directory") {
|
|
2059
|
-
const allEntries =
|
|
2060
|
-
|
|
2061
|
-
|
|
2117
|
+
const allEntries = z6.array(entryRow).parse(
|
|
2118
|
+
this.#stmt(
|
|
2119
|
+
`SELECT * FROM fs_entries WHERE path = ? OR path LIKE ? || '/%' ORDER BY path DESC`
|
|
2120
|
+
).all(srcPrefixed, srcPrefixed)
|
|
2121
|
+
);
|
|
2062
2122
|
for (const entry of [...allEntries].reverse()) {
|
|
2063
|
-
const relativePath =
|
|
2064
|
-
const newPath =
|
|
2123
|
+
const relativePath = path2.posix.relative(srcPrefixed, entry.path);
|
|
2124
|
+
const newPath = path2.posix.join(destPrefixed, relativePath);
|
|
2065
2125
|
this.#stmt(
|
|
2066
2126
|
`INSERT INTO fs_entries (path, type, mode, size, mtime, symlinkTarget)
|
|
2067
2127
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
@@ -2074,9 +2134,7 @@ var SqliteFs = class {
|
|
|
2074
2134
|
entry.symlinkTarget
|
|
2075
2135
|
);
|
|
2076
2136
|
if (entry.type === "file") {
|
|
2077
|
-
const chunks = this.#
|
|
2078
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2079
|
-
).all(entry.path);
|
|
2137
|
+
const chunks = this.#chunks(entry.path);
|
|
2080
2138
|
for (const chunk of chunks) {
|
|
2081
2139
|
this.#stmt(
|
|
2082
2140
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2100,9 +2158,7 @@ var SqliteFs = class {
|
|
|
2100
2158
|
srcEntry.symlinkTarget
|
|
2101
2159
|
);
|
|
2102
2160
|
if (srcEntry.type === "file") {
|
|
2103
|
-
const chunks = this.#
|
|
2104
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2105
|
-
).all(srcPrefixed);
|
|
2161
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2106
2162
|
for (const chunk of chunks) {
|
|
2107
2163
|
this.#stmt(
|
|
2108
2164
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2114,12 +2170,10 @@ var SqliteFs = class {
|
|
|
2114
2170
|
});
|
|
2115
2171
|
}
|
|
2116
2172
|
resolvePath(base, relativePath) {
|
|
2117
|
-
return
|
|
2173
|
+
return path2.posix.resolve(base, relativePath);
|
|
2118
2174
|
}
|
|
2119
2175
|
getAllPaths() {
|
|
2120
|
-
const rows = this.#stmt(
|
|
2121
|
-
"SELECT path FROM fs_entries ORDER BY path"
|
|
2122
|
-
).all();
|
|
2176
|
+
const rows = z6.array(pathRow).parse(this.#stmt("SELECT path FROM fs_entries ORDER BY path").all());
|
|
2123
2177
|
return rows.map((row) => row.path);
|
|
2124
2178
|
}
|
|
2125
2179
|
async realpath(filePath) {
|
|
@@ -2177,8 +2231,8 @@ var SqliteFs = class {
|
|
|
2177
2231
|
const destNormalized = this.#normalizePath(newPath);
|
|
2178
2232
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2179
2233
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2180
|
-
const srcEntry =
|
|
2181
|
-
srcPrefixed
|
|
2234
|
+
const srcEntry = entryRow.optional().parse(
|
|
2235
|
+
this.#stmt("SELECT * FROM fs_entries WHERE path = ?").get(srcPrefixed)
|
|
2182
2236
|
);
|
|
2183
2237
|
if (!srcEntry) {
|
|
2184
2238
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
@@ -2198,9 +2252,7 @@ var SqliteFs = class {
|
|
|
2198
2252
|
`INSERT INTO fs_entries (path, type, mode, size, mtime)
|
|
2199
2253
|
VALUES (?, 'file', ?, ?, ?)`
|
|
2200
2254
|
).run(destPrefixed, srcEntry.mode, srcEntry.size, Date.now());
|
|
2201
|
-
const chunks = this.#
|
|
2202
|
-
"SELECT chunkIndex, data FROM fs_chunks WHERE path = ?"
|
|
2203
|
-
).all(srcPrefixed);
|
|
2255
|
+
const chunks = this.#chunks(srcPrefixed);
|
|
2204
2256
|
for (const chunk of chunks) {
|
|
2205
2257
|
this.#stmt(
|
|
2206
2258
|
"INSERT INTO fs_chunks (path, chunkIndex, data) VALUES (?, ?, ?)"
|
|
@@ -2211,9 +2263,11 @@ var SqliteFs = class {
|
|
|
2211
2263
|
async readlink(linkPath) {
|
|
2212
2264
|
const normalized = this.#normalizePath(linkPath);
|
|
2213
2265
|
const prefixed = this.#prefixPath(normalized);
|
|
2214
|
-
const entry =
|
|
2215
|
-
|
|
2216
|
-
|
|
2266
|
+
const entry = linkRow.optional().parse(
|
|
2267
|
+
this.#stmt(
|
|
2268
|
+
"SELECT type, symlinkTarget FROM fs_entries WHERE path = ?"
|
|
2269
|
+
).get(prefixed)
|
|
2270
|
+
);
|
|
2217
2271
|
if (!entry) {
|
|
2218
2272
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
2219
2273
|
}
|
|
@@ -2226,7 +2280,8 @@ var SqliteFs = class {
|
|
|
2226
2280
|
|
|
2227
2281
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2228
2282
|
import { createRequire } from "node:module";
|
|
2229
|
-
import * as
|
|
2283
|
+
import * as path3 from "node:path";
|
|
2284
|
+
import z7 from "zod";
|
|
2230
2285
|
|
|
2231
2286
|
// packages/text2sql/src/lib/fs/mssql/ddl.mssql-fs.ts
|
|
2232
2287
|
function mssqlFsDDL(schema) {
|
|
@@ -2259,6 +2314,33 @@ GO
|
|
|
2259
2314
|
}
|
|
2260
2315
|
|
|
2261
2316
|
// packages/text2sql/src/lib/fs/mssql/mssql-fs.ts
|
|
2317
|
+
var entryRow2 = z7.object({
|
|
2318
|
+
path: z7.string(),
|
|
2319
|
+
type: entryType,
|
|
2320
|
+
mode: z7.number(),
|
|
2321
|
+
size: bigintColumn,
|
|
2322
|
+
mtime: bigintColumn,
|
|
2323
|
+
symlinkTarget: z7.string().nullable()
|
|
2324
|
+
});
|
|
2325
|
+
var typeRow2 = entryRow2.pick({ type: true });
|
|
2326
|
+
var pathRow2 = entryRow2.pick({ path: true });
|
|
2327
|
+
var pathTypeRow2 = entryRow2.pick({ path: true, type: true });
|
|
2328
|
+
var linkRow2 = z7.discriminatedUnion("type", [
|
|
2329
|
+
z7.object({ type: z7.literal("symlink"), symlinkTarget: z7.string() }),
|
|
2330
|
+
z7.object({
|
|
2331
|
+
type: z7.enum(["file", "directory"]),
|
|
2332
|
+
symlinkTarget: z7.string().nullable()
|
|
2333
|
+
})
|
|
2334
|
+
]);
|
|
2335
|
+
var existsRow = z7.object({ exists: z7.union([z7.literal(0), z7.literal(1)]) });
|
|
2336
|
+
var chunkRow2 = z7.object({
|
|
2337
|
+
chunkIndex: z7.number(),
|
|
2338
|
+
data: z7.instanceof(Buffer)
|
|
2339
|
+
});
|
|
2340
|
+
var dataRow2 = chunkRow2.pick({ data: true });
|
|
2341
|
+
function rowsOf(row, result) {
|
|
2342
|
+
return z7.array(row).parse(result.recordset);
|
|
2343
|
+
}
|
|
2262
2344
|
var MssqlFs = class _MssqlFs {
|
|
2263
2345
|
#pool;
|
|
2264
2346
|
#chunkSize;
|
|
@@ -2317,8 +2399,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2317
2399
|
await this.#pool.request().batch(batch);
|
|
2318
2400
|
}
|
|
2319
2401
|
}
|
|
2320
|
-
const rootSlashExists =
|
|
2321
|
-
|
|
2402
|
+
const rootSlashExists = rowsOf(
|
|
2403
|
+
existsRow,
|
|
2404
|
+
await this.#rawQuery(
|
|
2405
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') THEN 1 ELSE 0 END as [exists]`
|
|
2406
|
+
)
|
|
2322
2407
|
);
|
|
2323
2408
|
if (rootSlashExists[0].exists === 0) {
|
|
2324
2409
|
await this.#rawExec(
|
|
@@ -2328,9 +2413,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2328
2413
|
}
|
|
2329
2414
|
if (this.#root) {
|
|
2330
2415
|
await this.#createParentDirs(this.#root);
|
|
2331
|
-
const rootExists =
|
|
2332
|
-
|
|
2333
|
-
|
|
2416
|
+
const rootExists = rowsOf(
|
|
2417
|
+
existsRow,
|
|
2418
|
+
await this.#rawQuery(
|
|
2419
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2420
|
+
[this.#root]
|
|
2421
|
+
)
|
|
2334
2422
|
);
|
|
2335
2423
|
if (rootExists[0].exists === 0) {
|
|
2336
2424
|
await this.#rawExec(
|
|
@@ -2352,10 +2440,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2352
2440
|
const segments = p.split("/").filter(Boolean);
|
|
2353
2441
|
let currentPath = "/";
|
|
2354
2442
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2355
|
-
currentPath =
|
|
2356
|
-
const exists =
|
|
2357
|
-
|
|
2358
|
-
|
|
2443
|
+
currentPath = path3.posix.join(currentPath, segments[i]);
|
|
2444
|
+
const exists = rowsOf(
|
|
2445
|
+
existsRow,
|
|
2446
|
+
await this.#rawQuery(
|
|
2447
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2448
|
+
[currentPath]
|
|
2449
|
+
)
|
|
2359
2450
|
);
|
|
2360
2451
|
if (exists[0].exists === 0) {
|
|
2361
2452
|
await this.#rawExec(
|
|
@@ -2365,13 +2456,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2365
2456
|
}
|
|
2366
2457
|
}
|
|
2367
2458
|
}
|
|
2368
|
-
|
|
2459
|
+
#rawQuery(sql, params) {
|
|
2369
2460
|
const request = this.#pool.request();
|
|
2370
2461
|
params?.forEach((value, index2) => {
|
|
2371
2462
|
request.input(`p${index2}`, value);
|
|
2372
2463
|
});
|
|
2373
|
-
|
|
2374
|
-
return result.recordset;
|
|
2464
|
+
return request.query(sql);
|
|
2375
2465
|
}
|
|
2376
2466
|
async #rawExec(sql, params) {
|
|
2377
2467
|
const request = this.#pool.request();
|
|
@@ -2404,7 +2494,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2404
2494
|
}
|
|
2405
2495
|
}
|
|
2406
2496
|
#normalizeRoot(root) {
|
|
2407
|
-
return
|
|
2497
|
+
return path3.posix.resolve("/", root.trim());
|
|
2408
2498
|
}
|
|
2409
2499
|
#prefixPath(p) {
|
|
2410
2500
|
if (!this.#root) {
|
|
@@ -2413,7 +2503,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2413
2503
|
if (p === "/") {
|
|
2414
2504
|
return this.#root;
|
|
2415
2505
|
}
|
|
2416
|
-
return
|
|
2506
|
+
return path3.posix.join(this.#root, p);
|
|
2417
2507
|
}
|
|
2418
2508
|
#unprefixPath(p) {
|
|
2419
2509
|
if (!this.#root) {
|
|
@@ -2428,10 +2518,10 @@ var MssqlFs = class _MssqlFs {
|
|
|
2428
2518
|
return p;
|
|
2429
2519
|
}
|
|
2430
2520
|
#normalizePath(p) {
|
|
2431
|
-
return
|
|
2521
|
+
return path3.posix.resolve("/", p);
|
|
2432
2522
|
}
|
|
2433
2523
|
#dirname(p) {
|
|
2434
|
-
const dir =
|
|
2524
|
+
const dir = path3.posix.dirname(p);
|
|
2435
2525
|
return dir === "" ? "/" : dir;
|
|
2436
2526
|
}
|
|
2437
2527
|
async #ensureParentExists(filePath, transaction) {
|
|
@@ -2440,10 +2530,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2440
2530
|
if (parent === rootPath || parent === "/") return;
|
|
2441
2531
|
const request = transaction.request();
|
|
2442
2532
|
request.input("p0", parent);
|
|
2443
|
-
const
|
|
2444
|
-
|
|
2533
|
+
const [entry] = rowsOf(
|
|
2534
|
+
typeRow2,
|
|
2535
|
+
await request.query(
|
|
2536
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2537
|
+
)
|
|
2445
2538
|
);
|
|
2446
|
-
const entry = result.recordset[0];
|
|
2447
2539
|
if (!entry) {
|
|
2448
2540
|
await this.#ensureParentExists(parent, transaction);
|
|
2449
2541
|
const insertReq = transaction.request();
|
|
@@ -2477,20 +2569,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
2477
2569
|
}
|
|
2478
2570
|
}
|
|
2479
2571
|
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
|
-
}
|
|
2572
|
+
const sql = `SELECT data FROM ${this.#t("fs_chunks")} WHERE path = @p0 ORDER BY chunkIndex`;
|
|
2573
|
+
const rows = rowsOf(
|
|
2574
|
+
dataRow2,
|
|
2575
|
+
transaction ? await transaction.request().input("p0", filePath).query(sql) : await this.#query(sql, [filePath])
|
|
2576
|
+
);
|
|
2494
2577
|
if (rows.length === 0) {
|
|
2495
2578
|
return new Uint8Array(0);
|
|
2496
2579
|
}
|
|
@@ -2507,11 +2590,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2507
2590
|
if (seen.has(p)) {
|
|
2508
2591
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
2509
2592
|
}
|
|
2510
|
-
const
|
|
2511
|
-
|
|
2512
|
-
|
|
2593
|
+
const [entry] = rowsOf(
|
|
2594
|
+
linkRow2,
|
|
2595
|
+
await this.#query(
|
|
2596
|
+
`SELECT type, symlinkTarget FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2597
|
+
[p]
|
|
2598
|
+
)
|
|
2513
2599
|
);
|
|
2514
|
-
const entry = rows[0];
|
|
2515
2600
|
if (!entry) {
|
|
2516
2601
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
2517
2602
|
}
|
|
@@ -2520,7 +2605,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2520
2605
|
}
|
|
2521
2606
|
seen.add(p);
|
|
2522
2607
|
const target = this.#normalizePath(
|
|
2523
|
-
|
|
2608
|
+
path3.posix.resolve(this.#dirname(p), entry.symlinkTarget)
|
|
2524
2609
|
);
|
|
2525
2610
|
return this.#resolveSymlink(target, seen);
|
|
2526
2611
|
}
|
|
@@ -2528,8 +2613,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
2528
2613
|
if (content instanceof Uint8Array) {
|
|
2529
2614
|
return content;
|
|
2530
2615
|
}
|
|
2531
|
-
|
|
2532
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
2616
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
2533
2617
|
}
|
|
2534
2618
|
async close() {
|
|
2535
2619
|
if (this.#ownsPool) {
|
|
@@ -2543,11 +2627,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2543
2627
|
const normalized = this.#normalizePath(filePath);
|
|
2544
2628
|
const prefixed = this.#prefixPath(normalized);
|
|
2545
2629
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2546
|
-
const
|
|
2547
|
-
|
|
2548
|
-
|
|
2630
|
+
const [entry] = rowsOf(
|
|
2631
|
+
typeRow2,
|
|
2632
|
+
await this.#query(
|
|
2633
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2634
|
+
[resolved]
|
|
2635
|
+
)
|
|
2549
2636
|
);
|
|
2550
|
-
const entry = rows[0];
|
|
2551
2637
|
if (!entry) {
|
|
2552
2638
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2553
2639
|
}
|
|
@@ -2562,11 +2648,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2562
2648
|
const normalized = this.#normalizePath(filePath);
|
|
2563
2649
|
const prefixed = this.#prefixPath(normalized);
|
|
2564
2650
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2565
|
-
const
|
|
2566
|
-
|
|
2567
|
-
|
|
2651
|
+
const [entry] = rowsOf(
|
|
2652
|
+
typeRow2,
|
|
2653
|
+
await this.#query(
|
|
2654
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2655
|
+
[resolved]
|
|
2656
|
+
)
|
|
2568
2657
|
);
|
|
2569
|
-
const entry = rows[0];
|
|
2570
2658
|
if (!entry) {
|
|
2571
2659
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2572
2660
|
}
|
|
@@ -2608,10 +2696,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2608
2696
|
await this.#ensureParentExists(prefixed, transaction);
|
|
2609
2697
|
const checkReq = transaction.request();
|
|
2610
2698
|
checkReq.input("p0", prefixed);
|
|
2611
|
-
const
|
|
2612
|
-
|
|
2699
|
+
const [entry] = rowsOf(
|
|
2700
|
+
typeRow2,
|
|
2701
|
+
await checkReq.query(
|
|
2702
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2703
|
+
)
|
|
2613
2704
|
);
|
|
2614
|
-
const entry = result.recordset[0];
|
|
2615
2705
|
if (entry && entry.type !== "file") {
|
|
2616
2706
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
2617
2707
|
}
|
|
@@ -2639,9 +2729,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2639
2729
|
async exists(filePath) {
|
|
2640
2730
|
const normalized = this.#normalizePath(filePath);
|
|
2641
2731
|
const prefixed = this.#prefixPath(normalized);
|
|
2642
|
-
const rows =
|
|
2643
|
-
|
|
2644
|
-
|
|
2732
|
+
const rows = rowsOf(
|
|
2733
|
+
existsRow,
|
|
2734
|
+
await this.#query(
|
|
2735
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
2736
|
+
[prefixed]
|
|
2737
|
+
)
|
|
2645
2738
|
);
|
|
2646
2739
|
return rows[0].exists === 1;
|
|
2647
2740
|
}
|
|
@@ -2649,11 +2742,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2649
2742
|
const normalized = this.#normalizePath(filePath);
|
|
2650
2743
|
const prefixed = this.#prefixPath(normalized);
|
|
2651
2744
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2652
|
-
const
|
|
2653
|
-
|
|
2654
|
-
|
|
2745
|
+
const [entry] = rowsOf(
|
|
2746
|
+
entryRow2,
|
|
2747
|
+
await this.#query(
|
|
2748
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2749
|
+
[resolved]
|
|
2750
|
+
)
|
|
2655
2751
|
);
|
|
2656
|
-
const entry = rows[0];
|
|
2657
2752
|
if (!entry) {
|
|
2658
2753
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2659
2754
|
}
|
|
@@ -2661,19 +2756,21 @@ var MssqlFs = class _MssqlFs {
|
|
|
2661
2756
|
isFile: entry.type === "file",
|
|
2662
2757
|
isDirectory: entry.type === "directory",
|
|
2663
2758
|
isSymbolicLink: false,
|
|
2664
|
-
mode:
|
|
2665
|
-
size:
|
|
2666
|
-
mtime: new Date(
|
|
2759
|
+
mode: entry.mode,
|
|
2760
|
+
size: entry.size,
|
|
2761
|
+
mtime: new Date(entry.mtime)
|
|
2667
2762
|
};
|
|
2668
2763
|
}
|
|
2669
2764
|
async lstat(filePath) {
|
|
2670
2765
|
const normalized = this.#normalizePath(filePath);
|
|
2671
2766
|
const prefixed = this.#prefixPath(normalized);
|
|
2672
|
-
const
|
|
2673
|
-
|
|
2674
|
-
|
|
2767
|
+
const [entry] = rowsOf(
|
|
2768
|
+
entryRow2,
|
|
2769
|
+
await this.#query(
|
|
2770
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2771
|
+
[prefixed]
|
|
2772
|
+
)
|
|
2675
2773
|
);
|
|
2676
|
-
const entry = rows[0];
|
|
2677
2774
|
if (!entry) {
|
|
2678
2775
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
2679
2776
|
}
|
|
@@ -2681,19 +2778,21 @@ var MssqlFs = class _MssqlFs {
|
|
|
2681
2778
|
isFile: entry.type === "file",
|
|
2682
2779
|
isDirectory: entry.type === "directory",
|
|
2683
2780
|
isSymbolicLink: entry.type === "symlink",
|
|
2684
|
-
mode:
|
|
2685
|
-
size:
|
|
2686
|
-
mtime: new Date(
|
|
2781
|
+
mode: entry.mode,
|
|
2782
|
+
size: entry.size,
|
|
2783
|
+
mtime: new Date(entry.mtime)
|
|
2687
2784
|
};
|
|
2688
2785
|
}
|
|
2689
2786
|
async mkdir(dirPath, options) {
|
|
2690
2787
|
const normalized = this.#normalizePath(dirPath);
|
|
2691
2788
|
const prefixed = this.#prefixPath(normalized);
|
|
2692
|
-
const
|
|
2693
|
-
|
|
2694
|
-
|
|
2789
|
+
const [existing] = rowsOf(
|
|
2790
|
+
typeRow2,
|
|
2791
|
+
await this.#query(
|
|
2792
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2793
|
+
[prefixed]
|
|
2794
|
+
)
|
|
2695
2795
|
);
|
|
2696
|
-
const existing = existingRows[0];
|
|
2697
2796
|
if (existing) {
|
|
2698
2797
|
if (options?.recursive) {
|
|
2699
2798
|
return;
|
|
@@ -2703,17 +2802,19 @@ var MssqlFs = class _MssqlFs {
|
|
|
2703
2802
|
await this.#useTransaction(async (transaction) => {
|
|
2704
2803
|
if (options?.recursive) {
|
|
2705
2804
|
const rootPath = this.#root || "/";
|
|
2706
|
-
const relativePath =
|
|
2805
|
+
const relativePath = path3.posix.relative(rootPath, prefixed);
|
|
2707
2806
|
const segments = relativePath.split("/").filter(Boolean);
|
|
2708
2807
|
let currentPath = rootPath;
|
|
2709
2808
|
for (const segment of segments) {
|
|
2710
|
-
currentPath =
|
|
2809
|
+
currentPath = path3.posix.join(currentPath, segment);
|
|
2711
2810
|
const checkReq = transaction.request();
|
|
2712
2811
|
checkReq.input("p0", currentPath);
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2812
|
+
const [exists] = rowsOf(
|
|
2813
|
+
typeRow2,
|
|
2814
|
+
await checkReq.query(
|
|
2815
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2816
|
+
)
|
|
2715
2817
|
);
|
|
2716
|
-
const exists = result.recordset[0];
|
|
2717
2818
|
if (!exists) {
|
|
2718
2819
|
const insertReq = transaction.request();
|
|
2719
2820
|
insertReq.input("p0", currentPath);
|
|
@@ -2729,10 +2830,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
2729
2830
|
const parent = this.#dirname(prefixed);
|
|
2730
2831
|
const parentReq = transaction.request();
|
|
2731
2832
|
parentReq.input("p0", parent);
|
|
2732
|
-
const
|
|
2733
|
-
|
|
2833
|
+
const [parentEntry] = rowsOf(
|
|
2834
|
+
typeRow2,
|
|
2835
|
+
await parentReq.query(
|
|
2836
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`
|
|
2837
|
+
)
|
|
2734
2838
|
);
|
|
2735
|
-
const parentEntry = parentResult.recordset[0];
|
|
2736
2839
|
if (!parentEntry) {
|
|
2737
2840
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
2738
2841
|
}
|
|
@@ -2752,11 +2855,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2752
2855
|
const normalized = this.#normalizePath(dirPath);
|
|
2753
2856
|
const prefixed = this.#prefixPath(normalized);
|
|
2754
2857
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2755
|
-
const
|
|
2756
|
-
|
|
2757
|
-
|
|
2858
|
+
const [entry] = rowsOf(
|
|
2859
|
+
typeRow2,
|
|
2860
|
+
await this.#query(
|
|
2861
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2862
|
+
[resolved]
|
|
2863
|
+
)
|
|
2758
2864
|
);
|
|
2759
|
-
const entry = entryRows[0];
|
|
2760
2865
|
if (!entry) {
|
|
2761
2866
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
2762
2867
|
}
|
|
@@ -2764,24 +2869,29 @@ var MssqlFs = class _MssqlFs {
|
|
|
2764
2869
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
2765
2870
|
}
|
|
2766
2871
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
2767
|
-
const rows =
|
|
2768
|
-
|
|
2872
|
+
const rows = rowsOf(
|
|
2873
|
+
pathRow2,
|
|
2874
|
+
await this.#query(
|
|
2875
|
+
`SELECT path FROM ${this.#t("fs_entries")}
|
|
2769
2876
|
WHERE path LIKE @p0 + '%'
|
|
2770
2877
|
AND path != @p1
|
|
2771
2878
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
2772
|
-
|
|
2879
|
+
[prefix, resolved]
|
|
2880
|
+
)
|
|
2773
2881
|
);
|
|
2774
|
-
return rows.map((row) =>
|
|
2882
|
+
return rows.map((row) => path3.posix.basename(row.path));
|
|
2775
2883
|
}
|
|
2776
2884
|
async readdirWithFileTypes(dirPath) {
|
|
2777
2885
|
const normalized = this.#normalizePath(dirPath);
|
|
2778
2886
|
const prefixed = this.#prefixPath(normalized);
|
|
2779
2887
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2782
|
-
|
|
2888
|
+
const [entry] = rowsOf(
|
|
2889
|
+
typeRow2,
|
|
2890
|
+
await this.#query(
|
|
2891
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2892
|
+
[resolved]
|
|
2893
|
+
)
|
|
2783
2894
|
);
|
|
2784
|
-
const entry = entryRows[0];
|
|
2785
2895
|
if (!entry) {
|
|
2786
2896
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
2787
2897
|
}
|
|
@@ -2789,15 +2899,18 @@ var MssqlFs = class _MssqlFs {
|
|
|
2789
2899
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
2790
2900
|
}
|
|
2791
2901
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
2792
|
-
const rows =
|
|
2793
|
-
|
|
2902
|
+
const rows = rowsOf(
|
|
2903
|
+
pathTypeRow2,
|
|
2904
|
+
await this.#query(
|
|
2905
|
+
`SELECT path, type FROM ${this.#t("fs_entries")}
|
|
2794
2906
|
WHERE path LIKE @p0 + '%'
|
|
2795
2907
|
AND path != @p1
|
|
2796
2908
|
AND path NOT LIKE @p0 + '%/%'`,
|
|
2797
|
-
|
|
2909
|
+
[prefix, resolved]
|
|
2910
|
+
)
|
|
2798
2911
|
);
|
|
2799
2912
|
return rows.map((row) => ({
|
|
2800
|
-
name:
|
|
2913
|
+
name: path3.posix.basename(row.path),
|
|
2801
2914
|
isFile: row.type === "file",
|
|
2802
2915
|
isDirectory: row.type === "directory",
|
|
2803
2916
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -2806,11 +2919,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2806
2919
|
async rm(filePath, options) {
|
|
2807
2920
|
const normalized = this.#normalizePath(filePath);
|
|
2808
2921
|
const prefixed = this.#prefixPath(normalized);
|
|
2809
|
-
const
|
|
2810
|
-
|
|
2811
|
-
|
|
2922
|
+
const [entry] = rowsOf(
|
|
2923
|
+
typeRow2,
|
|
2924
|
+
await this.#query(
|
|
2925
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2926
|
+
[prefixed]
|
|
2927
|
+
)
|
|
2812
2928
|
);
|
|
2813
|
-
const entry = rows[0];
|
|
2814
2929
|
if (!entry) {
|
|
2815
2930
|
if (options?.force) {
|
|
2816
2931
|
return;
|
|
@@ -2821,10 +2936,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2821
2936
|
if (entry.type === "directory") {
|
|
2822
2937
|
const childrenReq = transaction.request();
|
|
2823
2938
|
childrenReq.input("p0", prefixed);
|
|
2824
|
-
const
|
|
2825
|
-
|
|
2939
|
+
const children = rowsOf(
|
|
2940
|
+
existsRow,
|
|
2941
|
+
await childrenReq.query(
|
|
2942
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path LIKE @p0 + '/%') THEN 1 ELSE 0 END as [exists]`
|
|
2943
|
+
)
|
|
2826
2944
|
);
|
|
2827
|
-
if (
|
|
2945
|
+
if (children[0].exists === 1 && !options?.recursive) {
|
|
2828
2946
|
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
2829
2947
|
}
|
|
2830
2948
|
const deleteReq = transaction.request();
|
|
@@ -2846,11 +2964,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2846
2964
|
const destNormalized = this.#normalizePath(dest);
|
|
2847
2965
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2848
2966
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2849
|
-
const
|
|
2850
|
-
|
|
2851
|
-
|
|
2967
|
+
const [srcEntry] = rowsOf(
|
|
2968
|
+
entryRow2,
|
|
2969
|
+
await this.#query(
|
|
2970
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
2971
|
+
[srcPrefixed]
|
|
2972
|
+
)
|
|
2852
2973
|
);
|
|
2853
|
-
const srcEntry = srcRows[0];
|
|
2854
2974
|
if (!srcEntry) {
|
|
2855
2975
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
2856
2976
|
}
|
|
@@ -2862,12 +2982,15 @@ var MssqlFs = class _MssqlFs {
|
|
|
2862
2982
|
if (srcEntry.type === "directory") {
|
|
2863
2983
|
const allEntriesReq = transaction.request();
|
|
2864
2984
|
allEntriesReq.input("p0", srcPrefixed);
|
|
2865
|
-
const
|
|
2866
|
-
|
|
2985
|
+
const allEntries = rowsOf(
|
|
2986
|
+
entryRow2,
|
|
2987
|
+
await allEntriesReq.query(
|
|
2988
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%'`
|
|
2989
|
+
)
|
|
2867
2990
|
);
|
|
2868
|
-
for (const entry of
|
|
2869
|
-
const relativePath =
|
|
2870
|
-
const newPath =
|
|
2991
|
+
for (const entry of allEntries) {
|
|
2992
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
2993
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2871
2994
|
const insertReq = transaction.request();
|
|
2872
2995
|
insertReq.input("p0", newPath);
|
|
2873
2996
|
insertReq.input("p1", entry.type);
|
|
@@ -2893,10 +3016,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2893
3016
|
);
|
|
2894
3017
|
const chunksReq = transaction.request();
|
|
2895
3018
|
chunksReq.input("p0", entry.path);
|
|
2896
|
-
const
|
|
2897
|
-
|
|
3019
|
+
const chunks = rowsOf(
|
|
3020
|
+
chunkRow2,
|
|
3021
|
+
await chunksReq.query(
|
|
3022
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3023
|
+
)
|
|
2898
3024
|
);
|
|
2899
|
-
for (const chunk of
|
|
3025
|
+
for (const chunk of chunks) {
|
|
2900
3026
|
const chunkInsertReq = transaction.request();
|
|
2901
3027
|
chunkInsertReq.input("p0", newPath);
|
|
2902
3028
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -2928,15 +3054,18 @@ var MssqlFs = class _MssqlFs {
|
|
|
2928
3054
|
if (srcEntry.type === "file") {
|
|
2929
3055
|
const chunksReq = transaction.request();
|
|
2930
3056
|
chunksReq.input("p0", srcPrefixed);
|
|
2931
|
-
const
|
|
2932
|
-
|
|
3057
|
+
const chunks = rowsOf(
|
|
3058
|
+
chunkRow2,
|
|
3059
|
+
await chunksReq.query(
|
|
3060
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3061
|
+
)
|
|
2933
3062
|
);
|
|
2934
3063
|
const deleteChunksReq = transaction.request();
|
|
2935
3064
|
deleteChunksReq.input("p0", destPrefixed);
|
|
2936
3065
|
await deleteChunksReq.query(
|
|
2937
3066
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
2938
3067
|
);
|
|
2939
|
-
for (const chunk of
|
|
3068
|
+
for (const chunk of chunks) {
|
|
2940
3069
|
const chunkInsertReq = transaction.request();
|
|
2941
3070
|
chunkInsertReq.input("p0", destPrefixed);
|
|
2942
3071
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -2954,11 +3083,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
2954
3083
|
const destNormalized = this.#normalizePath(dest);
|
|
2955
3084
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
2956
3085
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
2957
|
-
const
|
|
2958
|
-
|
|
2959
|
-
|
|
3086
|
+
const [srcEntry] = rowsOf(
|
|
3087
|
+
entryRow2,
|
|
3088
|
+
await this.#query(
|
|
3089
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3090
|
+
[srcPrefixed]
|
|
3091
|
+
)
|
|
2960
3092
|
);
|
|
2961
|
-
const srcEntry = srcRows[0];
|
|
2962
3093
|
if (!srcEntry) {
|
|
2963
3094
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
2964
3095
|
}
|
|
@@ -2967,17 +3098,20 @@ var MssqlFs = class _MssqlFs {
|
|
|
2967
3098
|
if (srcEntry.type === "directory") {
|
|
2968
3099
|
const allEntriesReq = transaction.request();
|
|
2969
3100
|
allEntriesReq.input("p0", srcPrefixed);
|
|
2970
|
-
const
|
|
2971
|
-
|
|
3101
|
+
const allEntries = rowsOf(
|
|
3102
|
+
entryRow2,
|
|
3103
|
+
await allEntriesReq.query(
|
|
3104
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0 OR path LIKE @p0 + '/%' ORDER BY path DESC`
|
|
3105
|
+
)
|
|
2972
3106
|
);
|
|
2973
3107
|
const destDeleteReq = transaction.request();
|
|
2974
3108
|
destDeleteReq.input("dp0", destPrefixed);
|
|
2975
3109
|
await destDeleteReq.query(
|
|
2976
3110
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = @dp0 OR path LIKE @dp0 + '/%'`
|
|
2977
3111
|
);
|
|
2978
|
-
for (const entry of [...
|
|
2979
|
-
const relativePath =
|
|
2980
|
-
const newPath =
|
|
3112
|
+
for (const entry of [...allEntries].reverse()) {
|
|
3113
|
+
const relativePath = path3.posix.relative(srcPrefixed, entry.path);
|
|
3114
|
+
const newPath = path3.posix.join(destPrefixed, relativePath);
|
|
2981
3115
|
const insertReq = transaction.request();
|
|
2982
3116
|
insertReq.input("p0", newPath);
|
|
2983
3117
|
insertReq.input("p1", entry.type);
|
|
@@ -3003,10 +3137,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3003
3137
|
);
|
|
3004
3138
|
const chunksReq = transaction.request();
|
|
3005
3139
|
chunksReq.input("p0", entry.path);
|
|
3006
|
-
const
|
|
3007
|
-
|
|
3140
|
+
const chunks = rowsOf(
|
|
3141
|
+
chunkRow2,
|
|
3142
|
+
await chunksReq.query(
|
|
3143
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3144
|
+
)
|
|
3008
3145
|
);
|
|
3009
|
-
for (const chunk of
|
|
3146
|
+
for (const chunk of chunks) {
|
|
3010
3147
|
const chunkInsertReq = transaction.request();
|
|
3011
3148
|
chunkInsertReq.input("p0", newPath);
|
|
3012
3149
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3048,10 +3185,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3048
3185
|
);
|
|
3049
3186
|
const chunksReq = transaction.request();
|
|
3050
3187
|
chunksReq.input("p0", srcPrefixed);
|
|
3051
|
-
const
|
|
3052
|
-
|
|
3188
|
+
const chunks = rowsOf(
|
|
3189
|
+
chunkRow2,
|
|
3190
|
+
await chunksReq.query(
|
|
3191
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3192
|
+
)
|
|
3053
3193
|
);
|
|
3054
|
-
for (const chunk of
|
|
3194
|
+
for (const chunk of chunks) {
|
|
3055
3195
|
const chunkInsertReq = transaction.request();
|
|
3056
3196
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3057
3197
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3070,7 +3210,7 @@ var MssqlFs = class _MssqlFs {
|
|
|
3070
3210
|
});
|
|
3071
3211
|
}
|
|
3072
3212
|
resolvePath(base, relativePath) {
|
|
3073
|
-
return
|
|
3213
|
+
return path3.posix.resolve(base, relativePath);
|
|
3074
3214
|
}
|
|
3075
3215
|
getAllPaths() {
|
|
3076
3216
|
throw new Error(
|
|
@@ -3078,8 +3218,11 @@ var MssqlFs = class _MssqlFs {
|
|
|
3078
3218
|
);
|
|
3079
3219
|
}
|
|
3080
3220
|
async getAllPathsAsync() {
|
|
3081
|
-
const rows =
|
|
3082
|
-
|
|
3221
|
+
const rows = rowsOf(
|
|
3222
|
+
pathRow2,
|
|
3223
|
+
await this.#query(
|
|
3224
|
+
`SELECT path FROM ${this.#t("fs_entries")} ORDER BY path`
|
|
3225
|
+
)
|
|
3083
3226
|
);
|
|
3084
3227
|
return rows.map((row) => row.path);
|
|
3085
3228
|
}
|
|
@@ -3087,9 +3230,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3087
3230
|
const normalized = this.#normalizePath(filePath);
|
|
3088
3231
|
const prefixed = this.#prefixPath(normalized);
|
|
3089
3232
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3090
|
-
const rows =
|
|
3091
|
-
|
|
3092
|
-
|
|
3233
|
+
const rows = rowsOf(
|
|
3234
|
+
existsRow,
|
|
3235
|
+
await this.#query(
|
|
3236
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3237
|
+
[resolved]
|
|
3238
|
+
)
|
|
3093
3239
|
);
|
|
3094
3240
|
if (rows[0].exists !== 1) {
|
|
3095
3241
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -3122,9 +3268,12 @@ var MssqlFs = class _MssqlFs {
|
|
|
3122
3268
|
async symlink(target, linkPath) {
|
|
3123
3269
|
const normalized = this.#normalizePath(linkPath);
|
|
3124
3270
|
const prefixed = this.#prefixPath(normalized);
|
|
3125
|
-
const existingRows =
|
|
3126
|
-
|
|
3127
|
-
|
|
3271
|
+
const existingRows = rowsOf(
|
|
3272
|
+
existsRow,
|
|
3273
|
+
await this.#query(
|
|
3274
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3275
|
+
[prefixed]
|
|
3276
|
+
)
|
|
3128
3277
|
);
|
|
3129
3278
|
if (existingRows[0].exists === 1) {
|
|
3130
3279
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
@@ -3146,20 +3295,25 @@ var MssqlFs = class _MssqlFs {
|
|
|
3146
3295
|
const destNormalized = this.#normalizePath(newPath);
|
|
3147
3296
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3148
3297
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3298
|
+
const [srcEntry] = rowsOf(
|
|
3299
|
+
entryRow2,
|
|
3300
|
+
await this.#query(
|
|
3301
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3302
|
+
[srcPrefixed]
|
|
3303
|
+
)
|
|
3152
3304
|
);
|
|
3153
|
-
const srcEntry = srcRows[0];
|
|
3154
3305
|
if (!srcEntry) {
|
|
3155
3306
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
3156
3307
|
}
|
|
3157
3308
|
if (srcEntry.type !== "file") {
|
|
3158
3309
|
throw new Error(`link: not supported for directories: ${existingPath}`);
|
|
3159
3310
|
}
|
|
3160
|
-
const existingRows =
|
|
3161
|
-
|
|
3162
|
-
|
|
3311
|
+
const existingRows = rowsOf(
|
|
3312
|
+
existsRow,
|
|
3313
|
+
await this.#query(
|
|
3314
|
+
`SELECT CASE WHEN EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = @p0) THEN 1 ELSE 0 END as [exists]`,
|
|
3315
|
+
[destPrefixed]
|
|
3316
|
+
)
|
|
3163
3317
|
);
|
|
3164
3318
|
if (existingRows[0].exists === 1) {
|
|
3165
3319
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
@@ -3177,10 +3331,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3177
3331
|
);
|
|
3178
3332
|
const chunksReq = transaction.request();
|
|
3179
3333
|
chunksReq.input("p0", srcPrefixed);
|
|
3180
|
-
const
|
|
3181
|
-
|
|
3334
|
+
const chunks = rowsOf(
|
|
3335
|
+
chunkRow2,
|
|
3336
|
+
await chunksReq.query(
|
|
3337
|
+
`SELECT chunkIndex, data FROM ${this.#t("fs_chunks")} WHERE path = @p0`
|
|
3338
|
+
)
|
|
3182
3339
|
);
|
|
3183
|
-
for (const chunk of
|
|
3340
|
+
for (const chunk of chunks) {
|
|
3184
3341
|
const chunkInsertReq = transaction.request();
|
|
3185
3342
|
chunkInsertReq.input("p0", destPrefixed);
|
|
3186
3343
|
chunkInsertReq.input("p1", chunk.chunkIndex);
|
|
@@ -3194,11 +3351,13 @@ var MssqlFs = class _MssqlFs {
|
|
|
3194
3351
|
async readlink(linkPath) {
|
|
3195
3352
|
const normalized = this.#normalizePath(linkPath);
|
|
3196
3353
|
const prefixed = this.#prefixPath(normalized);
|
|
3197
|
-
const
|
|
3198
|
-
|
|
3199
|
-
|
|
3354
|
+
const [entry] = rowsOf(
|
|
3355
|
+
linkRow2,
|
|
3356
|
+
await this.#query(
|
|
3357
|
+
`SELECT type, symlinkTarget FROM ${this.#t("fs_entries")} WHERE path = @p0`,
|
|
3358
|
+
[prefixed]
|
|
3359
|
+
)
|
|
3200
3360
|
);
|
|
3201
|
-
const entry = rows[0];
|
|
3202
3361
|
if (!entry) {
|
|
3203
3362
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
3204
3363
|
}
|
|
@@ -3211,7 +3370,8 @@ var MssqlFs = class _MssqlFs {
|
|
|
3211
3370
|
|
|
3212
3371
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
3213
3372
|
import { createRequire as createRequire2 } from "node:module";
|
|
3214
|
-
import * as
|
|
3373
|
+
import * as path4 from "node:path";
|
|
3374
|
+
import z8 from "zod";
|
|
3215
3375
|
|
|
3216
3376
|
// packages/text2sql/src/lib/fs/postgres/ddl.postgres-fs.ts
|
|
3217
3377
|
function postgresFsDDL(schema) {
|
|
@@ -3240,6 +3400,33 @@ CREATE TABLE IF NOT EXISTS "${schema}"."fs_chunks" (
|
|
|
3240
3400
|
}
|
|
3241
3401
|
|
|
3242
3402
|
// packages/text2sql/src/lib/fs/postgres/postgres-fs.ts
|
|
3403
|
+
var entryRow3 = z8.object({
|
|
3404
|
+
path: z8.string(),
|
|
3405
|
+
type: entryType,
|
|
3406
|
+
mode: z8.number(),
|
|
3407
|
+
size: bigintColumn,
|
|
3408
|
+
mtime: bigintColumn,
|
|
3409
|
+
symlink_target: z8.string().nullable()
|
|
3410
|
+
});
|
|
3411
|
+
var typeRow3 = entryRow3.pick({ type: true });
|
|
3412
|
+
var pathRow3 = entryRow3.pick({ path: true });
|
|
3413
|
+
var pathTypeRow3 = entryRow3.pick({ path: true, type: true });
|
|
3414
|
+
var linkRow3 = z8.discriminatedUnion("type", [
|
|
3415
|
+
z8.object({ type: z8.literal("symlink"), symlink_target: z8.string() }),
|
|
3416
|
+
z8.object({
|
|
3417
|
+
type: z8.enum(["file", "directory"]),
|
|
3418
|
+
symlink_target: z8.string().nullable()
|
|
3419
|
+
})
|
|
3420
|
+
]);
|
|
3421
|
+
var existsRow2 = z8.object({ exists: z8.boolean() });
|
|
3422
|
+
var chunkRow3 = z8.object({
|
|
3423
|
+
chunk_index: z8.number(),
|
|
3424
|
+
data: z8.instanceof(Buffer)
|
|
3425
|
+
});
|
|
3426
|
+
var dataRow3 = chunkRow3.pick({ data: true });
|
|
3427
|
+
function rowsOf2(row, result) {
|
|
3428
|
+
return z8.array(row).parse(result.rows);
|
|
3429
|
+
}
|
|
3243
3430
|
var PostgresFs = class _PostgresFs {
|
|
3244
3431
|
#pool;
|
|
3245
3432
|
#chunkSize;
|
|
@@ -3281,8 +3468,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3281
3468
|
async initialize() {
|
|
3282
3469
|
const ddl = postgresFsDDL(this.#schema);
|
|
3283
3470
|
await this.#pool.query(ddl);
|
|
3284
|
-
const rootSlashExists =
|
|
3285
|
-
|
|
3471
|
+
const rootSlashExists = rowsOf2(
|
|
3472
|
+
existsRow2,
|
|
3473
|
+
await this.#rawQuery(
|
|
3474
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = '/') AS exists`
|
|
3475
|
+
)
|
|
3286
3476
|
);
|
|
3287
3477
|
if (!rootSlashExists[0].exists) {
|
|
3288
3478
|
await this.#rawExec(
|
|
@@ -3292,9 +3482,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3292
3482
|
}
|
|
3293
3483
|
if (this.#root) {
|
|
3294
3484
|
await this.#createParentDirs(this.#root);
|
|
3295
|
-
const rootExists =
|
|
3296
|
-
|
|
3297
|
-
|
|
3485
|
+
const rootExists = rowsOf2(
|
|
3486
|
+
existsRow2,
|
|
3487
|
+
await this.#rawQuery(
|
|
3488
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3489
|
+
[this.#root]
|
|
3490
|
+
)
|
|
3298
3491
|
);
|
|
3299
3492
|
if (!rootExists[0].exists) {
|
|
3300
3493
|
await this.#rawExec(
|
|
@@ -3316,10 +3509,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3316
3509
|
const segments = p.split("/").filter(Boolean);
|
|
3317
3510
|
let currentPath = "/";
|
|
3318
3511
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
3319
|
-
currentPath =
|
|
3320
|
-
const exists =
|
|
3321
|
-
|
|
3322
|
-
|
|
3512
|
+
currentPath = path4.posix.join(currentPath, segments[i]);
|
|
3513
|
+
const exists = rowsOf2(
|
|
3514
|
+
existsRow2,
|
|
3515
|
+
await this.#rawQuery(
|
|
3516
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3517
|
+
[currentPath]
|
|
3518
|
+
)
|
|
3323
3519
|
);
|
|
3324
3520
|
if (!exists[0].exists) {
|
|
3325
3521
|
await this.#rawExec(
|
|
@@ -3329,9 +3525,8 @@ var PostgresFs = class _PostgresFs {
|
|
|
3329
3525
|
}
|
|
3330
3526
|
}
|
|
3331
3527
|
}
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
return result.rows;
|
|
3528
|
+
#rawQuery(sql, params) {
|
|
3529
|
+
return this.#pool.query(sql, params);
|
|
3335
3530
|
}
|
|
3336
3531
|
async #rawExec(sql, params) {
|
|
3337
3532
|
const result = await this.#pool.query(sql, params);
|
|
@@ -3361,7 +3556,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3361
3556
|
}
|
|
3362
3557
|
}
|
|
3363
3558
|
#normalizeRoot(root) {
|
|
3364
|
-
return
|
|
3559
|
+
return path4.posix.resolve("/", root.trim());
|
|
3365
3560
|
}
|
|
3366
3561
|
#prefixPath(p) {
|
|
3367
3562
|
if (!this.#root) {
|
|
@@ -3370,7 +3565,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3370
3565
|
if (p === "/") {
|
|
3371
3566
|
return this.#root;
|
|
3372
3567
|
}
|
|
3373
|
-
return
|
|
3568
|
+
return path4.posix.join(this.#root, p);
|
|
3374
3569
|
}
|
|
3375
3570
|
#unprefixPath(p) {
|
|
3376
3571
|
if (!this.#root) {
|
|
@@ -3385,21 +3580,23 @@ var PostgresFs = class _PostgresFs {
|
|
|
3385
3580
|
return p;
|
|
3386
3581
|
}
|
|
3387
3582
|
#normalizePath(p) {
|
|
3388
|
-
return
|
|
3583
|
+
return path4.posix.resolve("/", p);
|
|
3389
3584
|
}
|
|
3390
3585
|
#dirname(p) {
|
|
3391
|
-
const dir =
|
|
3586
|
+
const dir = path4.posix.dirname(p);
|
|
3392
3587
|
return dir === "" ? "/" : dir;
|
|
3393
3588
|
}
|
|
3394
3589
|
async #ensureParentExists(filePath, client) {
|
|
3395
3590
|
const parent = this.#dirname(filePath);
|
|
3396
3591
|
const rootPath = this.#root || "/";
|
|
3397
3592
|
if (parent === rootPath || parent === "/") return;
|
|
3398
|
-
const
|
|
3399
|
-
|
|
3400
|
-
|
|
3593
|
+
const [entry] = rowsOf2(
|
|
3594
|
+
typeRow3,
|
|
3595
|
+
await client.query(
|
|
3596
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3597
|
+
[parent]
|
|
3598
|
+
)
|
|
3401
3599
|
);
|
|
3402
|
-
const entry = result.rows[0];
|
|
3403
3600
|
if (!entry) {
|
|
3404
3601
|
await this.#ensureParentExists(parent, client);
|
|
3405
3602
|
await client.query(
|
|
@@ -3426,19 +3623,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3426
3623
|
}
|
|
3427
3624
|
}
|
|
3428
3625
|
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
|
-
}
|
|
3626
|
+
const sql = `SELECT data FROM ${this.#t("fs_chunks")} WHERE path = $1 ORDER BY chunk_index`;
|
|
3627
|
+
const rows = rowsOf2(
|
|
3628
|
+
dataRow3,
|
|
3629
|
+
client ? await client.query(sql, [filePath]) : await this.#query(sql, [filePath])
|
|
3630
|
+
);
|
|
3442
3631
|
if (rows.length === 0) {
|
|
3443
3632
|
return new Uint8Array(0);
|
|
3444
3633
|
}
|
|
@@ -3455,11 +3644,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3455
3644
|
if (seen.has(p)) {
|
|
3456
3645
|
throw new Error(`readFile: circular symlink: ${p}`);
|
|
3457
3646
|
}
|
|
3458
|
-
const
|
|
3459
|
-
|
|
3460
|
-
|
|
3647
|
+
const [entry] = rowsOf2(
|
|
3648
|
+
linkRow3,
|
|
3649
|
+
await this.#query(
|
|
3650
|
+
`SELECT type, symlink_target FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3651
|
+
[p]
|
|
3652
|
+
)
|
|
3461
3653
|
);
|
|
3462
|
-
const entry = rows[0];
|
|
3463
3654
|
if (!entry) {
|
|
3464
3655
|
throw new Error(`ENOENT: no such file or directory: ${p}`);
|
|
3465
3656
|
}
|
|
@@ -3468,7 +3659,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3468
3659
|
}
|
|
3469
3660
|
seen.add(p);
|
|
3470
3661
|
const target = this.#normalizePath(
|
|
3471
|
-
|
|
3662
|
+
path4.posix.resolve(this.#dirname(p), entry.symlink_target)
|
|
3472
3663
|
);
|
|
3473
3664
|
return this.#resolveSymlink(target, seen);
|
|
3474
3665
|
}
|
|
@@ -3476,8 +3667,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3476
3667
|
if (content instanceof Uint8Array) {
|
|
3477
3668
|
return content;
|
|
3478
3669
|
}
|
|
3479
|
-
|
|
3480
|
-
return new Uint8Array(Buffer.from(content, enc));
|
|
3670
|
+
return new Uint8Array(Buffer.from(content, encoding ?? "utf8"));
|
|
3481
3671
|
}
|
|
3482
3672
|
async close() {
|
|
3483
3673
|
if (this.#ownsPool) {
|
|
@@ -3491,11 +3681,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3491
3681
|
const normalized = this.#normalizePath(filePath);
|
|
3492
3682
|
const prefixed = this.#prefixPath(normalized);
|
|
3493
3683
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3494
|
-
const
|
|
3495
|
-
|
|
3496
|
-
|
|
3684
|
+
const [entry] = rowsOf2(
|
|
3685
|
+
typeRow3,
|
|
3686
|
+
await this.#query(
|
|
3687
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3688
|
+
[resolved]
|
|
3689
|
+
)
|
|
3497
3690
|
);
|
|
3498
|
-
const entry = rows[0];
|
|
3499
3691
|
if (!entry) {
|
|
3500
3692
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3501
3693
|
}
|
|
@@ -3510,11 +3702,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3510
3702
|
const normalized = this.#normalizePath(filePath);
|
|
3511
3703
|
const prefixed = this.#prefixPath(normalized);
|
|
3512
3704
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3513
|
-
const
|
|
3514
|
-
|
|
3515
|
-
|
|
3705
|
+
const [entry] = rowsOf2(
|
|
3706
|
+
typeRow3,
|
|
3707
|
+
await this.#query(
|
|
3708
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3709
|
+
[resolved]
|
|
3710
|
+
)
|
|
3516
3711
|
);
|
|
3517
|
-
const entry = rows[0];
|
|
3518
3712
|
if (!entry) {
|
|
3519
3713
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3520
3714
|
}
|
|
@@ -3546,11 +3740,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3546
3740
|
const newData = this.#toUint8Array(content, encoding);
|
|
3547
3741
|
await this.#useTransaction(async (client) => {
|
|
3548
3742
|
await this.#ensureParentExists(prefixed, client);
|
|
3549
|
-
const
|
|
3550
|
-
|
|
3551
|
-
|
|
3743
|
+
const [entry] = rowsOf2(
|
|
3744
|
+
typeRow3,
|
|
3745
|
+
await client.query(
|
|
3746
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3747
|
+
[prefixed]
|
|
3748
|
+
)
|
|
3552
3749
|
);
|
|
3553
|
-
const entry = result.rows[0];
|
|
3554
3750
|
if (entry && entry.type !== "file") {
|
|
3555
3751
|
throw new Error(`appendFile: not a file: ${filePath}`);
|
|
3556
3752
|
}
|
|
@@ -3570,9 +3766,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3570
3766
|
async exists(filePath) {
|
|
3571
3767
|
const normalized = this.#normalizePath(filePath);
|
|
3572
3768
|
const prefixed = this.#prefixPath(normalized);
|
|
3573
|
-
const rows =
|
|
3574
|
-
|
|
3575
|
-
|
|
3769
|
+
const rows = rowsOf2(
|
|
3770
|
+
existsRow2,
|
|
3771
|
+
await this.#query(
|
|
3772
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
3773
|
+
[prefixed]
|
|
3774
|
+
)
|
|
3576
3775
|
);
|
|
3577
3776
|
return rows[0].exists;
|
|
3578
3777
|
}
|
|
@@ -3580,11 +3779,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3580
3779
|
const normalized = this.#normalizePath(filePath);
|
|
3581
3780
|
const prefixed = this.#prefixPath(normalized);
|
|
3582
3781
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3583
|
-
const
|
|
3584
|
-
|
|
3585
|
-
|
|
3782
|
+
const [entry] = rowsOf2(
|
|
3783
|
+
entryRow3,
|
|
3784
|
+
await this.#query(
|
|
3785
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3786
|
+
[resolved]
|
|
3787
|
+
)
|
|
3586
3788
|
);
|
|
3587
|
-
const entry = rows[0];
|
|
3588
3789
|
if (!entry) {
|
|
3589
3790
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3590
3791
|
}
|
|
@@ -3592,19 +3793,21 @@ var PostgresFs = class _PostgresFs {
|
|
|
3592
3793
|
isFile: entry.type === "file",
|
|
3593
3794
|
isDirectory: entry.type === "directory",
|
|
3594
3795
|
isSymbolicLink: false,
|
|
3595
|
-
mode:
|
|
3596
|
-
size:
|
|
3597
|
-
mtime: new Date(
|
|
3796
|
+
mode: entry.mode,
|
|
3797
|
+
size: entry.size,
|
|
3798
|
+
mtime: new Date(entry.mtime)
|
|
3598
3799
|
};
|
|
3599
3800
|
}
|
|
3600
3801
|
async lstat(filePath) {
|
|
3601
3802
|
const normalized = this.#normalizePath(filePath);
|
|
3602
3803
|
const prefixed = this.#prefixPath(normalized);
|
|
3603
|
-
const
|
|
3604
|
-
|
|
3605
|
-
|
|
3804
|
+
const [entry] = rowsOf2(
|
|
3805
|
+
entryRow3,
|
|
3806
|
+
await this.#query(
|
|
3807
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3808
|
+
[prefixed]
|
|
3809
|
+
)
|
|
3606
3810
|
);
|
|
3607
|
-
const entry = rows[0];
|
|
3608
3811
|
if (!entry) {
|
|
3609
3812
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
3610
3813
|
}
|
|
@@ -3612,19 +3815,21 @@ var PostgresFs = class _PostgresFs {
|
|
|
3612
3815
|
isFile: entry.type === "file",
|
|
3613
3816
|
isDirectory: entry.type === "directory",
|
|
3614
3817
|
isSymbolicLink: entry.type === "symlink",
|
|
3615
|
-
mode:
|
|
3616
|
-
size:
|
|
3617
|
-
mtime: new Date(
|
|
3818
|
+
mode: entry.mode,
|
|
3819
|
+
size: entry.size,
|
|
3820
|
+
mtime: new Date(entry.mtime)
|
|
3618
3821
|
};
|
|
3619
3822
|
}
|
|
3620
3823
|
async mkdir(dirPath, options) {
|
|
3621
3824
|
const normalized = this.#normalizePath(dirPath);
|
|
3622
3825
|
const prefixed = this.#prefixPath(normalized);
|
|
3623
|
-
const
|
|
3624
|
-
|
|
3625
|
-
|
|
3826
|
+
const [existing] = rowsOf2(
|
|
3827
|
+
typeRow3,
|
|
3828
|
+
await this.#query(
|
|
3829
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3830
|
+
[prefixed]
|
|
3831
|
+
)
|
|
3626
3832
|
);
|
|
3627
|
-
const existing = existingRows[0];
|
|
3628
3833
|
if (existing) {
|
|
3629
3834
|
if (options?.recursive) {
|
|
3630
3835
|
return;
|
|
@@ -3634,16 +3839,18 @@ var PostgresFs = class _PostgresFs {
|
|
|
3634
3839
|
await this.#useTransaction(async (client) => {
|
|
3635
3840
|
if (options?.recursive) {
|
|
3636
3841
|
const rootPath = this.#root || "/";
|
|
3637
|
-
const relativePath =
|
|
3842
|
+
const relativePath = path4.posix.relative(rootPath, prefixed);
|
|
3638
3843
|
const segments = relativePath.split("/").filter(Boolean);
|
|
3639
3844
|
let currentPath = rootPath;
|
|
3640
3845
|
for (const segment of segments) {
|
|
3641
|
-
currentPath =
|
|
3642
|
-
const
|
|
3643
|
-
|
|
3644
|
-
|
|
3846
|
+
currentPath = path4.posix.join(currentPath, segment);
|
|
3847
|
+
const [exists] = rowsOf2(
|
|
3848
|
+
typeRow3,
|
|
3849
|
+
await client.query(
|
|
3850
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3851
|
+
[currentPath]
|
|
3852
|
+
)
|
|
3645
3853
|
);
|
|
3646
|
-
const exists = result.rows[0];
|
|
3647
3854
|
if (!exists) {
|
|
3648
3855
|
await client.query(
|
|
3649
3856
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime) VALUES ($1, 'directory', 493, 0, $2)`,
|
|
@@ -3655,11 +3862,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3655
3862
|
}
|
|
3656
3863
|
} else {
|
|
3657
3864
|
const parent = this.#dirname(prefixed);
|
|
3658
|
-
const
|
|
3659
|
-
|
|
3660
|
-
|
|
3865
|
+
const [parentEntry] = rowsOf2(
|
|
3866
|
+
typeRow3,
|
|
3867
|
+
await client.query(
|
|
3868
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3869
|
+
[parent]
|
|
3870
|
+
)
|
|
3661
3871
|
);
|
|
3662
|
-
const parentEntry = parentResult.rows[0];
|
|
3663
3872
|
if (!parentEntry) {
|
|
3664
3873
|
throw new Error(`mkdir: parent does not exist: ${parent}`);
|
|
3665
3874
|
}
|
|
@@ -3677,11 +3886,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3677
3886
|
const normalized = this.#normalizePath(dirPath);
|
|
3678
3887
|
const prefixed = this.#prefixPath(normalized);
|
|
3679
3888
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3680
|
-
const
|
|
3681
|
-
|
|
3682
|
-
|
|
3889
|
+
const [entry] = rowsOf2(
|
|
3890
|
+
typeRow3,
|
|
3891
|
+
await this.#query(
|
|
3892
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3893
|
+
[resolved]
|
|
3894
|
+
)
|
|
3683
3895
|
);
|
|
3684
|
-
const entry = entryRows[0];
|
|
3685
3896
|
if (!entry) {
|
|
3686
3897
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
3687
3898
|
}
|
|
@@ -3689,24 +3900,29 @@ var PostgresFs = class _PostgresFs {
|
|
|
3689
3900
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
3690
3901
|
}
|
|
3691
3902
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
3692
|
-
const rows =
|
|
3693
|
-
|
|
3903
|
+
const rows = rowsOf2(
|
|
3904
|
+
pathRow3,
|
|
3905
|
+
await this.#query(
|
|
3906
|
+
`SELECT path FROM ${this.#t("fs_entries")}
|
|
3694
3907
|
WHERE path LIKE $1 || '%'
|
|
3695
3908
|
AND path != $2
|
|
3696
3909
|
AND path NOT LIKE $1 || '%/%'`,
|
|
3697
|
-
|
|
3910
|
+
[prefix, resolved]
|
|
3911
|
+
)
|
|
3698
3912
|
);
|
|
3699
|
-
return rows.map((row) =>
|
|
3913
|
+
return rows.map((row) => path4.posix.basename(row.path));
|
|
3700
3914
|
}
|
|
3701
3915
|
async readdirWithFileTypes(dirPath) {
|
|
3702
3916
|
const normalized = this.#normalizePath(dirPath);
|
|
3703
3917
|
const prefixed = this.#prefixPath(normalized);
|
|
3704
3918
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3705
|
-
const
|
|
3706
|
-
|
|
3707
|
-
|
|
3919
|
+
const [entry] = rowsOf2(
|
|
3920
|
+
typeRow3,
|
|
3921
|
+
await this.#query(
|
|
3922
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3923
|
+
[resolved]
|
|
3924
|
+
)
|
|
3708
3925
|
);
|
|
3709
|
-
const entry = entryRows[0];
|
|
3710
3926
|
if (!entry) {
|
|
3711
3927
|
throw new Error(`ENOENT: no such file or directory: ${dirPath}`);
|
|
3712
3928
|
}
|
|
@@ -3714,15 +3930,18 @@ var PostgresFs = class _PostgresFs {
|
|
|
3714
3930
|
throw new Error(`ENOTDIR: not a directory: ${dirPath}`);
|
|
3715
3931
|
}
|
|
3716
3932
|
const prefix = resolved === "/" ? "/" : resolved + "/";
|
|
3717
|
-
const rows =
|
|
3718
|
-
|
|
3933
|
+
const rows = rowsOf2(
|
|
3934
|
+
pathTypeRow3,
|
|
3935
|
+
await this.#query(
|
|
3936
|
+
`SELECT path, type FROM ${this.#t("fs_entries")}
|
|
3719
3937
|
WHERE path LIKE $1 || '%'
|
|
3720
3938
|
AND path != $2
|
|
3721
3939
|
AND path NOT LIKE $1 || '%/%'`,
|
|
3722
|
-
|
|
3940
|
+
[prefix, resolved]
|
|
3941
|
+
)
|
|
3723
3942
|
);
|
|
3724
3943
|
return rows.map((row) => ({
|
|
3725
|
-
name:
|
|
3944
|
+
name: path4.posix.basename(row.path),
|
|
3726
3945
|
isFile: row.type === "file",
|
|
3727
3946
|
isDirectory: row.type === "directory",
|
|
3728
3947
|
isSymbolicLink: row.type === "symlink"
|
|
@@ -3731,11 +3950,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3731
3950
|
async rm(filePath, options) {
|
|
3732
3951
|
const normalized = this.#normalizePath(filePath);
|
|
3733
3952
|
const prefixed = this.#prefixPath(normalized);
|
|
3734
|
-
const
|
|
3735
|
-
|
|
3736
|
-
|
|
3953
|
+
const [entry] = rowsOf2(
|
|
3954
|
+
typeRow3,
|
|
3955
|
+
await this.#query(
|
|
3956
|
+
`SELECT type FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3957
|
+
[prefixed]
|
|
3958
|
+
)
|
|
3737
3959
|
);
|
|
3738
|
-
const entry = rows[0];
|
|
3739
3960
|
if (!entry) {
|
|
3740
3961
|
if (options?.force) {
|
|
3741
3962
|
return;
|
|
@@ -3744,11 +3965,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3744
3965
|
}
|
|
3745
3966
|
await this.#useTransaction(async (client) => {
|
|
3746
3967
|
if (entry.type === "directory") {
|
|
3747
|
-
const
|
|
3748
|
-
|
|
3749
|
-
|
|
3968
|
+
const children = rowsOf2(
|
|
3969
|
+
existsRow2,
|
|
3970
|
+
await client.query(
|
|
3971
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path LIKE $1 || '/%') AS exists`,
|
|
3972
|
+
[prefixed]
|
|
3973
|
+
)
|
|
3750
3974
|
);
|
|
3751
|
-
if (
|
|
3975
|
+
if (children[0].exists && !options?.recursive) {
|
|
3752
3976
|
throw new Error(`ENOTEMPTY: directory not empty: ${filePath}`);
|
|
3753
3977
|
}
|
|
3754
3978
|
await client.query(
|
|
@@ -3768,11 +3992,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
3768
3992
|
const destNormalized = this.#normalizePath(dest);
|
|
3769
3993
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3770
3994
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3771
|
-
const
|
|
3772
|
-
|
|
3773
|
-
|
|
3995
|
+
const [srcEntry] = rowsOf2(
|
|
3996
|
+
entryRow3,
|
|
3997
|
+
await this.#query(
|
|
3998
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
3999
|
+
[srcPrefixed]
|
|
4000
|
+
)
|
|
3774
4001
|
);
|
|
3775
|
-
const srcEntry = srcRows[0];
|
|
3776
4002
|
if (!srcEntry) {
|
|
3777
4003
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
3778
4004
|
}
|
|
@@ -3782,13 +4008,16 @@ var PostgresFs = class _PostgresFs {
|
|
|
3782
4008
|
await this.#useTransaction(async (client) => {
|
|
3783
4009
|
await this.#ensureParentExists(destPrefixed, client);
|
|
3784
4010
|
if (srcEntry.type === "directory") {
|
|
3785
|
-
const
|
|
3786
|
-
|
|
3787
|
-
|
|
4011
|
+
const allEntries = rowsOf2(
|
|
4012
|
+
entryRow3,
|
|
4013
|
+
await client.query(
|
|
4014
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%'`,
|
|
4015
|
+
[srcPrefixed]
|
|
4016
|
+
)
|
|
3788
4017
|
);
|
|
3789
|
-
for (const entry of
|
|
3790
|
-
const relativePath =
|
|
3791
|
-
const newPath =
|
|
4018
|
+
for (const entry of allEntries) {
|
|
4019
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
4020
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3792
4021
|
await client.query(
|
|
3793
4022
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
3794
4023
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -3807,11 +4036,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3807
4036
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3808
4037
|
[newPath]
|
|
3809
4038
|
);
|
|
3810
|
-
const
|
|
3811
|
-
|
|
3812
|
-
|
|
4039
|
+
const chunks = rowsOf2(
|
|
4040
|
+
chunkRow3,
|
|
4041
|
+
await client.query(
|
|
4042
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4043
|
+
[entry.path]
|
|
4044
|
+
)
|
|
3813
4045
|
);
|
|
3814
|
-
for (const chunk of
|
|
4046
|
+
for (const chunk of chunks) {
|
|
3815
4047
|
await client.query(
|
|
3816
4048
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3817
4049
|
[newPath, chunk.chunk_index, chunk.data]
|
|
@@ -3834,15 +4066,18 @@ var PostgresFs = class _PostgresFs {
|
|
|
3834
4066
|
]
|
|
3835
4067
|
);
|
|
3836
4068
|
if (srcEntry.type === "file") {
|
|
3837
|
-
const
|
|
3838
|
-
|
|
3839
|
-
|
|
4069
|
+
const chunks = rowsOf2(
|
|
4070
|
+
chunkRow3,
|
|
4071
|
+
await client.query(
|
|
4072
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4073
|
+
[srcPrefixed]
|
|
4074
|
+
)
|
|
3840
4075
|
);
|
|
3841
4076
|
await client.query(
|
|
3842
4077
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3843
4078
|
[destPrefixed]
|
|
3844
4079
|
);
|
|
3845
|
-
for (const chunk of
|
|
4080
|
+
for (const chunk of chunks) {
|
|
3846
4081
|
await client.query(
|
|
3847
4082
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3848
4083
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -3857,28 +4092,33 @@ var PostgresFs = class _PostgresFs {
|
|
|
3857
4092
|
const destNormalized = this.#normalizePath(dest);
|
|
3858
4093
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
3859
4094
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
3860
|
-
const
|
|
3861
|
-
|
|
3862
|
-
|
|
4095
|
+
const [srcEntry] = rowsOf2(
|
|
4096
|
+
entryRow3,
|
|
4097
|
+
await this.#query(
|
|
4098
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4099
|
+
[srcPrefixed]
|
|
4100
|
+
)
|
|
3863
4101
|
);
|
|
3864
|
-
const srcEntry = srcRows[0];
|
|
3865
4102
|
if (!srcEntry) {
|
|
3866
4103
|
throw new Error(`ENOENT: no such file or directory: ${src}`);
|
|
3867
4104
|
}
|
|
3868
4105
|
await this.#useTransaction(async (client) => {
|
|
3869
4106
|
await this.#ensureParentExists(destPrefixed, client);
|
|
3870
4107
|
if (srcEntry.type === "directory") {
|
|
3871
|
-
const
|
|
3872
|
-
|
|
3873
|
-
|
|
4108
|
+
const allEntries = rowsOf2(
|
|
4109
|
+
entryRow3,
|
|
4110
|
+
await client.query(
|
|
4111
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%' ORDER BY path DESC`,
|
|
4112
|
+
[srcPrefixed]
|
|
4113
|
+
)
|
|
3874
4114
|
);
|
|
3875
4115
|
await client.query(
|
|
3876
4116
|
`DELETE FROM ${this.#t("fs_entries")} WHERE path = $1 OR path LIKE $1 || '/%'`,
|
|
3877
4117
|
[destPrefixed]
|
|
3878
4118
|
);
|
|
3879
|
-
for (const entry of [...
|
|
3880
|
-
const relativePath =
|
|
3881
|
-
const newPath =
|
|
4119
|
+
for (const entry of [...allEntries].reverse()) {
|
|
4120
|
+
const relativePath = path4.posix.relative(srcPrefixed, entry.path);
|
|
4121
|
+
const newPath = path4.posix.join(destPrefixed, relativePath);
|
|
3882
4122
|
await client.query(
|
|
3883
4123
|
`INSERT INTO ${this.#t("fs_entries")} (path, type, mode, size, mtime, symlink_target)
|
|
3884
4124
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
@@ -3897,11 +4137,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3897
4137
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3898
4138
|
[newPath]
|
|
3899
4139
|
);
|
|
3900
|
-
const
|
|
3901
|
-
|
|
3902
|
-
|
|
4140
|
+
const chunks = rowsOf2(
|
|
4141
|
+
chunkRow3,
|
|
4142
|
+
await client.query(
|
|
4143
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4144
|
+
[entry.path]
|
|
4145
|
+
)
|
|
3903
4146
|
);
|
|
3904
|
-
for (const chunk of
|
|
4147
|
+
for (const chunk of chunks) {
|
|
3905
4148
|
await client.query(
|
|
3906
4149
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3907
4150
|
[newPath, chunk.chunk_index, chunk.data]
|
|
@@ -3932,11 +4175,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
3932
4175
|
`DELETE FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
3933
4176
|
[destPrefixed]
|
|
3934
4177
|
);
|
|
3935
|
-
const
|
|
3936
|
-
|
|
3937
|
-
|
|
4178
|
+
const chunks = rowsOf2(
|
|
4179
|
+
chunkRow3,
|
|
4180
|
+
await client.query(
|
|
4181
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4182
|
+
[srcPrefixed]
|
|
4183
|
+
)
|
|
3938
4184
|
);
|
|
3939
|
-
for (const chunk of
|
|
4185
|
+
for (const chunk of chunks) {
|
|
3940
4186
|
await client.query(
|
|
3941
4187
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
3942
4188
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -3951,7 +4197,7 @@ var PostgresFs = class _PostgresFs {
|
|
|
3951
4197
|
});
|
|
3952
4198
|
}
|
|
3953
4199
|
resolvePath(base, relativePath) {
|
|
3954
|
-
return
|
|
4200
|
+
return path4.posix.resolve(base, relativePath);
|
|
3955
4201
|
}
|
|
3956
4202
|
getAllPaths() {
|
|
3957
4203
|
throw new Error(
|
|
@@ -3959,8 +4205,11 @@ var PostgresFs = class _PostgresFs {
|
|
|
3959
4205
|
);
|
|
3960
4206
|
}
|
|
3961
4207
|
async getAllPathsAsync() {
|
|
3962
|
-
const rows =
|
|
3963
|
-
|
|
4208
|
+
const rows = rowsOf2(
|
|
4209
|
+
pathRow3,
|
|
4210
|
+
await this.#query(
|
|
4211
|
+
`SELECT path FROM ${this.#t("fs_entries")} ORDER BY path`
|
|
4212
|
+
)
|
|
3964
4213
|
);
|
|
3965
4214
|
return rows.map((row) => row.path);
|
|
3966
4215
|
}
|
|
@@ -3968,9 +4217,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
3968
4217
|
const normalized = this.#normalizePath(filePath);
|
|
3969
4218
|
const prefixed = this.#prefixPath(normalized);
|
|
3970
4219
|
const resolved = await this.#resolveSymlink(prefixed);
|
|
3971
|
-
const rows =
|
|
3972
|
-
|
|
3973
|
-
|
|
4220
|
+
const rows = rowsOf2(
|
|
4221
|
+
existsRow2,
|
|
4222
|
+
await this.#query(
|
|
4223
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4224
|
+
[resolved]
|
|
4225
|
+
)
|
|
3974
4226
|
);
|
|
3975
4227
|
if (!rows[0].exists) {
|
|
3976
4228
|
throw new Error(`ENOENT: no such file or directory: ${filePath}`);
|
|
@@ -4003,9 +4255,12 @@ var PostgresFs = class _PostgresFs {
|
|
|
4003
4255
|
async symlink(target, linkPath) {
|
|
4004
4256
|
const normalized = this.#normalizePath(linkPath);
|
|
4005
4257
|
const prefixed = this.#prefixPath(normalized);
|
|
4006
|
-
const existingRows =
|
|
4007
|
-
|
|
4008
|
-
|
|
4258
|
+
const existingRows = rowsOf2(
|
|
4259
|
+
existsRow2,
|
|
4260
|
+
await this.#query(
|
|
4261
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4262
|
+
[prefixed]
|
|
4263
|
+
)
|
|
4009
4264
|
);
|
|
4010
4265
|
if (existingRows[0].exists) {
|
|
4011
4266
|
throw new Error(`EEXIST: file already exists: ${linkPath}`);
|
|
@@ -4024,20 +4279,25 @@ var PostgresFs = class _PostgresFs {
|
|
|
4024
4279
|
const destNormalized = this.#normalizePath(newPath);
|
|
4025
4280
|
const srcPrefixed = this.#prefixPath(srcNormalized);
|
|
4026
4281
|
const destPrefixed = this.#prefixPath(destNormalized);
|
|
4027
|
-
const
|
|
4028
|
-
|
|
4029
|
-
|
|
4282
|
+
const [srcEntry] = rowsOf2(
|
|
4283
|
+
entryRow3,
|
|
4284
|
+
await this.#query(
|
|
4285
|
+
`SELECT * FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4286
|
+
[srcPrefixed]
|
|
4287
|
+
)
|
|
4030
4288
|
);
|
|
4031
|
-
const srcEntry = srcRows[0];
|
|
4032
4289
|
if (!srcEntry) {
|
|
4033
4290
|
throw new Error(`ENOENT: no such file or directory: ${existingPath}`);
|
|
4034
4291
|
}
|
|
4035
4292
|
if (srcEntry.type !== "file") {
|
|
4036
4293
|
throw new Error(`link: not supported for directories: ${existingPath}`);
|
|
4037
4294
|
}
|
|
4038
|
-
const existingRows =
|
|
4039
|
-
|
|
4040
|
-
|
|
4295
|
+
const existingRows = rowsOf2(
|
|
4296
|
+
existsRow2,
|
|
4297
|
+
await this.#query(
|
|
4298
|
+
`SELECT EXISTS(SELECT 1 FROM ${this.#t("fs_entries")} WHERE path = $1) AS exists`,
|
|
4299
|
+
[destPrefixed]
|
|
4300
|
+
)
|
|
4041
4301
|
);
|
|
4042
4302
|
if (existingRows[0].exists) {
|
|
4043
4303
|
throw new Error(`EEXIST: file already exists: ${newPath}`);
|
|
@@ -4049,11 +4309,14 @@ var PostgresFs = class _PostgresFs {
|
|
|
4049
4309
|
VALUES ($1, 'file', $2, $3, $4)`,
|
|
4050
4310
|
[destPrefixed, srcEntry.mode, srcEntry.size, Date.now()]
|
|
4051
4311
|
);
|
|
4052
|
-
const
|
|
4053
|
-
|
|
4054
|
-
|
|
4312
|
+
const chunks = rowsOf2(
|
|
4313
|
+
chunkRow3,
|
|
4314
|
+
await client.query(
|
|
4315
|
+
`SELECT chunk_index, data FROM ${this.#t("fs_chunks")} WHERE path = $1`,
|
|
4316
|
+
[srcPrefixed]
|
|
4317
|
+
)
|
|
4055
4318
|
);
|
|
4056
|
-
for (const chunk of
|
|
4319
|
+
for (const chunk of chunks) {
|
|
4057
4320
|
await client.query(
|
|
4058
4321
|
`INSERT INTO ${this.#t("fs_chunks")} (path, chunk_index, data) VALUES ($1, $2, $3)`,
|
|
4059
4322
|
[destPrefixed, chunk.chunk_index, chunk.data]
|
|
@@ -4064,11 +4327,13 @@ var PostgresFs = class _PostgresFs {
|
|
|
4064
4327
|
async readlink(linkPath) {
|
|
4065
4328
|
const normalized = this.#normalizePath(linkPath);
|
|
4066
4329
|
const prefixed = this.#prefixPath(normalized);
|
|
4067
|
-
const
|
|
4068
|
-
|
|
4069
|
-
|
|
4330
|
+
const [entry] = rowsOf2(
|
|
4331
|
+
linkRow3,
|
|
4332
|
+
await this.#query(
|
|
4333
|
+
`SELECT type, symlink_target FROM ${this.#t("fs_entries")} WHERE path = $1`,
|
|
4334
|
+
[prefixed]
|
|
4335
|
+
)
|
|
4070
4336
|
);
|
|
4071
|
-
const entry = rows[0];
|
|
4072
4337
|
if (!entry) {
|
|
4073
4338
|
throw new Error(`ENOENT: no such file or directory: ${linkPath}`);
|
|
4074
4339
|
}
|
|
@@ -4087,29 +4352,29 @@ var ScopedFs = class {
|
|
|
4087
4352
|
this.#base = options.base;
|
|
4088
4353
|
this.#prefix = options.prefix.replace(/\/$/, "");
|
|
4089
4354
|
}
|
|
4090
|
-
#scope(
|
|
4091
|
-
return `${this.#prefix}${
|
|
4355
|
+
#scope(path6) {
|
|
4356
|
+
return `${this.#prefix}${path6}`;
|
|
4092
4357
|
}
|
|
4093
|
-
#unscope(
|
|
4094
|
-
if (
|
|
4358
|
+
#unscope(path6) {
|
|
4359
|
+
if (path6 === this.#prefix) {
|
|
4095
4360
|
return "/";
|
|
4096
4361
|
}
|
|
4097
|
-
if (
|
|
4098
|
-
return
|
|
4362
|
+
if (path6.startsWith(this.#prefix + "/")) {
|
|
4363
|
+
return path6.slice(this.#prefix.length) || "/";
|
|
4099
4364
|
}
|
|
4100
|
-
return
|
|
4365
|
+
return path6;
|
|
4101
4366
|
}
|
|
4102
|
-
async writeFile(
|
|
4103
|
-
await this.#base.writeFile(this.#scope(
|
|
4367
|
+
async writeFile(path6, content, options) {
|
|
4368
|
+
await this.#base.writeFile(this.#scope(path6), content, options);
|
|
4104
4369
|
}
|
|
4105
|
-
async appendFile(
|
|
4106
|
-
await this.#base.appendFile(this.#scope(
|
|
4370
|
+
async appendFile(path6, content, options) {
|
|
4371
|
+
await this.#base.appendFile(this.#scope(path6), content, options);
|
|
4107
4372
|
}
|
|
4108
|
-
async mkdir(
|
|
4109
|
-
return this.#base.mkdir(this.#scope(
|
|
4373
|
+
async mkdir(path6, options) {
|
|
4374
|
+
return this.#base.mkdir(this.#scope(path6), options);
|
|
4110
4375
|
}
|
|
4111
|
-
async rm(
|
|
4112
|
-
await this.#base.rm(this.#scope(
|
|
4376
|
+
async rm(path6, options) {
|
|
4377
|
+
await this.#base.rm(this.#scope(path6), options);
|
|
4113
4378
|
}
|
|
4114
4379
|
async cp(src, dest, options) {
|
|
4115
4380
|
await this.#base.cp(this.#scope(src), this.#scope(dest), options);
|
|
@@ -4117,8 +4382,8 @@ var ScopedFs = class {
|
|
|
4117
4382
|
async mv(src, dest) {
|
|
4118
4383
|
await this.#base.mv(this.#scope(src), this.#scope(dest));
|
|
4119
4384
|
}
|
|
4120
|
-
async chmod(
|
|
4121
|
-
return this.#base.chmod(this.#scope(
|
|
4385
|
+
async chmod(path6, mode) {
|
|
4386
|
+
return this.#base.chmod(this.#scope(path6), mode);
|
|
4122
4387
|
}
|
|
4123
4388
|
async symlink(target, linkPath) {
|
|
4124
4389
|
await this.#base.symlink(target, this.#scope(linkPath));
|
|
@@ -4126,35 +4391,35 @@ var ScopedFs = class {
|
|
|
4126
4391
|
async link(existingPath, newPath) {
|
|
4127
4392
|
await this.#base.link(this.#scope(existingPath), this.#scope(newPath));
|
|
4128
4393
|
}
|
|
4129
|
-
readFile(
|
|
4130
|
-
return this.#base.readFile(this.#scope(
|
|
4394
|
+
readFile(path6, options) {
|
|
4395
|
+
return this.#base.readFile(this.#scope(path6), options);
|
|
4131
4396
|
}
|
|
4132
|
-
readFileBuffer(
|
|
4133
|
-
return this.#base.readFileBuffer(this.#scope(
|
|
4397
|
+
readFileBuffer(path6) {
|
|
4398
|
+
return this.#base.readFileBuffer(this.#scope(path6));
|
|
4134
4399
|
}
|
|
4135
|
-
stat(
|
|
4136
|
-
return this.#base.stat(this.#scope(
|
|
4400
|
+
stat(path6) {
|
|
4401
|
+
return this.#base.stat(this.#scope(path6));
|
|
4137
4402
|
}
|
|
4138
|
-
lstat(
|
|
4139
|
-
return this.#base.lstat(this.#scope(
|
|
4403
|
+
lstat(path6) {
|
|
4404
|
+
return this.#base.lstat(this.#scope(path6));
|
|
4140
4405
|
}
|
|
4141
|
-
readdir(
|
|
4142
|
-
return this.#base.readdir(this.#scope(
|
|
4406
|
+
readdir(path6) {
|
|
4407
|
+
return this.#base.readdir(this.#scope(path6));
|
|
4143
4408
|
}
|
|
4144
|
-
readdirWithFileTypes(
|
|
4145
|
-
return this.#base.readdirWithFileTypes(this.#scope(
|
|
4409
|
+
readdirWithFileTypes(path6) {
|
|
4410
|
+
return this.#base.readdirWithFileTypes(this.#scope(path6));
|
|
4146
4411
|
}
|
|
4147
|
-
exists(
|
|
4148
|
-
return this.#base.exists(this.#scope(
|
|
4412
|
+
exists(path6) {
|
|
4413
|
+
return this.#base.exists(this.#scope(path6));
|
|
4149
4414
|
}
|
|
4150
|
-
readlink(
|
|
4151
|
-
return this.#base.readlink(this.#scope(
|
|
4415
|
+
readlink(path6) {
|
|
4416
|
+
return this.#base.readlink(this.#scope(path6));
|
|
4152
4417
|
}
|
|
4153
|
-
realpath(
|
|
4154
|
-
return this.#base.realpath(this.#scope(
|
|
4418
|
+
realpath(path6) {
|
|
4419
|
+
return this.#base.realpath(this.#scope(path6)).then((p) => this.#unscope(p));
|
|
4155
4420
|
}
|
|
4156
|
-
utimes(
|
|
4157
|
-
return this.#base.utimes(this.#scope(
|
|
4421
|
+
utimes(path6, atime, mtime) {
|
|
4422
|
+
return this.#base.utimes(this.#scope(path6), atime, mtime);
|
|
4158
4423
|
}
|
|
4159
4424
|
resolvePath(base, relativePath) {
|
|
4160
4425
|
return this.#base.resolvePath(base, relativePath);
|
|
@@ -4577,18 +4842,17 @@ import { BashTransformPipeline } from "just-bash";
|
|
|
4577
4842
|
|
|
4578
4843
|
// packages/text2sql/src/lib/agents/sql-transform-plugins.ts
|
|
4579
4844
|
import { parse as parse2, serialize } from "just-bash";
|
|
4580
|
-
import { createHash as
|
|
4581
|
-
import * as
|
|
4845
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
4846
|
+
import * as path5 from "node:path";
|
|
4582
4847
|
import {
|
|
4583
4848
|
BashException,
|
|
4584
4849
|
asStaticWordText as asStaticWordText2
|
|
4585
4850
|
} from "@deepagents/context";
|
|
4851
|
+
function isRecord(value) {
|
|
4852
|
+
return typeof value === "object" && value !== null;
|
|
4853
|
+
}
|
|
4586
4854
|
function isScriptNode(value) {
|
|
4587
|
-
|
|
4588
|
-
return false;
|
|
4589
|
-
}
|
|
4590
|
-
const node = value;
|
|
4591
|
-
return node.type === "Script" && Array.isArray(node.statements);
|
|
4855
|
+
return isRecord(value) && value.type === "Script" && Array.isArray(value.statements);
|
|
4592
4856
|
}
|
|
4593
4857
|
var BLOCKED_DB_CLIENT_COMMANDS = /* @__PURE__ */ new Set([
|
|
4594
4858
|
"psql",
|
|
@@ -4678,11 +4942,7 @@ function wordContainsBlockedCommand(word, context, mode) {
|
|
|
4678
4942
|
if (!word) {
|
|
4679
4943
|
return false;
|
|
4680
4944
|
}
|
|
4681
|
-
return wordPartContainsBlockedCommand(
|
|
4682
|
-
word.parts,
|
|
4683
|
-
context,
|
|
4684
|
-
mode
|
|
4685
|
-
);
|
|
4945
|
+
return wordPartContainsBlockedCommand(word.parts, context, mode);
|
|
4686
4946
|
}
|
|
4687
4947
|
function wordPartContainsBlockedCommand(parts, context, mode) {
|
|
4688
4948
|
for (const part of parts) {
|
|
@@ -4693,6 +4953,9 @@ function wordPartContainsBlockedCommand(parts, context, mode) {
|
|
|
4693
4953
|
return false;
|
|
4694
4954
|
}
|
|
4695
4955
|
function partContainsBlockedCommand(node, context, mode) {
|
|
4956
|
+
if (!isRecord(node)) {
|
|
4957
|
+
return false;
|
|
4958
|
+
}
|
|
4696
4959
|
const type = node.type;
|
|
4697
4960
|
if (type === "CommandSubstitution" || type === "ProcessSubstitution") {
|
|
4698
4961
|
if (isScriptNode(node.body)) {
|
|
@@ -4709,27 +4972,13 @@ function partContainsBlockedCommand(node, context, mode) {
|
|
|
4709
4972
|
}
|
|
4710
4973
|
for (const value of Object.values(node)) {
|
|
4711
4974
|
if (Array.isArray(value)) {
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
if (partContainsBlockedCommand(
|
|
4715
|
-
item,
|
|
4716
|
-
context,
|
|
4717
|
-
mode
|
|
4718
|
-
)) {
|
|
4719
|
-
return true;
|
|
4720
|
-
}
|
|
4721
|
-
}
|
|
4975
|
+
if (wordPartContainsBlockedCommand(value, context, mode)) {
|
|
4976
|
+
return true;
|
|
4722
4977
|
}
|
|
4723
4978
|
continue;
|
|
4724
4979
|
}
|
|
4725
|
-
if (
|
|
4726
|
-
|
|
4727
|
-
value,
|
|
4728
|
-
context,
|
|
4729
|
-
mode
|
|
4730
|
-
)) {
|
|
4731
|
-
return true;
|
|
4732
|
-
}
|
|
4980
|
+
if (partContainsBlockedCommand(value, context, mode)) {
|
|
4981
|
+
return true;
|
|
4733
4982
|
}
|
|
4734
4983
|
}
|
|
4735
4984
|
return false;
|
|
@@ -5072,11 +5321,7 @@ function isBlockedSimpleCommand(command, context, mode, options) {
|
|
|
5072
5321
|
}
|
|
5073
5322
|
if (command.redirections.some((redirection) => {
|
|
5074
5323
|
if (redirection.target.type === "Word") {
|
|
5075
|
-
return wordContainsBlockedCommand(
|
|
5076
|
-
redirection.target,
|
|
5077
|
-
context,
|
|
5078
|
-
mode
|
|
5079
|
-
);
|
|
5324
|
+
return wordContainsBlockedCommand(redirection.target, context, mode);
|
|
5080
5325
|
}
|
|
5081
5326
|
if (redirection.target.type === "HereDoc" && redirection.target.content) {
|
|
5082
5327
|
return wordContainsBlockedCommand(
|
|
@@ -5093,7 +5338,7 @@ function isBlockedSimpleCommand(command, context, mode, options) {
|
|
|
5093
5338
|
if (!commandName) {
|
|
5094
5339
|
return false;
|
|
5095
5340
|
}
|
|
5096
|
-
const normalizedName =
|
|
5341
|
+
const normalizedName = path5.posix.basename(commandName).toLowerCase();
|
|
5097
5342
|
if (BLOCKED_DB_CLIENT_COMMANDS.has(normalizedName)) {
|
|
5098
5343
|
return true;
|
|
5099
5344
|
}
|
|
@@ -5213,10 +5458,8 @@ function wordPartsContainExpansion(parts) {
|
|
|
5213
5458
|
if (part.type === "CommandSubstitution" || part.type === "ParameterExpansion" || part.type === "ArithmeticExpansion") {
|
|
5214
5459
|
return true;
|
|
5215
5460
|
}
|
|
5216
|
-
if (part.type === "DoubleQuoted" &&
|
|
5217
|
-
|
|
5218
|
-
return true;
|
|
5219
|
-
}
|
|
5461
|
+
if (part.type === "DoubleQuoted" && wordPartsContainExpansion(part.parts)) {
|
|
5462
|
+
return true;
|
|
5220
5463
|
}
|
|
5221
5464
|
}
|
|
5222
5465
|
return false;
|
|
@@ -5232,38 +5475,33 @@ function isSqlCommandRequiringRewrite(cmd) {
|
|
|
5232
5475
|
if (!isValidAdapterName(dbName)) return false;
|
|
5233
5476
|
const sqlArgs = cmd.args.slice(2);
|
|
5234
5477
|
if (sqlArgs.length > 1) return true;
|
|
5235
|
-
return sqlArgs.some(
|
|
5236
|
-
(arg) => wordPartsContainExpansion(
|
|
5237
|
-
arg.parts
|
|
5238
|
-
)
|
|
5239
|
-
);
|
|
5478
|
+
return sqlArgs.some((arg) => wordPartsContainExpansion(arg.parts));
|
|
5240
5479
|
}
|
|
5241
5480
|
function extractWordPartText(parts) {
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5481
|
+
return parts.map(wordPartText).join("");
|
|
5482
|
+
}
|
|
5483
|
+
function wordPartText(part) {
|
|
5484
|
+
switch (part.type) {
|
|
5485
|
+
case "Literal":
|
|
5486
|
+
case "SingleQuoted":
|
|
5487
|
+
case "Escaped":
|
|
5488
|
+
return part.value;
|
|
5489
|
+
case "DoubleQuoted":
|
|
5490
|
+
return extractWordPartText(part.parts);
|
|
5491
|
+
case "CommandSubstitution":
|
|
5492
|
+
return part.legacy ? "`" + serialize(part.body).trim() + "`" : "$(" + serialize(part.body).trim() + ")";
|
|
5493
|
+
case "ParameterExpansion":
|
|
5494
|
+
return emitParameterExpansion(part);
|
|
5495
|
+
case "ArithmeticExpansion":
|
|
5496
|
+
return "$((" + (part.expression.originalText ?? "") + "))";
|
|
5497
|
+
default:
|
|
5498
|
+
return "";
|
|
5499
|
+
}
|
|
5261
5500
|
}
|
|
5262
5501
|
function emitParameterExpansion(part) {
|
|
5263
|
-
const parameter = part
|
|
5264
|
-
const operation = part.operation;
|
|
5502
|
+
const { parameter, operation } = part;
|
|
5265
5503
|
if (!operation) return "$" + parameter;
|
|
5266
|
-
if (operation.type === "DefaultValue"
|
|
5504
|
+
if (operation.type === "DefaultValue") {
|
|
5267
5505
|
const fallback = extractWordPartText(operation.word.parts);
|
|
5268
5506
|
const separator = operation.checkEmpty ? ":-" : "-";
|
|
5269
5507
|
return "${" + parameter + separator + fallback + "}";
|
|
@@ -5271,18 +5509,14 @@ function emitParameterExpansion(part) {
|
|
|
5271
5509
|
return "${" + parameter + "}";
|
|
5272
5510
|
}
|
|
5273
5511
|
function extractSqlText(args) {
|
|
5274
|
-
return args.map(
|
|
5275
|
-
(arg) => extractWordPartText(
|
|
5276
|
-
arg.parts
|
|
5277
|
-
)
|
|
5278
|
-
).join(" ");
|
|
5512
|
+
return args.map((arg) => extractWordPartText(arg.parts)).join(" ");
|
|
5279
5513
|
}
|
|
5280
5514
|
function rewriteSqlCommand(cmd, ast) {
|
|
5281
5515
|
const subcommand = asStaticWordText2(cmd.args[0]);
|
|
5282
5516
|
const dbName = asStaticWordText2(cmd.args[1]);
|
|
5283
5517
|
const sqlArgs = cmd.args.slice(2);
|
|
5284
5518
|
const unquotedSql = extractSqlText(sqlArgs);
|
|
5285
|
-
const hash2 =
|
|
5519
|
+
const hash2 = createHash3("sha256").update(serialize(ast)).digest("hex").slice(0, 12);
|
|
5286
5520
|
const sqlPath = `/tmp/sql-inline-${subcommand}-${hash2}.sql`;
|
|
5287
5521
|
const heredocTag = `SQL_${hash2.toUpperCase()}`;
|
|
5288
5522
|
const groupScript = [
|
|
@@ -5394,7 +5628,6 @@ import {
|
|
|
5394
5628
|
} from "@deepagents/context";
|
|
5395
5629
|
|
|
5396
5630
|
// packages/text2sql/src/lib/sql.ts
|
|
5397
|
-
import "@deepagents/agent";
|
|
5398
5631
|
var text2SqlValidationMarker = /* @__PURE__ */ Symbol("Text2SqlValidationError");
|
|
5399
5632
|
var text2SqlUnknownAdapterMarker = /* @__PURE__ */ Symbol("Text2SqlUnknownAdapterError");
|
|
5400
5633
|
var Text2SqlValidationError = class _Text2SqlValidationError extends Error {
|
|
@@ -5455,8 +5688,7 @@ var Text2Sql = class {
|
|
|
5455
5688
|
this.#config = config;
|
|
5456
5689
|
this.#indexer = new AdapterIndexer({
|
|
5457
5690
|
adapters: config.adapters,
|
|
5458
|
-
cache: config.cache
|
|
5459
|
-
lock: config.lock
|
|
5691
|
+
cache: config.cache
|
|
5460
5692
|
});
|
|
5461
5693
|
}
|
|
5462
5694
|
#requireAdapter(name) {
|
|
@@ -5466,13 +5698,6 @@ var Text2Sql = class {
|
|
|
5466
5698
|
}
|
|
5467
5699
|
return adapter;
|
|
5468
5700
|
}
|
|
5469
|
-
#requireModel(op) {
|
|
5470
|
-
const model = this.#config.model;
|
|
5471
|
-
if (!model) {
|
|
5472
|
-
throw new Error(`Text2Sql.${op}() requires a model in Text2SqlConfig`);
|
|
5473
|
-
}
|
|
5474
|
-
return model;
|
|
5475
|
-
}
|
|
5476
5701
|
adapterNames() {
|
|
5477
5702
|
return Object.keys(this.#config.adapters);
|
|
5478
5703
|
}
|
|
@@ -5514,8 +5739,10 @@ var Text2Sql = class {
|
|
|
5514
5739
|
if (!Array.isArray(result)) {
|
|
5515
5740
|
throw new Error("adapter.execute must return an array of rows");
|
|
5516
5741
|
}
|
|
5517
|
-
const
|
|
5518
|
-
|
|
5742
|
+
const rows = result;
|
|
5743
|
+
const [first] = rows;
|
|
5744
|
+
const columns = typeof first === "object" && first !== null ? Object.keys(first) : [];
|
|
5745
|
+
return { rows, columns };
|
|
5519
5746
|
}
|
|
5520
5747
|
async #validateWith(adapter, sql) {
|
|
5521
5748
|
const formatted = adapter.format(sql);
|
|
@@ -5529,18 +5756,6 @@ var Text2Sql = class {
|
|
|
5529
5756
|
onProgress: options.onProgress
|
|
5530
5757
|
});
|
|
5531
5758
|
}
|
|
5532
|
-
async toSql(input, adapterName) {
|
|
5533
|
-
const adapter = this.#requireAdapter(adapterName);
|
|
5534
|
-
const model = this.#requireModel("toSql");
|
|
5535
|
-
const fragments = await this.#indexer.indexAdapter(adapterName);
|
|
5536
|
-
const result = await toSql({
|
|
5537
|
-
input,
|
|
5538
|
-
adapter,
|
|
5539
|
-
fragments,
|
|
5540
|
-
model
|
|
5541
|
-
});
|
|
5542
|
-
return result.sql;
|
|
5543
|
-
}
|
|
5544
5759
|
async toPairs(adapterName, factory) {
|
|
5545
5760
|
const adapter = this.#requireAdapter(adapterName);
|
|
5546
5761
|
const producer = factory(adapter);
|
|
@@ -5679,15 +5894,13 @@ function extractSqlInvocation(command) {
|
|
|
5679
5894
|
return parseSqlQueryInvocation(repairSqlCommand(command));
|
|
5680
5895
|
}
|
|
5681
5896
|
function inputCommand(input) {
|
|
5682
|
-
return input
|
|
5897
|
+
return typeof input === "object" && input !== null && "command" in input ? input.command : void 0;
|
|
5683
5898
|
}
|
|
5684
5899
|
function alreadyValidated(messages, run) {
|
|
5685
5900
|
for (const message of messages ?? []) {
|
|
5686
5901
|
for (const part of message.parts) {
|
|
5687
5902
|
if (!isToolUIPart(part)) continue;
|
|
5688
|
-
const invocation = extractSqlInvocation(
|
|
5689
|
-
inputCommand(part.input)
|
|
5690
|
-
);
|
|
5903
|
+
const invocation = extractSqlInvocation(inputCommand(part.input));
|
|
5691
5904
|
if (invocation?.subcommand === "validate" && invocation.dbName === run.dbName && invocation.sql === run.sql) {
|
|
5692
5905
|
return true;
|
|
5693
5906
|
}
|
|
@@ -5718,7 +5931,6 @@ export {
|
|
|
5718
5931
|
Checkpoint,
|
|
5719
5932
|
FileCache,
|
|
5720
5933
|
FileIndexCache,
|
|
5721
|
-
FileIndexLock,
|
|
5722
5934
|
JsonCache,
|
|
5723
5935
|
MssqlFs,
|
|
5724
5936
|
Point,
|
|
@@ -5745,10 +5957,12 @@ export {
|
|
|
5745
5957
|
filterRelationshipsByTables,
|
|
5746
5958
|
filterTablesByName,
|
|
5747
5959
|
getTablesWithRelated,
|
|
5960
|
+
groundingFor,
|
|
5748
5961
|
hashConfig,
|
|
5749
5962
|
index,
|
|
5750
5963
|
instructions,
|
|
5751
5964
|
isValidAdapterName,
|
|
5965
|
+
jsonCodec,
|
|
5752
5966
|
matchesFilter,
|
|
5753
5967
|
relationship,
|
|
5754
5968
|
repairSqlCommand,
|