@absolutejs/absolute 0.20.0-beta.120 → 0.20.0-beta.122

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/changelog.json +37 -0
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  4. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  5. package/dist/angular/index.js +14 -2
  6. package/dist/angular/index.js.map +5 -4
  7. package/dist/angular/server.js +14 -2
  8. package/dist/angular/server.js.map +5 -4
  9. package/dist/build.js +15 -3
  10. package/dist/build.js.map +6 -5
  11. package/dist/cli/{add-kt4qx8sh.js → add-9sa7e3vd.js} +5 -5
  12. package/dist/cli/{androidEmulatorController-v6chbhem.js → androidEmulatorController-sj141e1c.js} +3 -3
  13. package/dist/cli/{androidNativeWatcher-mgqws6ag.js → androidNativeWatcher-dnp95nk2.js} +3 -3
  14. package/dist/cli/{api-xtq3zqfg.js → api-2hd8cahp.js} +1 -1
  15. package/dist/cli/{compile-5m830csy.js → compile-hywymh6y.js} +1 -1
  16. package/dist/cli/config/server.js +59 -9
  17. package/dist/cli/db-8wweexdp.js +1100 -0
  18. package/dist/cli/{dev-ww30tdrv.js → dev-pdefc9ac.js} +9 -9
  19. package/dist/cli/{emulatorDoctor-y2nqmaha.js → emulatorDoctor-gzarrsex.js} +2 -2
  20. package/dist/cli/{emulatorInstaller-3shdna4g.js → emulatorInstaller-pjw4ex6q.js} +3 -3
  21. package/dist/cli/{expoDevController-zz516pdd.js → expoDevController-weywa74d.js} +3 -3
  22. package/dist/cli/{generate-zy3d9bce.js → generate-069p0dk3.js} +4 -4
  23. package/dist/cli/{htmx-63kt9qj1.js → htmx-5wh1jh75.js} +2 -2
  24. package/dist/cli/{index-t84wxk1p.js → index-00wfffav.js} +50 -8
  25. package/dist/cli/{index-wtyg9cy0.js → index-1ys3dnrs.js} +1 -1
  26. package/dist/cli/{index-knt92dm8.js → index-255xs63d.js} +1 -1
  27. package/dist/cli/{index-wspj2mq3.js → index-3x5wpx5d.js} +1 -1
  28. package/dist/cli/{index-28nxv57v.js → index-5cgsrv62.js} +12 -2
  29. package/dist/cli/{index-mxmg15c5.js → index-ddakkws4.js} +2 -2
  30. package/dist/cli/{index-ce870r79.js → index-erngp7a9.js} +1 -1
  31. package/dist/cli/{index-pa3hmzj7.js → index-j2nw3edf.js} +1 -1
  32. package/dist/cli/{index-1wgc9e0v.js → index-keg69zm1.js} +1 -1
  33. package/dist/cli/{index-5268nwjx.js → index-q3sq287p.js} +1 -1
  34. package/dist/cli/{index-jf1f6npt.js → index-rqbk0b30.js} +1 -1
  35. package/dist/cli/{index-q1d4ns4n.js → index-v26ze17p.js} +1 -1
  36. package/dist/cli/{index-hneb973j.js → index-vkkqe08e.js} +2 -2
  37. package/dist/cli/index.js +23 -18
  38. package/dist/cli/{info-crpftzxh.js → info-d74dr585.js} +1 -1
  39. package/dist/cli/{iosNativeWatcher-8w1gawg4.js → iosNativeWatcher-kggp7j9a.js} +4 -4
  40. package/dist/cli/{iosSimulatorController-5vhqvhg6.js → iosSimulatorController-xcxxfkzx.js} +4 -4
  41. package/dist/cli/{mobile-21vsmrjd.js → mobile-00bqw12c.js} +9 -9
  42. package/dist/cli/{ps-ha7bhpc6.js → ps-8y28kzmb.js} +1 -1
  43. package/dist/cli/{psTui-rxszyyz8.js → psTui-8e96mwgz.js} +1 -1
  44. package/dist/cli/{remoteMacProtocol-dybpgazw.js → remoteMacProtocol-r38jhg44.js} +4 -4
  45. package/dist/cli/{remove-pwfv4wsd.js → remove-3fd1z2hx.js} +4 -4
  46. package/dist/cli/{start-3bhf56tj.js → start-q08avhxg.js} +2 -2
  47. package/dist/cli/{typecheck-7n5599tp.js → typecheck-yj9s13eb.js} +1 -1
  48. package/dist/cli/{workspace-h7czpaqh.js → workspace-e3jt4as8.js} +1 -1
  49. package/dist/client/chunks/index-dk743xs6.js +146 -0
  50. package/dist/client/chunks/index-dk743xs6.js.map +10 -0
  51. package/dist/client/chunks/index-jrcwp722.js +12 -0
  52. package/dist/client/chunks/index-jrcwp722.js.map +10 -0
  53. package/dist/client/chunks/{islands-xj2n8nwf.js → islands-50dg63j9.js} +6 -3
  54. package/dist/client/chunks/{islands-xj2n8nwf.js.map → islands-50dg63j9.js.map} +3 -3
  55. package/dist/client/chunks/{react-pdg4325x.js → react-yq4ss9y4.js} +4 -3
  56. package/dist/client/chunks/{react-pdg4325x.js.map → react-yq4ss9y4.js.map} +2 -2
  57. package/dist/client/index.js +5 -4
  58. package/dist/client/index.js.map +2 -2
  59. package/dist/index.js +15 -3
  60. package/dist/index.js.map +6 -5
  61. package/dist/islands/index.js +14 -2
  62. package/dist/islands/index.js.map +5 -4
  63. package/dist/mobile/index.js +13 -3
  64. package/dist/mobile/index.js.map +4 -4
  65. package/dist/mobile/remoteMacAgentEntry.js +162 -162
  66. package/dist/react/index.js +14 -2
  67. package/dist/react/index.js.map +5 -4
  68. package/dist/react/server.js +14 -2
  69. package/dist/react/server.js.map +5 -4
  70. package/dist/src/cli/scripts/db.d.ts +2 -19
  71. package/dist/src/cli/scripts/dbEngines/detect.d.ts +8 -0
  72. package/dist/src/cli/scripts/dbEngines/mssql.d.ts +4 -0
  73. package/dist/src/cli/scripts/dbEngines/mysql.d.ts +2 -0
  74. package/dist/src/cli/scripts/dbEngines/open.d.ts +2 -0
  75. package/dist/src/cli/scripts/dbEngines/postgres.d.ts +2 -0
  76. package/dist/src/cli/scripts/dbEngines/sqlText.d.ts +13 -0
  77. package/dist/src/cli/scripts/dbEngines/sqlite.d.ts +4 -0
  78. package/dist/src/cli/scripts/dbEngines/values.d.ts +12 -0
  79. package/dist/src/cli/utils.d.ts +7 -0
  80. package/dist/src/client/browserTranslation.d.ts +3 -0
  81. package/dist/src/client/browserTranslationAttributes.d.ts +2 -0
  82. package/dist/src/utils/userAgentFunctions.d.ts +1 -1
  83. package/dist/src/vue/components/Image.d.ts +1 -1
  84. package/dist/svelte/index.js +14 -2
  85. package/dist/svelte/index.js.map +5 -4
  86. package/dist/svelte/server.js +14 -2
  87. package/dist/svelte/server.js.map +5 -4
  88. package/dist/types/db.d.ts +109 -0
  89. package/dist/vue/browser.js +75 -8
  90. package/dist/vue/browser.js.map +5 -4
  91. package/dist/vue/index.js +77 -9
  92. package/dist/vue/index.js.map +6 -5
  93. package/dist/vue/server.js +14 -2
  94. package/dist/vue/server.js.map +5 -4
  95. package/package.json +13 -1
  96. package/dist/cli/db-tejnwt9j.js +0 -238
  97. package/dist/client/chunks/index-5py90ctf.js +0 -87
  98. package/dist/client/chunks/index-5py90ctf.js.map +0 -10
@@ -0,0 +1,1100 @@
1
+ // @bun
2
+ import {
3
+ colors
4
+ } from "./index-8nym68py.js";
5
+ import {
6
+ UNFOUND_INDEX
7
+ } from "./index-czwrxgdj.js";
8
+ import {
9
+ __require
10
+ } from "./index-mywsk201.js";
11
+
12
+ // src/cli/scripts/db.ts
13
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
14
+ import { join as join2 } from "path";
15
+ var {env, spawn } = globalThis.Bun;
16
+
17
+ // src/cli/scripts/dbEngines/detect.ts
18
+ import { existsSync, readFileSync } from "fs";
19
+ import { join } from "path";
20
+ var DRIZZLE_CONFIGS = [
21
+ "drizzle.config.ts",
22
+ "drizzle.config.mts",
23
+ "drizzle.config.js",
24
+ "drizzle.config.mjs",
25
+ "drizzle.config.cjs"
26
+ ];
27
+ var PRISMA_SCHEMAS = ["prisma/schema.prisma", "schema.prisma"];
28
+ var SQLITE_FILE_PATTERN = /\.(db|db3|sqlite|sqlite3)$/i;
29
+ var SUPPORTED_SCHEMES = "postgres://, postgresql://, cockroachdb://, mysql://, mariadb://, singlestore://, file:, sqlite:, libsql://, http(s)://, ws(s)://, sqlserver://, mssql://";
30
+ var SCHEME_FAMILIES = {
31
+ "cockroachdb:": "postgres",
32
+ "file:": "sqlite",
33
+ "http:": "libsql",
34
+ "https:": "libsql",
35
+ "libsql:": "libsql",
36
+ "mariadb:": "mysql",
37
+ "mssql:": "mssql",
38
+ "mysql:": "mysql",
39
+ "postgres:": "postgres",
40
+ "postgresql:": "postgres",
41
+ "singlestore:": "mysql",
42
+ "sqlite:": "sqlite",
43
+ "sqlite3:": "sqlite",
44
+ "sqlserver:": "mssql",
45
+ "ws:": "libsql",
46
+ "wss:": "libsql"
47
+ };
48
+ var REFUSED_SCHEMES = {
49
+ "edgedb:": "Gel (EdgeDB)",
50
+ "gel:": "Gel (EdgeDB)",
51
+ "mongodb:": "MongoDB",
52
+ "mongodb+srv:": "MongoDB"
53
+ };
54
+ var DIALECT_FAMILIES = {
55
+ cockroach: "postgres",
56
+ cockroachdb: "postgres",
57
+ mssql: "mssql",
58
+ mysql: "mysql",
59
+ postgresql: "postgres",
60
+ singlestore: "mysql",
61
+ sqlite: "sqlite",
62
+ sqlserver: "mssql",
63
+ turso: "sqlite"
64
+ };
65
+ var REFUSED_DIALECTS = {
66
+ gel: "Gel (EdgeDB)",
67
+ mongodb: "MongoDB"
68
+ };
69
+ var readText = (path) => existsSync(path) ? readFileSync(path, "utf-8") : undefined;
70
+ var drizzleHint = (cwd) => DRIZZLE_CONFIGS.map((name) => {
71
+ const text = readText(join(cwd, name));
72
+ const dialect = text?.match(/dialect\s*:\s*['"`](\w+)['"`]/)?.[1];
73
+ return dialect === undefined ? undefined : { dialect, source: name };
74
+ }).find((hint) => hint !== undefined);
75
+ var prismaHint = (cwd) => PRISMA_SCHEMAS.map((name) => {
76
+ const text = readText(join(cwd, name));
77
+ const block = text?.match(/datasource\s+\w+\s*\{[^}]*\}/)?.[0];
78
+ const provider = block?.match(/provider\s*=\s*"(\w+)"/)?.[1];
79
+ return provider === undefined ? undefined : { dialect: provider, source: name };
80
+ }).find((hint) => hint !== undefined);
81
+ var readOrmDialect = (cwd) => drizzleHint(cwd) ?? prismaHint(cwd);
82
+ var refuse = (engine, origin) => new Error(`absolute db does not support ${engine} (${origin}): backup/restore works on SQL databases only \u2014 PostgreSQL, CockroachDB, MySQL, MariaDB, SingleStore, SQLite, libSQL/Turso and SQL Server.`);
83
+ var schemeOf = (url) => {
84
+ const match = url.match(/^([a-z][a-z0-9+.-]*:)/i);
85
+ return match?.[1]?.toLowerCase();
86
+ };
87
+ var familyForSchemeless = (url, hint) => {
88
+ const hinted = hint === undefined ? undefined : DIALECT_FAMILIES[hint.dialect];
89
+ if (hinted === "sqlite" || SQLITE_FILE_PATTERN.test(url))
90
+ return "sqlite";
91
+ return;
92
+ };
93
+ var detectTarget = (url, hint) => {
94
+ const scheme = schemeOf(url);
95
+ const refusedScheme = scheme === undefined ? undefined : REFUSED_SCHEMES[scheme];
96
+ if (refusedScheme !== undefined)
97
+ throw refuse(refusedScheme, `${scheme}// URL`);
98
+ const family = scheme === undefined || scheme.length === 2 ? familyForSchemeless(url, hint) : SCHEME_FAMILIES[scheme];
99
+ const refusedDialect = hint === undefined ? undefined : REFUSED_DIALECTS[hint.dialect];
100
+ if (family === undefined && refusedDialect !== undefined && hint)
101
+ throw refuse(refusedDialect, `${hint.source} declares "${hint.dialect}"`);
102
+ if (family === undefined)
103
+ throw new Error(`Unrecognised database URL${scheme === undefined ? "" : ` scheme "${scheme}"`}. absolute db understands ${SUPPORTED_SCHEMES}, or a path to a .db/.sqlite file.`);
104
+ return { family, url };
105
+ };
106
+ var sqlitePath = (url, cwd) => {
107
+ const withoutScheme = url.replace(/^(sqlite3?|file):(\/\/)?/i, "").replace(/\?.*$/, "");
108
+ const decoded = decodeURIComponent(withoutScheme);
109
+ if (decoded === ":memory:")
110
+ throw new Error("An in-memory SQLite database (:memory:) has nothing to back up or restore; point --url at a database file.");
111
+ const candidates = decoded.startsWith("/") ? [decoded] : [join(cwd, decoded), join(cwd, "prisma", decoded)];
112
+ const found = candidates.find((candidate) => existsSync(candidate));
113
+ if (found === undefined)
114
+ throw new Error(`SQLite database file not found: ${candidates[0]}. Create it (run your migrations) first \u2014 absolute db never creates an empty database.`);
115
+ return found;
116
+ };
117
+
118
+ // src/cli/scripts/dbEngines/sqlText.ts
119
+ var MAX_CHUNK_ROWS = 500;
120
+ var chunkRows = (items, size) => Array.from({ length: Math.ceil(items.length / size) }, (_, idx) => items.slice(idx * size, idx * size + size));
121
+ var insertableColumns = (meta) => meta.columns.filter((col) => col.generated !== true);
122
+ var quoteIdent = (name) => `"${name.replace(/"/g, '""')}"`;
123
+ var quoteMssqlIdent = (name) => `[${name.replace(/]/g, "]]")}]`;
124
+ var quoteMysqlIdent = (name) => `\`${name.replace(/`/g, "``")}\``;
125
+ var rowsPerChunk = (columnCount, paramLimit) => Math.max(1, Math.min(MAX_CHUNK_ROWS, Math.floor(paramLimit / Math.max(1, columnCount))));
126
+ var updatableColumns = (meta) => insertableColumns(meta).map((col) => col.name).filter((name) => !meta.primaryKey.includes(name));
127
+ var conflictClause = (meta) => {
128
+ if (meta.primaryKey.length === 0)
129
+ return "on conflict do nothing";
130
+ const target = meta.primaryKey.map(quoteIdent).join(", ");
131
+ const updatable = updatableColumns(meta);
132
+ if (updatable.length === 0)
133
+ return `on conflict (${target}) do nothing`;
134
+ const sets = updatable.map((name) => `${quoteIdent(name)} = excluded.${quoteIdent(name)}`).join(", ");
135
+ return `on conflict (${target}) do update set ${sets}`;
136
+ };
137
+ var valueGroups = (rowCount, columnCount, slot) => Array.from({ length: rowCount }, (_, rowIdx) => {
138
+ const slots = Array.from({ length: columnCount }, (_cell, colIdx) => slot(rowIdx * columnCount + colIdx));
139
+ return `(${slots.join(", ")})`;
140
+ }).join(", ");
141
+ var mysqlInsert = (meta, rowCount, rowAlias) => {
142
+ const cols = insertableColumns(meta);
143
+ const columnList = cols.map((col) => quoteMysqlIdent(col.name)).join(", ");
144
+ const groups = valueGroups(rowCount, cols.length, () => "?");
145
+ const updatable = updatableColumns(meta);
146
+ const table = quoteMysqlIdent(meta.name);
147
+ const [first] = cols;
148
+ if ((meta.primaryKey.length === 0 || updatable.length === 0) && first !== undefined)
149
+ return `insert into ${table} (${columnList}) values ${groups} on duplicate key update ${quoteMysqlIdent(first.name)} = ${quoteMysqlIdent(first.name)}`;
150
+ const incoming = (name) => rowAlias ? `new_row.${quoteMysqlIdent(name)}` : `values(${quoteMysqlIdent(name)})`;
151
+ const sets = updatable.map((name) => `${quoteMysqlIdent(name)} = ${incoming(name)}`).join(", ");
152
+ const alias = rowAlias ? " as new_row" : "";
153
+ return `insert into ${table} (${columnList}) values ${groups}${alias} on duplicate key update ${sets}`;
154
+ };
155
+ var postgresInsert = (meta, rowCount, overridingSystemValue) => {
156
+ const cols = insertableColumns(meta);
157
+ const columnList = cols.map((col) => quoteIdent(col.name)).join(", ");
158
+ const overriding = overridingSystemValue ? " overriding system value" : "";
159
+ const groups = valueGroups(rowCount, cols.length, (index) => `$${index + 1}`);
160
+ return `insert into ${quoteIdent(meta.name)} (${columnList})${overriding} values ${groups} ${conflictClause(meta)}`;
161
+ };
162
+ var sqliteInsert = (meta, rowCount) => {
163
+ const cols = insertableColumns(meta);
164
+ const columnList = cols.map((col) => quoteIdent(col.name)).join(", ");
165
+ const groups = valueGroups(rowCount, cols.length, () => "?");
166
+ return `insert into ${quoteIdent(meta.name)} (${columnList}) values ${groups} ${conflictClause(meta)}`;
167
+ };
168
+ var mssqlCast = (col, index) => `cast(@p${index} as ${col.sqlType ?? "nvarchar(max)"})`;
169
+ var dependencyOrder = (names, links) => {
170
+ const present = new Set(names);
171
+ const edges = links.filter((link) => present.has(link.from) && present.has(link.to) && link.from !== link.to);
172
+ const indegree = new Map(names.map((name) => [name, 0]));
173
+ edges.forEach((link) => indegree.set(link.from, (indegree.get(link.from) ?? 0) + 1));
174
+ const ready = names.filter((name) => (indegree.get(name) ?? 0) === 0);
175
+ const ordered = [];
176
+ const release = (parent) => edges.filter((link) => link.to === parent).forEach((link) => {
177
+ const next = (indegree.get(link.from) ?? 0) - 1;
178
+ indegree.set(link.from, next);
179
+ if (next === 0)
180
+ ready.push(link.from);
181
+ });
182
+ const drain = () => {
183
+ const head = ready.shift();
184
+ if (head === undefined)
185
+ return;
186
+ ordered.push(head);
187
+ release(head);
188
+ drain();
189
+ };
190
+ drain();
191
+ names.forEach((name) => {
192
+ if (!ordered.includes(name))
193
+ ordered.push(name);
194
+ });
195
+ return ordered;
196
+ };
197
+ var mssqlUpsert = (meta, rowCount, qualifiedTable) => {
198
+ const cols = insertableColumns(meta);
199
+ const names = cols.map((col) => quoteMssqlIdent(col.name));
200
+ const rows = Array.from({ length: rowCount }, (_, rowIdx) => {
201
+ const slots = cols.map((col, colIdx) => mssqlCast(col, rowIdx * cols.length + colIdx));
202
+ return `(${slots.join(", ")})`;
203
+ }).join(", ");
204
+ const identity = cols.some((col) => col.identity === true);
205
+ const identityOn = identity ? `set identity_insert ${qualifiedTable} on; ` : "";
206
+ const identityOff = identity ? ` set identity_insert ${qualifiedTable} off;` : "";
207
+ if (meta.primaryKey.length === 0)
208
+ return `${identityOn}insert into ${qualifiedTable} (${names.join(", ")}) values ${rows};${identityOff}`;
209
+ const match = meta.primaryKey.map((name) => `tgt.${quoteMssqlIdent(name)} = src.${quoteMssqlIdent(name)}`).join(" and ");
210
+ const updatable = updatableColumns(meta);
211
+ const whenMatched = updatable.length === 0 ? "" : ` when matched then update set ${updatable.map((name) => `tgt.${quoteMssqlIdent(name)} = src.${quoteMssqlIdent(name)}`).join(", ")}`;
212
+ const sourceCols = names.map((name) => `src.${name}`).join(", ");
213
+ return `${identityOn}merge into ${qualifiedTable} with (holdlock) as tgt using (values ${rows}) as src (${names.join(", ")}) on ${match}${whenMatched} when not matched then insert (${names.join(", ")}) values (${sourceCols});${identityOff}`;
214
+ };
215
+
216
+ // src/cli/scripts/dbEngines/values.ts
217
+ var INT32_MAX = 2147483647;
218
+ var INT32_MIN = -2147483648;
219
+ var ISO_UTC_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(?:Z|[+-]00:?00)$/;
220
+ var isRecord = (value) => typeof value === "object" && value !== null;
221
+ var isSerializedBuffer = (value) => isRecord(value) && value.type === "Buffer" && Array.isArray(value.data) && value.data.every((byte) => typeof byte === "number");
222
+ var decodeBinary = (value) => isSerializedBuffer(value) ? Buffer.from(value.data) : undefined;
223
+ var isStructured = (value) => Array.isArray(value) || isRecord(value) && !(value instanceof Date) && !Buffer.isBuffer(value);
224
+ var parseJsonText = (value) => {
225
+ if (typeof value !== "string")
226
+ return value;
227
+ try {
228
+ const parsed = JSON.parse(value);
229
+ return parsed;
230
+ } catch {
231
+ return value;
232
+ }
233
+ };
234
+ var quotePgArrayElement = (value) => {
235
+ if (value === null || value === undefined)
236
+ return "NULL";
237
+ if (Array.isArray(value))
238
+ return pgArrayLiteral(value);
239
+ const text = isRecord(value) ? JSON.stringify(value) : String(value);
240
+ return `"${text.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
241
+ };
242
+ var encodeMssqlValue = (col, value) => {
243
+ if (value === null || value === undefined)
244
+ return null;
245
+ const bytes = decodeBinary(value);
246
+ if (bytes !== undefined && !col.isJson)
247
+ return bytes;
248
+ if (isStructured(value))
249
+ return JSON.stringify(value);
250
+ if (typeof value === "number" && Number.isInteger(value) && (value > INT32_MAX || value < INT32_MIN))
251
+ return String(value);
252
+ if (col.kind === "temporal" && typeof value === "string")
253
+ return value.replace(/Z$/, "");
254
+ return value;
255
+ };
256
+ var encodeMysqlValue = (col, value) => {
257
+ if (value === null || value === undefined)
258
+ return null;
259
+ const bytes = decodeBinary(value);
260
+ if (bytes !== undefined && !col.isJson)
261
+ return bytes;
262
+ if (col.isJson)
263
+ return JSON.stringify(value);
264
+ if (isStructured(value))
265
+ return JSON.stringify(value);
266
+ if (col.kind === "temporal" && typeof value === "string")
267
+ return isoToSqlDateTime(value);
268
+ return value;
269
+ };
270
+ var encodeSqliteValue = (col, value) => {
271
+ if (value === null || value === undefined)
272
+ return null;
273
+ const bytes = decodeBinary(value);
274
+ if (bytes !== undefined && !col.isJson)
275
+ return new Uint8Array(bytes);
276
+ if (typeof value === "boolean")
277
+ return value ? 1 : 0;
278
+ if (isStructured(value))
279
+ return JSON.stringify(value);
280
+ return value;
281
+ };
282
+ var encodeValue = (col, value) => {
283
+ if (value === null || value === undefined)
284
+ return null;
285
+ if (col.isJson)
286
+ return value;
287
+ const bytes = decodeBinary(value);
288
+ if (bytes !== undefined)
289
+ return bytes;
290
+ if (Array.isArray(value))
291
+ return pgArrayLiteral(value);
292
+ if (isStructured(value))
293
+ return JSON.stringify(value);
294
+ return value;
295
+ };
296
+ var isoToSqlDateTime = (value) => value.replace(ISO_UTC_PATTERN, "$1 $2");
297
+ var pgArrayLiteral = (values) => `{${values.map(quotePgArrayElement).join(",")}}`;
298
+ var normalizeValue = (value) => {
299
+ if (typeof value === "bigint")
300
+ return value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(value) : value.toString();
301
+ if (value instanceof ArrayBuffer)
302
+ return Buffer.from(value);
303
+ if (value instanceof Uint8Array && !Buffer.isBuffer(value))
304
+ return Buffer.from(value);
305
+ return value;
306
+ };
307
+ var normalizeRow = (row) => Object.fromEntries(Object.entries(row).map(([key, value]) => [key, normalizeValue(value)]));
308
+
309
+ // src/cli/scripts/dbEngines/mssql.ts
310
+ var MSSQL_PARAM_LIMIT = 2000;
311
+ var DEFAULT_PORT = 1433;
312
+ var UNICODE_BYTES = 2;
313
+ var MAX_LENGTH_UNBOUNDED = -1;
314
+ var LENGTH_TYPES = ["binary", "char", "varbinary", "varchar"];
315
+ var UNICODE_LENGTH_TYPES = ["nchar", "nvarchar"];
316
+ var SCALE_TYPES = ["datetime2", "datetimeoffset", "time"];
317
+ var DECIMAL_TYPES = ["decimal", "numeric"];
318
+ var TEMPORAL_TYPES = [
319
+ "date",
320
+ "datetime",
321
+ "datetime2",
322
+ "datetimeoffset",
323
+ "smalldatetime",
324
+ "time"
325
+ ];
326
+ var MONEY_TYPES = ["money", "smallmoney"];
327
+ var CLR_TYPES = ["geography", "geometry", "hierarchyid"];
328
+ var BINARY_TYPES = ["binary", "image", "varbinary", ...CLR_TYPES];
329
+ var SERVER_GENERATED_TYPES = ["timestamp"];
330
+ var truthy = (value) => value !== undefined && ["1", "true", "yes"].includes(value.toLowerCase());
331
+ var optionalValue = (value) => value === undefined || value === "" ? undefined : value;
332
+ var mssqlColumnType = (row) => {
333
+ const type = row.type.toLowerCase();
334
+ const maxOr = (length) => row.max_length === MAX_LENGTH_UNBOUNDED ? "max" : String(length);
335
+ if (LENGTH_TYPES.includes(type))
336
+ return `${type}(${maxOr(row.max_length)})`;
337
+ if (UNICODE_LENGTH_TYPES.includes(type))
338
+ return `${type}(${maxOr(row.max_length / UNICODE_BYTES)})`;
339
+ if (DECIMAL_TYPES.includes(type))
340
+ return `${type}(${row.precision}, ${row.scale})`;
341
+ if (SCALE_TYPES.includes(type))
342
+ return `${type}(${row.scale})`;
343
+ return type;
344
+ };
345
+ var parseMssqlUrl = (url) => {
346
+ if (/^sqlserver:/i.test(url)) {
347
+ const [hostPart = "", ...pairs] = url.replace(/^sqlserver:\/\//i, "").split(";");
348
+ const settings = new Map(pairs.filter((pair) => pair.includes("=")).map((pair) => {
349
+ const [key = "", ...rest] = pair.split("=");
350
+ return [key.trim().toLowerCase(), rest.join("=").trim()];
351
+ }));
352
+ const [hostWithInstance = "", port] = hostPart.split(":");
353
+ const [server = "", instanceName] = hostWithInstance.split("\\");
354
+ const target2 = {
355
+ database: optionalValue(settings.get("database") ?? settings.get("initial catalog")),
356
+ encrypt: settings.has("encrypt") ? truthy(settings.get("encrypt")) : true,
357
+ instanceName: optionalValue(instanceName),
358
+ password: settings.get("password") ?? settings.get("pwd"),
359
+ port: port === undefined ? undefined : Number(port),
360
+ server,
361
+ trustServerCertificate: truthy(settings.get("trustservercertificate")),
362
+ user: settings.get("user") ?? settings.get("username") ?? settings.get("user id") ?? settings.get("uid")
363
+ };
364
+ return target2;
365
+ }
366
+ const parsed = new URL(url);
367
+ const params = parsed.searchParams;
368
+ const target = {
369
+ database: optionalValue(decodeURIComponent(parsed.pathname.slice(1))),
370
+ encrypt: params.has("encrypt") ? truthy(params.get("encrypt") ?? undefined) : true,
371
+ instanceName: optionalValue(params.get("instanceName") ?? undefined),
372
+ password: optionalValue(decodeURIComponent(parsed.password)),
373
+ port: parsed.port === "" ? undefined : Number(parsed.port),
374
+ server: parsed.hostname,
375
+ trustServerCertificate: truthy(params.get("trustServerCertificate") ?? undefined),
376
+ user: optionalValue(decodeURIComponent(parsed.username))
377
+ };
378
+ return target;
379
+ };
380
+ var toColumn = (row) => {
381
+ const type = row.type.toLowerCase();
382
+ const column = {
383
+ generated: row.is_computed || SERVER_GENERATED_TYPES.includes(type),
384
+ identity: row.is_identity,
385
+ isJson: false,
386
+ kind: "other",
387
+ name: row.name,
388
+ sqlType: mssqlColumnType(row)
389
+ };
390
+ if (BINARY_TYPES.includes(type))
391
+ column.kind = "binary";
392
+ if (TEMPORAL_TYPES.includes(type))
393
+ column.kind = "temporal";
394
+ return column;
395
+ };
396
+ var selectExpression = (col) => {
397
+ const name = quoteMssqlIdent(col.name);
398
+ const type = (col.sqlType ?? "").replace(/\(.*$/, "");
399
+ if (TEMPORAL_TYPES.includes(type))
400
+ return `convert(nvarchar(max), ${name}, 126) as ${name}`;
401
+ if (MONEY_TYPES.includes(type))
402
+ return `convert(nvarchar(max), ${name}, 2) as ${name}`;
403
+ if (DECIMAL_TYPES.includes(type))
404
+ return `cast(${name} as nvarchar(max)) as ${name}`;
405
+ if (CLR_TYPES.includes(type))
406
+ return `cast(${name} as varbinary(max)) as ${name}`;
407
+ return name;
408
+ };
409
+ var loadMssql = async () => {
410
+ try {
411
+ return await import("mssql");
412
+ } catch {
413
+ throw new Error("SQL Server support needs the optional mssql driver in this project: bun add mssql");
414
+ }
415
+ };
416
+ var openMssql = async (url) => {
417
+ const { ConnectionPool } = await loadMssql();
418
+ const target = parseMssqlUrl(url);
419
+ const pool = new ConnectionPool({
420
+ database: target.database,
421
+ options: {
422
+ encrypt: target.encrypt,
423
+ instanceName: target.instanceName,
424
+ trustServerCertificate: target.trustServerCertificate
425
+ },
426
+ password: target.password,
427
+ port: target.instanceName === undefined ? target.port ?? DEFAULT_PORT : target.port,
428
+ server: target.server,
429
+ user: target.user
430
+ });
431
+ await pool.connect();
432
+ const query = async (text, params = []) => {
433
+ const request = pool.request();
434
+ params.forEach((value, idx) => request.input(`p${idx}`, value));
435
+ const result = await request.query(text);
436
+ return result.recordset ?? [];
437
+ };
438
+ const [schemaRow] = await query("select schema_name() as name");
439
+ const schema = String(schemaRow?.name ?? "dbo");
440
+ const qualified = (name) => `${quoteMssqlIdent(schema)}.${quoteMssqlIdent(name)}`;
441
+ const listTables = async () => {
442
+ const rows = await query("select name from sys.tables where schema_id = schema_id(@p0) and is_ms_shipped = 0 order by name", [schema]);
443
+ return rows.map((row) => String(row.name));
444
+ };
445
+ const tableMeta = async (name) => {
446
+ const [columnRows, keyRows] = await Promise.all([
447
+ query("select c.name, type_name(c.system_type_id) as type, c.max_length, c.precision, c.scale, c.is_computed, c.is_identity from sys.columns c where c.object_id = object_id(@p0) order by c.column_id", [qualified(name)]),
448
+ query("select c.name from sys.indexes i join sys.index_columns ic on ic.object_id = i.object_id and ic.index_id = i.index_id join sys.columns c on c.object_id = ic.object_id and c.column_id = ic.column_id where i.is_primary_key = 1 and i.object_id = object_id(@p0) order by ic.key_ordinal", [qualified(name)])
449
+ ]);
450
+ const columns = columnRows.map((row) => {
451
+ const column = {
452
+ is_computed: row.is_computed === true,
453
+ is_identity: row.is_identity === true,
454
+ max_length: Number(row.max_length),
455
+ name: String(row.name),
456
+ precision: Number(row.precision),
457
+ scale: Number(row.scale),
458
+ type: String(row.type)
459
+ };
460
+ return toColumn(column);
461
+ });
462
+ const primaryKey = keyRows.map((row) => String(row.name));
463
+ const meta = { columns, name, primaryKey };
464
+ return meta;
465
+ };
466
+ const foreignLinks = async () => {
467
+ const rows = await query("select object_name(fk.parent_object_id) as child, object_name(fk.referenced_object_id) as parent from sys.foreign_keys fk where fk.schema_id = schema_id(@p0)", [schema]);
468
+ return rows.map((row) => ({
469
+ from: String(row.child),
470
+ to: String(row.parent)
471
+ }));
472
+ };
473
+ const readRows = async (meta) => {
474
+ const list = meta.columns.map(selectExpression).join(", ");
475
+ const rows = await query(`select ${list} from ${qualified(meta.name)}`);
476
+ return rows.map(normalizeRow);
477
+ };
478
+ const insertChunk = async (meta, rows) => {
479
+ const cols = insertableColumns(meta);
480
+ const params = rows.flatMap((row) => cols.map((col) => encodeMssqlValue(col, row[col.name])));
481
+ await query(mssqlUpsert(meta, rows.length, qualified(meta.name)), params);
482
+ };
483
+ const insertRows = async (meta, rows) => {
484
+ const size = rowsPerChunk(insertableColumns(meta).length, MSSQL_PARAM_LIMIT);
485
+ await chunkRows(rows, size).reduce(async (prev, part) => {
486
+ await prev;
487
+ return insertChunk(meta, part);
488
+ }, Promise.resolve());
489
+ };
490
+ const truncate = async (names) => {
491
+ if (names.length === 0)
492
+ return;
493
+ const tables = names.map(qualified);
494
+ const statements = [
495
+ ...tables.map((table) => `alter table ${table} nocheck constraint all;`),
496
+ ...tables.map((table) => `delete from ${table};`),
497
+ ...tables.map((table) => `alter table ${table} with check check constraint all;`)
498
+ ];
499
+ await query(statements.join(" "));
500
+ };
501
+ const connection = {
502
+ engine: "mssql",
503
+ foreignLinks,
504
+ insertRows,
505
+ listTables,
506
+ readRows,
507
+ tableMeta,
508
+ truncate,
509
+ afterRestore: () => Promise.resolve(),
510
+ close: () => pool.close()
511
+ };
512
+ return connection;
513
+ };
514
+
515
+ // src/cli/scripts/dbEngines/mysql.ts
516
+ var {SQL } = globalThis.Bun;
517
+ var MYSQL_PARAM_LIMIT = 65535;
518
+ var ROW_ALIAS_MIN_VERSION = "8.0.19".split(".").map(Number);
519
+ var NOT_FOUND = -1;
520
+ var KINDS = {
521
+ binary: "binary",
522
+ bit: "binary",
523
+ blob: "binary",
524
+ date: "temporal",
525
+ datetime: "temporal",
526
+ json: "json",
527
+ longblob: "binary",
528
+ mediumblob: "binary",
529
+ time: "temporal",
530
+ timestamp: "temporal",
531
+ tinyblob: "binary",
532
+ varbinary: "binary"
533
+ };
534
+ var GENERATED_EXTRA = /\b(VIRTUAL|STORED|PERSISTENT)\b/i;
535
+ var PUBLIC_KEY_RETRIEVAL_PARAM = "allowPublicKeyRetrieval";
536
+ var kindOf = (dataType) => KINDS[dataType] ?? "other";
537
+ var atLeast = (version, minimum) => {
538
+ const parts = (version.match(/^(\d+)\.(\d+)\.(\d+)/) ?? []).slice(1).map(Number);
539
+ const firstDiff = minimum.findIndex((part, idx) => (parts[idx] ?? 0) !== part);
540
+ return firstDiff === NOT_FOUND || (parts[firstDiff] ?? 0) > (minimum[firstDiff] ?? 0);
541
+ };
542
+ var connectionOptions = (url) => {
543
+ const parsed = new URL(url.replace(/^singlestore:/i, "mysql:"));
544
+ const allowPublicKeyRetrieval = parsed.searchParams.get(PUBLIC_KEY_RETRIEVAL_PARAM) === "true";
545
+ parsed.searchParams.delete(PUBLIC_KEY_RETRIEVAL_PARAM);
546
+ const options = {
547
+ allowPublicKeyRetrieval,
548
+ url: parsed.toString()
549
+ };
550
+ return options;
551
+ };
552
+ var openMysql = async (url) => {
553
+ const sql = new SQL(connectionOptions(url));
554
+ const [version] = await sql.unsafe("select version() as v");
555
+ const versionText = version?.v ?? "";
556
+ const singlestoreRows = await sql.unsafe(`show variables like 'memsql_version'`);
557
+ const mariadb = /mariadb/i.test(versionText);
558
+ const singlestore = singlestoreRows.length > 0;
559
+ const rowAlias = !mariadb && !singlestore && atLeast(versionText, ROW_ALIAS_MIN_VERSION);
560
+ const engineName = mariadb ? "mariadb" : "mysql";
561
+ const listTables = async () => {
562
+ const rows = await sql.unsafe(`select table_name as name from information_schema.tables where table_schema = database() and table_type = 'BASE TABLE' order by table_name`);
563
+ return rows.map((row) => row.name);
564
+ };
565
+ const mariadbJsonColumns = async (name) => {
566
+ if (!mariadb)
567
+ return new Set;
568
+ const rows = await sql.unsafe(`select check_clause as clause from information_schema.check_constraints where constraint_schema = database() and table_name = ?`, [name]);
569
+ return new Set(rows.flatMap((row) => [...row.clause.matchAll(/json_valid\(`([^`]+)`\)/gi)].map((match) => match[1] ?? "")));
570
+ };
571
+ const columnsFor = async (name) => {
572
+ const jsonText = await mariadbJsonColumns(name);
573
+ const rows = await sql.unsafe(`select column_name as name, data_type as data_type, extra as extra from information_schema.columns where table_schema = database() and table_name = ? order by ordinal_position`, [name]);
574
+ return rows.map((row) => ({
575
+ generated: GENERATED_EXTRA.test(row.extra ?? ""),
576
+ isJson: row.data_type.toLowerCase() === "json" || jsonText.has(row.name),
577
+ kind: kindOf(row.data_type.toLowerCase()),
578
+ name: row.name
579
+ }));
580
+ };
581
+ const primaryKeyFor = async (name) => {
582
+ const rows = await sql.unsafe(`select column_name as name from information_schema.key_column_usage where table_schema = database() and table_name = ? and constraint_name = 'PRIMARY' order by ordinal_position`, [name]);
583
+ return rows.map((row) => row.name);
584
+ };
585
+ const tableMeta = async (name) => {
586
+ const [columns, primaryKey] = await Promise.all([
587
+ columnsFor(name),
588
+ primaryKeyFor(name)
589
+ ]);
590
+ return { columns, name, primaryKey };
591
+ };
592
+ const foreignLinks = async () => {
593
+ const rows = await sql.unsafe(`select table_name as child, referenced_table_name as parent from information_schema.key_column_usage where table_schema = database() and referenced_table_name is not null`);
594
+ return rows.map((row) => ({ from: row.child, to: row.parent }));
595
+ };
596
+ const readRows = async (meta) => {
597
+ const list = meta.columns.map((col) => col.kind === "temporal" ? `cast(${quoteMysqlIdent(col.name)} as char) as ${quoteMysqlIdent(col.name)}` : quoteMysqlIdent(col.name)).join(", ");
598
+ const rows = await sql.unsafe(`select ${list} from ${quoteMysqlIdent(meta.name)}`);
599
+ return rows.map(normalizeRow);
600
+ };
601
+ const insertChunk = async (meta, rows) => {
602
+ const cols = insertableColumns(meta);
603
+ const params = rows.flatMap((row) => cols.map((col) => encodeMysqlValue(col, row[col.name])));
604
+ await sql.unsafe(mysqlInsert(meta, rows.length, rowAlias), params);
605
+ };
606
+ const insertRows = async (meta, rows) => {
607
+ const size = rowsPerChunk(insertableColumns(meta).length, MYSQL_PARAM_LIMIT);
608
+ await chunkRows(rows, size).reduce(async (prev, part) => {
609
+ await prev;
610
+ return insertChunk(meta, part);
611
+ }, Promise.resolve());
612
+ };
613
+ const truncate = async (names) => {
614
+ if (names.length === 0)
615
+ return;
616
+ const conn = await sql.reserve();
617
+ const statements = [
618
+ ...singlestore ? [] : ["set foreign_key_checks = 0"],
619
+ ...names.map((name) => `truncate table ${quoteMysqlIdent(name)}`)
620
+ ];
621
+ try {
622
+ await statements.reduce(async (prev, statement) => {
623
+ await prev;
624
+ await conn.unsafe(statement);
625
+ }, Promise.resolve());
626
+ } finally {
627
+ if (!singlestore)
628
+ await conn.unsafe("set foreign_key_checks = 1");
629
+ conn.release();
630
+ }
631
+ };
632
+ const connection = {
633
+ engine: singlestore ? "singlestore" : engineName,
634
+ foreignLinks,
635
+ insertRows,
636
+ listTables,
637
+ readRows,
638
+ tableMeta,
639
+ truncate,
640
+ afterRestore: () => Promise.resolve(),
641
+ close: () => sql.end()
642
+ };
643
+ return connection;
644
+ };
645
+
646
+ // src/cli/scripts/dbEngines/postgres.ts
647
+ var {SQL: SQL2 } = globalThis.Bun;
648
+ var PG_PARAM_LIMIT = 65535;
649
+ var SCHEMA = "public";
650
+ var JSON_DATA_TYPES = ["json", "jsonb"];
651
+ var KINDS2 = {
652
+ ARRAY: "array",
653
+ bytea: "binary",
654
+ json: "json",
655
+ jsonb: "json"
656
+ };
657
+ var kindOf2 = (dataType) => KINDS2[dataType] ?? "other";
658
+ var toColumn2 = (row) => ({
659
+ generated: row.is_generated === "ALWAYS",
660
+ identity: row.identity_generation === "ALWAYS",
661
+ isJson: JSON_DATA_TYPES.includes(row.data_type),
662
+ kind: kindOf2(row.data_type),
663
+ name: row.column_name,
664
+ sequenced: row.is_identity === "YES" || (row.column_default ?? "").startsWith("nextval(")
665
+ });
666
+ var connectionUrl = (url) => url.replace(/^cockroachdb:/i, "postgresql:");
667
+ var openPostgres = async (url) => {
668
+ const sql = new SQL2(connectionUrl(url));
669
+ const [version] = await sql.unsafe("select version() as v");
670
+ const cockroach = /cockroachdb/i.test(version?.v ?? "");
671
+ const sequencedByTable = new Map;
672
+ const listTables = async () => {
673
+ const rows = await sql`select table_name from information_schema.tables where table_schema = ${SCHEMA} and table_type = ${"BASE TABLE"} order by table_name`;
674
+ return rows.map((row) => row.table_name);
675
+ };
676
+ const columnsFor = async (name) => {
677
+ const hidden = cockroach ? ` and is_hidden = 'NO'` : "";
678
+ const rows = await sql.unsafe(`select column_name, data_type, column_default, is_generated, is_identity, identity_generation from information_schema.columns where table_schema = $1 and table_name = $2${hidden} order by ordinal_position`, [SCHEMA, name]);
679
+ return rows.map(toColumn2);
680
+ };
681
+ const primaryKeyFor = async (name) => {
682
+ const rows = await sql.unsafe(`select a.attname as col from pg_index i join pg_attribute a on a.attrelid = i.indrelid and a.attnum = any(i.indkey) where i.indrelid = $1::regclass and i.indisprimary order by a.attnum`, [`${SCHEMA}.${quoteIdent(name)}`]);
683
+ return rows.map((row) => row.col);
684
+ };
685
+ const tableMeta = async (name) => {
686
+ const [columns, primaryKey] = await Promise.all([
687
+ columnsFor(name),
688
+ primaryKeyFor(name)
689
+ ]);
690
+ sequencedByTable.set(name, columns.filter((col) => col.sequenced).map((col) => col.name));
691
+ return {
692
+ columns: columns.map(({ generated, identity, isJson, kind, name: colName }) => ({
693
+ generated,
694
+ identity,
695
+ isJson,
696
+ kind,
697
+ name: colName
698
+ })),
699
+ name,
700
+ primaryKey
701
+ };
702
+ };
703
+ const foreignLinks = async () => {
704
+ const rows = await sql.unsafe(`select tc.table_name as child, ccu.table_name as parent from information_schema.table_constraints tc join information_schema.constraint_column_usage ccu on ccu.constraint_name = tc.constraint_name and ccu.table_schema = tc.table_schema where tc.constraint_type = 'FOREIGN KEY' and tc.table_schema = $1`, [SCHEMA]);
705
+ return rows.map((row) => ({ from: row.child, to: row.parent }));
706
+ };
707
+ const readRows = async (meta) => {
708
+ const rows = await sql.unsafe(`select * from ${quoteIdent(meta.name)}`);
709
+ return rows;
710
+ };
711
+ const insertChunk = async (meta, rows) => {
712
+ const cols = insertableColumns(meta);
713
+ const overriding = cols.some((col) => col.identity === true);
714
+ const params = rows.flatMap((row) => cols.map((col) => encodeValue(col, row[col.name])));
715
+ await sql.unsafe(postgresInsert(meta, rows.length, overriding), params);
716
+ };
717
+ const insertRows = async (meta, rows) => {
718
+ const size = rowsPerChunk(insertableColumns(meta).length, PG_PARAM_LIMIT);
719
+ await chunkRows(rows, size).reduce(async (prev, part) => {
720
+ await prev;
721
+ return insertChunk(meta, part);
722
+ }, Promise.resolve());
723
+ };
724
+ const truncate = async (names) => {
725
+ if (names.length === 0)
726
+ return;
727
+ const list = names.map(quoteIdent).join(", ");
728
+ const restart = cockroach ? "" : " restart identity";
729
+ await sql.unsafe(`truncate ${list}${restart} cascade`);
730
+ };
731
+ const resyncSequences = async (meta) => {
732
+ const sequenced = sequencedByTable.get(meta.name) ?? [];
733
+ await Promise.all(sequenced.map((col) => sql.unsafe(`select setval(pg_get_serial_sequence($1, $2), coalesce((select max(${quoteIdent(col)}) from ${quoteIdent(meta.name)}), 0) + 1, false)`, [`${SCHEMA}.${quoteIdent(meta.name)}`, col])));
734
+ };
735
+ const afterRestore = async (restored) => {
736
+ await Promise.all(restored.map(resyncSequences));
737
+ };
738
+ const connection = {
739
+ afterRestore,
740
+ engine: cockroach ? "cockroach" : "postgres",
741
+ foreignLinks,
742
+ insertRows,
743
+ listTables,
744
+ readRows,
745
+ tableMeta,
746
+ truncate,
747
+ close: () => sql.end()
748
+ };
749
+ return connection;
750
+ };
751
+
752
+ // src/cli/scripts/dbEngines/sqlite.ts
753
+ import { Database } from "bun:sqlite";
754
+ var SQLITE_PARAM_LIMIT = 32766;
755
+ var GENERATED_HIDDEN = 2;
756
+ var AUTH_TOKEN_ENV_KEYS = [
757
+ "TURSO_AUTH_TOKEN",
758
+ "LIBSQL_AUTH_TOKEN",
759
+ "DATABASE_AUTH_TOKEN"
760
+ ];
761
+ var toBinding = (value) => {
762
+ if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || value instanceof Uint8Array)
763
+ return value;
764
+ return String(value);
765
+ };
766
+ var bunSqliteExecutor = (path) => {
767
+ const db = new Database(path, {
768
+ create: false,
769
+ readwrite: true,
770
+ safeIntegers: true
771
+ });
772
+ const executor = {
773
+ all: (query, params) => {
774
+ const rows = db.query(query).all(...params.map(toBinding));
775
+ return Promise.resolve(rows);
776
+ },
777
+ batch: (statements) => {
778
+ db.transaction(() => {
779
+ statements.forEach((statement) => db.run(statement));
780
+ })();
781
+ return Promise.resolve();
782
+ },
783
+ close: () => {
784
+ db.close();
785
+ return Promise.resolve();
786
+ },
787
+ run: (query, params) => {
788
+ db.query(query).run(...params.map(toBinding));
789
+ return Promise.resolve();
790
+ }
791
+ };
792
+ return executor;
793
+ };
794
+ var loadLibsql = async () => {
795
+ try {
796
+ return await import("@libsql/client");
797
+ } catch {
798
+ throw new Error("Remote libSQL / Turso support needs the optional @libsql/client driver in this project: bun add @libsql/client");
799
+ }
800
+ };
801
+ var libsqlAuthToken = (url) => url.searchParams.get("authToken") ?? AUTH_TOKEN_ENV_KEYS.map((key) => process.env[key]).find((value) => typeof value === "string" && value !== "");
802
+ var libsqlExecutor = async (url) => {
803
+ const { createClient } = await loadLibsql();
804
+ const parsed = new URL(url);
805
+ const authToken = libsqlAuthToken(parsed);
806
+ parsed.searchParams.delete("authToken");
807
+ const client = createClient({
808
+ authToken,
809
+ intMode: "bigint",
810
+ url: parsed.toString()
811
+ });
812
+ const toArgs = (params) => params.map((value) => {
813
+ const binding = toBinding(value);
814
+ return typeof binding === "boolean" ? Number(binding) : binding;
815
+ });
816
+ const executor = {
817
+ all: async (query, params) => {
818
+ const result = await client.execute({
819
+ args: toArgs(params),
820
+ sql: query
821
+ });
822
+ return result.rows.map((row) => Object.fromEntries(result.columns.map((column, idx) => [column, row[idx]])));
823
+ },
824
+ batch: async (statements) => {
825
+ await client.batch(statements, "write");
826
+ },
827
+ close: () => {
828
+ client.close();
829
+ return Promise.resolve();
830
+ },
831
+ run: async (query, params) => {
832
+ await client.execute({ args: toArgs(params), sql: query });
833
+ }
834
+ };
835
+ return executor;
836
+ };
837
+ var isInternalTable = (name) => name.startsWith("sqlite_") || name.startsWith("libsql_");
838
+ var openSqlite = (exec, engine) => {
839
+ const listTables = async () => {
840
+ const rows = await exec.all(`select name from sqlite_master where type = 'table' order by name`, []);
841
+ return rows.map((row) => String(row.name)).filter((name) => !isInternalTable(name));
842
+ };
843
+ const tableMeta = async (name) => {
844
+ const rows = await exec.all("select name, type, pk, hidden from pragma_table_xinfo(?) order by cid", [name]);
845
+ const columnRows = rows.map((row) => {
846
+ const column = {
847
+ hidden: row.hidden,
848
+ name: String(row.name),
849
+ pk: row.pk,
850
+ type: typeof row.type === "string" ? row.type : null
851
+ };
852
+ return column;
853
+ });
854
+ const primaryKey = columnRows.filter((row) => Number(row.pk) > 0).sort((left, right) => Number(left.pk) - Number(right.pk)).map((row) => row.name);
855
+ const columns = columnRows.map((row) => {
856
+ const column = {
857
+ generated: Number(row.hidden) >= GENERATED_HIDDEN,
858
+ isJson: false,
859
+ kind: /blob/i.test(row.type ?? "") ? "binary" : "other",
860
+ name: row.name
861
+ };
862
+ return column;
863
+ });
864
+ const meta = { columns, name, primaryKey };
865
+ return meta;
866
+ };
867
+ const foreignLinks = async () => {
868
+ const rows = await exec.all(`select m.name as child, f."table" as parent from sqlite_master m join pragma_foreign_key_list(m.name) f where m.type = 'table'`, []);
869
+ return rows.map((row) => ({
870
+ from: String(row.child),
871
+ to: String(row.parent)
872
+ }));
873
+ };
874
+ const readRows = async (meta) => {
875
+ const rows = await exec.all(`select * from ${quoteIdent(meta.name)}`, []);
876
+ return rows.map(normalizeRow);
877
+ };
878
+ const insertChunk = async (meta, rows) => {
879
+ const cols = insertableColumns(meta);
880
+ const params = rows.flatMap((row) => cols.map((col) => encodeSqliteValue(col, row[col.name])));
881
+ await exec.run(sqliteInsert(meta, rows.length), params);
882
+ };
883
+ const insertRows = async (meta, rows) => {
884
+ const size = rowsPerChunk(insertableColumns(meta).length, SQLITE_PARAM_LIMIT);
885
+ await chunkRows(rows, size).reduce(async (prev, part) => {
886
+ await prev;
887
+ return insertChunk(meta, part);
888
+ }, Promise.resolve());
889
+ };
890
+ const truncate = async (names) => {
891
+ if (names.length === 0)
892
+ return;
893
+ const sequence = await exec.all(`select name from sqlite_master where type = 'table' and name = 'sqlite_sequence'`, []);
894
+ const quotedNames = names.map((name) => `'${name.replace(/'/g, "''")}'`).join(", ");
895
+ await exec.batch([
896
+ "pragma defer_foreign_keys = on",
897
+ ...names.map((name) => `delete from ${quoteIdent(name)}`),
898
+ ...sequence.length > 0 ? [`delete from sqlite_sequence where name in (${quotedNames})`] : []
899
+ ]);
900
+ };
901
+ const connection = {
902
+ close: exec.close,
903
+ engine,
904
+ foreignLinks,
905
+ insertRows,
906
+ listTables,
907
+ readRows,
908
+ tableMeta,
909
+ truncate,
910
+ afterRestore: () => Promise.resolve()
911
+ };
912
+ return connection;
913
+ };
914
+
915
+ // src/cli/scripts/dbEngines/open.ts
916
+ var openConnection = async (target, cwd) => {
917
+ if (target.family === "postgres")
918
+ return openPostgres(target.url);
919
+ if (target.family === "mysql")
920
+ return openMysql(target.url);
921
+ if (target.family === "mssql")
922
+ return openMssql(target.url);
923
+ if (target.family === "libsql")
924
+ return openSqlite(await libsqlExecutor(target.url), "libsql");
925
+ return openSqlite(bunSqliteExecutor(sqlitePath(target.url, cwd)), "sqlite");
926
+ };
927
+
928
+ // src/cli/scripts/db.ts
929
+ var BACKUP_FORMAT_VERSION = 1;
930
+ var URL_ENV_KEYS = [
931
+ "DATABASE_URL",
932
+ "POSTGRES_URL",
933
+ "DATABASE_URL_UNPOOLED",
934
+ "MYSQL_URL",
935
+ "TURSO_DATABASE_URL",
936
+ "LIBSQL_URL",
937
+ "MSSQL_URL"
938
+ ];
939
+ var TEXT_JSON_ENGINES = ["libsql", "mssql", "sqlite"];
940
+ var SEED_CANDIDATES = ["db/seed.ts", "src/db/seed.ts", "seed.ts"];
941
+ var VALUE_FLAGS = ["--out", "--url", "--only", "--exclude"];
942
+ var paint = (text, color) => `${color}${text}${colors.reset}`;
943
+ var findUrl = (explicit) => explicit ?? URL_ENV_KEYS.map((key) => env[key]).find((value) => typeof value === "string" && value !== "");
944
+ var resolveUrl = (explicit) => {
945
+ const found = findUrl(explicit);
946
+ if (found === undefined || found === "")
947
+ throw new Error(`No database URL found. Set ${URL_ENV_KEYS.join(" or ")}, or pass --url <url>.`);
948
+ return found;
949
+ };
950
+ var resolveTarget = (url) => detectTarget(url, readOrmDialect(process.cwd()));
951
+ var keepTable = (name, options) => (options.only.length === 0 || options.only.includes(name)) && !options.exclude.includes(name);
952
+ var withConnection = async (target, work) => {
953
+ const conn = await openConnection(target, process.cwd());
954
+ try {
955
+ return await work(conn);
956
+ } finally {
957
+ await conn.close();
958
+ }
959
+ };
960
+ var dumpTables = async (conn, options) => {
961
+ const chosen = (await conn.listTables()).filter((name) => keepTable(name, options));
962
+ const dumps = await Promise.all(chosen.map(async (name) => {
963
+ const rows = await conn.readRows(await conn.tableMeta(name));
964
+ return [name, rows];
965
+ }));
966
+ const tables = Object.fromEntries(dumps);
967
+ return { chosen, engine: conn.engine, tables };
968
+ };
969
+ var runBackup = async (options) => {
970
+ const { chosen, engine, tables } = await withConnection(resolveTarget(options.url), (conn) => dumpTables(conn, options));
971
+ const stamp = new Date().toISOString();
972
+ const payload = engine === "postgres" ? { at: stamp, tables, v: BACKUP_FORMAT_VERSION } : { at: stamp, engine, tables, v: BACKUP_FORMAT_VERSION };
973
+ const dir = options.out ?? join2(process.cwd(), "backups");
974
+ mkdirSync(dir, { recursive: true });
975
+ const json = JSON.stringify(payload, (_, value) => typeof value === "bigint" ? value.toString() : value);
976
+ const file = join2(dir, `backup-${payload.at.replace(/[:.]/g, "-")}.json`);
977
+ writeFileSync(file, json);
978
+ writeFileSync(join2(dir, "latest.json"), json);
979
+ const total = chosen.reduce((sum, name) => sum + (tables[name]?.length ?? 0), 0);
980
+ console.log(paint(`\u2713 backup \u2192 ${file}`, colors.green));
981
+ console.log(paint(` ${engine}: ${chosen.length} tables, ${total} rows`, colors.dim));
982
+ };
983
+ var parseJsonColumns = (meta, row) => {
984
+ const parsed = { ...row };
985
+ meta.columns.filter((col) => col.isJson).forEach((col) => {
986
+ parsed[col.name] = parseJsonText(row[col.name]);
987
+ });
988
+ return parsed;
989
+ };
990
+ var confirmTruncate = (count, options) => !options.truncate || options.yes || prompt(paint(`\u26A0 TRUNCATE ${count} tables before restore? type "yes": `, colors.yellow)) === "yes";
991
+ var restoreInto = async (conn, payload, options) => {
992
+ const names = Object.keys(payload.tables).filter((name) => keepTable(name, options));
993
+ const existing = new Set(await conn.listTables());
994
+ const missing = names.filter((name) => !existing.has(name));
995
+ if (missing.length > 0)
996
+ throw new Error(`The target ${conn.engine} database has no table ${missing.join(", ")}. Create the schema first (e.g. drizzle-kit push / prisma migrate deploy) or pass --exclude ${missing.join(",")}.`);
997
+ const source = payload.engine ?? "postgres";
998
+ if (source !== conn.engine)
999
+ console.log(paint(` restoring a ${source} backup into ${conn.engine}; values are re-encoded per column`, colors.dim));
1000
+ const order = dependencyOrder(names, await conn.foreignLinks());
1001
+ const metas = await Promise.all(order.map((name) => conn.tableMeta(name)));
1002
+ if (!confirmTruncate(order.length, options)) {
1003
+ console.log(paint("aborted", colors.yellow));
1004
+ return;
1005
+ }
1006
+ if (options.truncate)
1007
+ await conn.truncate([...order].reverse());
1008
+ const jsonAsText = TEXT_JSON_ENGINES.includes(source);
1009
+ await metas.reduce(async (prev, meta) => {
1010
+ await prev;
1011
+ const rows = payload.tables[meta.name] ?? [];
1012
+ return conn.insertRows(meta, jsonAsText ? rows.map((row) => parseJsonColumns(meta, row)) : rows);
1013
+ }, Promise.resolve());
1014
+ await conn.afterRestore(metas.filter((meta) => (payload.tables[meta.name]?.length ?? 0) > 0));
1015
+ return order;
1016
+ };
1017
+ var runRestore = async (file, options) => {
1018
+ if (!existsSync2(file))
1019
+ throw new Error(`Backup not found: ${file}`);
1020
+ const payload = JSON.parse(readFileSync2(file, "utf-8"));
1021
+ const order = await withConnection(resolveTarget(options.url), (conn) => restoreInto(conn, payload, options));
1022
+ if (order === undefined)
1023
+ return;
1024
+ const total = order.reduce((sum, name) => sum + (payload.tables[name]?.length ?? 0), 0);
1025
+ console.log(paint(`\u2713 restored ${order.length} tables, ${total} rows (idempotent upsert by primary key)`, colors.green));
1026
+ };
1027
+ var seedEnv = (explicitUrl) => {
1028
+ const url = findUrl(explicitUrl);
1029
+ if (url === undefined || url === "")
1030
+ return { ...process.env };
1031
+ return {
1032
+ ...process.env,
1033
+ ABSOLUTE_DB_ENGINE: resolveTarget(url).family,
1034
+ DATABASE_URL: url
1035
+ };
1036
+ };
1037
+ var runSeed = async (entry, url) => {
1038
+ const target = entry ?? SEED_CANDIDATES.find((candidate) => existsSync2(join2(process.cwd(), candidate)));
1039
+ if (target === undefined)
1040
+ throw new Error(`No seed script found (looked for ${SEED_CANDIDATES.join(", ")}). Pass a path: absolute db seed <file>.`);
1041
+ console.log(paint(`seeding via ${target}\u2026`, colors.cyan));
1042
+ const proc = spawn(["bun", "run", target], {
1043
+ env: seedEnv(url),
1044
+ stderr: "inherit",
1045
+ stdin: "inherit",
1046
+ stdout: "inherit"
1047
+ });
1048
+ const code = await proc.exited;
1049
+ if (code !== 0)
1050
+ throw new Error(`Seed failed (exit ${code}).`);
1051
+ };
1052
+ var flagValue = (rest, flag) => {
1053
+ const idx = rest.indexOf(flag);
1054
+ return idx === UNFOUND_INDEX ? undefined : rest[idx + 1];
1055
+ };
1056
+ var listValue = (rest, flag) => (flagValue(rest, flag) ?? "").split(",").map((part) => part.trim()).filter((part) => part !== "");
1057
+ var parseOptions = (rest) => ({
1058
+ exclude: listValue(rest, "--exclude"),
1059
+ only: listValue(rest, "--only"),
1060
+ out: flagValue(rest, "--out"),
1061
+ truncate: rest.includes("--truncate"),
1062
+ url: resolveUrl(flagValue(rest, "--url")),
1063
+ yes: rest.includes("--yes") || rest.includes("-y")
1064
+ });
1065
+ var positionalArgs = (rest) => rest.filter((arg, idx) => !arg.startsWith("-") && !VALUE_FLAGS.includes(rest[idx - 1] ?? ""));
1066
+ var usage = () => {
1067
+ console.error("Usage: absolute db <backup|restore|seed> [options]");
1068
+ console.error(" backup [--out <dir>] [--only a,b] [--exclude a,b] [--url <url>] Dump tables \u2192 JSON (+ latest.json)");
1069
+ console.error(" restore [file] [--truncate] [--only a,b] [--exclude a,b] [-y] Idempotent upsert by primary key");
1070
+ console.error(" seed [file] [--url <url>] Run the project\u2019s seed script");
1071
+ console.error("Engines (picked from the URL scheme): PostgreSQL + CockroachDB (postgres://), MySQL, MariaDB + SingleStore (mysql://, mariadb://, singlestore://),");
1072
+ console.error(" SQLite + local libSQL files (file:, sqlite:, *.db), remote libSQL/Turso (libsql://, https://; needs @libsql/client),");
1073
+ console.error(" SQL Server (sqlserver://, mssql://; needs mssql). MongoDB and Gel are refused.");
1074
+ process.exit(1);
1075
+ };
1076
+ var runDb = async (args) => {
1077
+ const [sub, ...rest] = args;
1078
+ if (sub === "backup") {
1079
+ await runBackup(parseOptions(rest));
1080
+ return;
1081
+ }
1082
+ if (sub === "restore") {
1083
+ const file = positionalArgs(rest)[0] ?? join2(process.cwd(), "backups", "latest.json");
1084
+ await runRestore(file, parseOptions(rest));
1085
+ return;
1086
+ }
1087
+ if (sub === "seed") {
1088
+ await runSeed(positionalArgs(rest)[0], flagValue(rest, "--url"));
1089
+ return;
1090
+ }
1091
+ usage();
1092
+ };
1093
+ export {
1094
+ chunkRows,
1095
+ conflictClause,
1096
+ dependencyOrder,
1097
+ encodeValue,
1098
+ quoteIdent,
1099
+ runDb
1100
+ };