@hot-updater/cloudflare 1.0.0-rc.1 → 1.0.0-rc.16

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 (44) hide show
  1. package/dist/iac/index.cjs +312 -1022
  2. package/dist/iac/index.d.cts +1 -5
  3. package/dist/iac/index.d.mts +1 -5
  4. package/dist/iac/index.mjs +309 -1019
  5. package/dist/index.cjs +97 -870
  6. package/dist/index.d.cts +353 -4
  7. package/dist/index.d.mts +354 -5
  8. package/dist/index.mjs +96 -871
  9. package/dist/worker/index.cjs +59 -858
  10. package/dist/worker/index.d.cts +355 -10
  11. package/dist/worker/index.d.mts +355 -10
  12. package/dist/worker/index.mjs +62 -862
  13. package/package.json +7 -8
  14. package/sql/bundles.sql +81 -190
  15. package/src/d1Database.spec.ts +150 -138
  16. package/src/d1Database.ts +58 -40
  17. package/src/d1Executor.ts +84 -0
  18. package/src/d1Schema.spec.ts +84 -0
  19. package/src/d1Schema.ts +25 -0
  20. package/src/d1TestDatabase.ts +38 -0
  21. package/src/index.ts +1 -0
  22. package/src/plugins.ts +8 -0
  23. package/src/worker/d1Database.spec.ts +51 -25
  24. package/src/worker/d1Database.ts +21 -27
  25. package/src/worker/index.ts +1 -0
  26. package/worker/dist/README.md +1 -1
  27. package/worker/dist/index.js +7640 -5712
  28. package/worker/dist/index.js.map +4 -4
  29. package/worker/migrations/0001_hot-updater_1.0.0.sql +81 -205
  30. package/worker/src/d1.conformance.integration.spec.ts +53 -0
  31. package/worker/src/d1.readBudgets.integration.spec.ts +85 -0
  32. package/worker/src/databaseMigration.integration.spec.ts +78 -108
  33. package/worker/src/databasePlugins.integration.spec.ts +154 -140
  34. package/worker/src/index.integration.spec.ts +29 -84
  35. package/worker/src/index.ts +2 -2
  36. package/worker/src/readPlans.integration.spec.ts +91 -0
  37. package/src/d1Implementation.spec.ts +0 -252
  38. package/src/d1Implementation.ts +0 -742
  39. package/src/d1Query.spec.ts +0 -46
  40. package/src/d1Query.ts +0 -89
  41. package/src/d1Rows.spec.ts +0 -111
  42. package/src/d1Rows.ts +0 -326
  43. package/src/d1Sql.spec.ts +0 -30
  44. package/src/d1Sql.ts +0 -175
@@ -6,7 +6,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
10
  var __copyProps = (to, from, except, desc) => {
11
11
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
12
  key = keys[i];
@@ -17,35 +17,36 @@ var __copyProps = (to, from, except, desc) => {
17
17
  }
18
18
  return to;
19
19
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
21
21
  value: mod,
22
22
  enumerable: true
23
23
  }) : target, mod));
24
24
  //#endregion
25
25
  let crypto = require("crypto");
26
- crypto = __toESM(crypto);
26
+ crypto = __toESM(crypto, 1);
27
27
  let fs_promises = require("fs/promises");
28
- fs_promises = __toESM(fs_promises);
28
+ fs_promises = __toESM(fs_promises, 1);
29
29
  let path = require("path");
30
- path = __toESM(path);
30
+ path = __toESM(path, 1);
31
31
  let _hot_updater_cli_tools = require("@hot-updater/cli-tools");
32
- let _hot_updater_server = require("@hot-updater/server");
32
+ let _hot_updater_server_db = require("@hot-updater/server/db");
33
33
  let cloudflare = require("cloudflare");
34
- cloudflare = __toESM(cloudflare);
35
- let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
36
- let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
34
+ cloudflare = __toESM(cloudflare, 1);
35
+ let _hot_updater_server_database = require("@hot-updater/server/database");
36
+ let _hot_updater_server_plugins_api_keys = require("@hot-updater/server/plugins/api-keys");
37
+ let _hot_updater_server_plugins_insights = require("@hot-updater/server/plugins/insights");
37
38
  let node_url = require("node:url");
38
39
  let node_child_process = require("node:child_process");
39
40
  let node_string_decoder = require("node:string_decoder");
40
41
  let node_util = require("node:util");
41
42
  let node_process = require("node:process");
42
- node_process = __toESM(node_process);
43
+ node_process = __toESM(node_process, 1);
43
44
  let node_tty = require("node:tty");
44
- node_tty = __toESM(node_tty);
45
+ node_tty = __toESM(node_tty, 1);
45
46
  let node_path = require("node:path");
46
- node_path = __toESM(node_path);
47
+ node_path = __toESM(node_path, 1);
47
48
  let fs = require("fs");
48
- fs = __toESM(fs);
49
+ fs = __toESM(fs, 1);
49
50
  let node_timers_promises = require("node:timers/promises");
50
51
  let node_os = require("node:os");
51
52
  let node_events = require("node:events");
@@ -56,896 +57,118 @@ let node_stream = require("node:stream");
56
57
  let node_buffer = require("node:buffer");
57
58
  let cloudflare_error = require("cloudflare/error");
58
59
  let os = require("os");
59
- os = __toESM(os);
60
- //#region src/d1Rows.ts
61
- var InvalidD1RowError = class extends Error {
62
- name = "InvalidD1RowError";
63
- model;
64
- constructor(model) {
65
- super(`D1 returned an invalid ${model} row`);
66
- this.model = model;
67
- }
68
- };
69
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
70
- const stringValue = (row, field, model) => {
71
- const value = row[field];
72
- if (typeof value !== "string") throw new InvalidD1RowError(model);
73
- return value;
74
- };
75
- const nullableString = (row, field, model) => {
76
- const value = row[field];
77
- if (value === null) return null;
78
- if (typeof value !== "string") throw new InvalidD1RowError(model);
79
- return value;
80
- };
81
- const numberValue = (row, field, model) => {
82
- const value = row[field];
83
- if (typeof value !== "number") throw new InvalidD1RowError(model);
84
- return value;
85
- };
86
- const byteSizeValue = (row, field, model) => {
87
- const value = row[field];
88
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new InvalidD1RowError(model);
89
- return value;
90
- };
91
- const booleanValue = (row, field, model) => {
92
- const value = row[field];
93
- if (value === true || value === 1) return true;
94
- if (value === false || value === 0) return false;
95
- throw new InvalidD1RowError(model);
96
- };
97
- const jsonValue = (value, model) => {
98
- if (typeof value !== "string") throw new InvalidD1RowError(model);
99
- try {
100
- return JSON.parse(value);
101
- } catch (error) {
102
- if (error instanceof SyntaxError) throw new InvalidD1RowError(model);
103
- throw error;
104
- }
105
- };
106
- const metadata = (row) => {
107
- const value = jsonValue(row["metadata"], "bundles");
108
- if (!(0, _hot_updater_plugin_core.isDatabaseMetadataObject)(value)) throw new InvalidD1RowError("bundles");
109
- return value;
110
- };
111
- const bundleRow = (row) => {
112
- const platform = stringValue(row, "platform", "bundles");
113
- if (platform !== "ios" && platform !== "android") throw new InvalidD1RowError("bundles");
114
- return {
115
- id: stringValue(row, "id", "bundles"),
116
- platform,
117
- file_hash: stringValue(row, "file_hash", "bundles"),
118
- git_commit_hash: nullableString(row, "git_commit_hash", "bundles"),
119
- storage_uri: stringValue(row, "storage_uri", "bundles"),
120
- archive_byte_size: row["archive_byte_size"] === void 0 ? 0 : byteSizeValue(row, "archive_byte_size", "bundles"),
121
- metadata: metadata(row),
122
- manifest_storage_uri: nullableString(row, "manifest_storage_uri", "bundles"),
123
- manifest_file_hash: nullableString(row, "manifest_file_hash", "bundles"),
124
- asset_base_storage_uri: nullableString(row, "asset_base_storage_uri", "bundles")
125
- };
126
- };
127
- const patchRow = (row) => ({
128
- id: stringValue(row, "id", "bundle_patches"),
129
- bundle_id: stringValue(row, "bundle_id", "bundle_patches"),
130
- base_bundle_id: stringValue(row, "base_bundle_id", "bundle_patches"),
131
- base_file_hash: stringValue(row, "base_file_hash", "bundle_patches"),
132
- patch_file_hash: stringValue(row, "patch_file_hash", "bundle_patches"),
133
- patch_storage_uri: stringValue(row, "patch_storage_uri", "bundle_patches"),
134
- byte_size: byteSizeValue(row, "byte_size", "bundle_patches"),
135
- order_index: numberValue(row, "order_index", "bundle_patches")
136
- });
137
- const channelRow = (row) => ({
138
- id: stringValue(row, "id", "channels"),
139
- name: stringValue(row, "name", "channels")
140
- });
141
- const eventRow = (row) => {
142
- const type = stringValue(row, "type", "bundle_events");
143
- const platform = stringValue(row, "platform", "bundle_events");
144
- const fromBundleId = nullableString(row, "from_bundle_id", "bundle_events");
145
- const updateStrategy = nullableString(row, "update_strategy", "bundle_events");
146
- if (platform !== "ios" && platform !== "android" || !((type === "UPDATE_APPLIED" || type === "RECOVERED" || type === "RELEASE_ADOPTED") && typeof fromBundleId === "string" && (updateStrategy === "fingerprint" || updateStrategy === "appVersion") || type === "UNCHANGED" && fromBundleId === null && updateStrategy === null)) throw new InvalidD1RowError("bundle_events");
147
- return {
148
- id: stringValue(row, "id", "bundle_events"),
149
- type,
150
- install_id: stringValue(row, "install_id", "bundle_events"),
151
- user_id: nullableString(row, "user_id", "bundle_events"),
152
- username: nullableString(row, "username", "bundle_events"),
153
- from_release_id: nullableString(row, "from_release_id", "bundle_events"),
154
- from_bundle_id: fromBundleId,
155
- to_release_id: nullableString(row, "to_release_id", "bundle_events"),
156
- to_bundle_id: stringValue(row, "to_bundle_id", "bundle_events"),
157
- platform,
158
- app_version: stringValue(row, "app_version", "bundle_events"),
159
- channel: stringValue(row, "channel", "bundle_events"),
160
- cohort: stringValue(row, "cohort", "bundle_events"),
161
- update_strategy: updateStrategy,
162
- fingerprint_hash: nullableString(row, "fingerprint_hash", "bundle_events"),
163
- sdk_version: nullableString(row, "sdk_version", "bundle_events"),
164
- received_at_ms: numberValue(row, "received_at_ms", "bundle_events")
165
- };
166
- };
167
- const apiKeyRow = (row) => {
168
- const role = stringValue(row, "role", "api_keys");
169
- if (role !== "client") throw new InvalidD1RowError("api_keys");
170
- const revokedAt = row["revoked_at_ms"];
171
- return {
172
- id: stringValue(row, "id", "api_keys"),
173
- hash: stringValue(row, "hash", "api_keys"),
174
- name: stringValue(row, "name", "api_keys"),
175
- prefix: stringValue(row, "prefix", "api_keys"),
176
- role,
177
- created_at_ms: numberValue(row, "created_at_ms", "api_keys"),
178
- revoked_at_ms: revokedAt === null ? null : numberValue(row, "revoked_at_ms", "api_keys")
179
- };
180
- };
181
- const releaseTargetCohorts = (row) => {
182
- const value = jsonValue(row["target_cohorts"], "releases");
183
- if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) throw new InvalidD1RowError("releases");
184
- return value.filter((item) => typeof item === "string");
185
- };
186
- const releaseRow = (row) => {
187
- const platform = stringValue(row, "platform", "releases");
188
- const kind = stringValue(row, "kind", "releases");
189
- const strategy = stringValue(row, "strategy", "releases");
190
- const operation = stringValue(row, "operation", "releases");
191
- if (platform !== "ios" && platform !== "android" || kind !== "BUNDLE" && kind !== "EMBEDDED" || strategy !== "APP_VERSION" && strategy !== "FINGERPRINT" || operation !== "DEPLOY" && operation !== "PROMOTE" && operation !== "ROLLBACK") throw new InvalidD1RowError("releases");
192
- return {
193
- id: stringValue(row, "id", "releases"),
194
- revision: numberValue(row, "revision", "releases"),
195
- scope_key: stringValue(row, "scope_key", "releases"),
196
- channel_id: stringValue(row, "channel_id", "releases"),
197
- platform,
198
- kind,
199
- bundle_id: nullableString(row, "bundle_id", "releases"),
200
- strategy,
201
- target_app_version: nullableString(row, "target_app_version", "releases"),
202
- fingerprint_hash: nullableString(row, "fingerprint_hash", "releases"),
203
- enabled: booleanValue(row, "enabled", "releases"),
204
- should_force_update: booleanValue(row, "should_force_update", "releases"),
205
- message: nullableString(row, "message", "releases"),
206
- rollout_cohort_count: numberValue(row, "rollout_cohort_count", "releases"),
207
- target_cohorts: releaseTargetCohorts(row),
208
- operation,
209
- source_release_id: nullableString(row, "source_release_id", "releases"),
210
- created_at_ms: numberValue(row, "created_at_ms", "releases"),
211
- updated_at_ms: numberValue(row, "updated_at_ms", "releases")
212
- };
213
- };
214
- const releaseCatalogRow = (row) => {
215
- const platform = stringValue(row, "platform", "release_catalogs");
216
- const strategy = stringValue(row, "strategy", "release_catalogs");
217
- if (platform !== "ios" && platform !== "android" || strategy !== "APP_VERSION" && strategy !== "FINGERPRINT") throw new InvalidD1RowError("release_catalogs");
218
- return {
219
- scope_key: stringValue(row, "scope_key", "release_catalogs"),
220
- catalog_id: stringValue(row, "catalog_id", "release_catalogs"),
221
- strategy,
222
- channel_id: stringValue(row, "channel_id", "release_catalogs"),
223
- channel_key: stringValue(row, "channel_key", "release_catalogs"),
224
- platform,
225
- fingerprint_hash: nullableString(row, "fingerprint_hash", "release_catalogs"),
226
- generation: numberValue(row, "generation", "release_catalogs"),
227
- payload: stringValue(row, "payload", "release_catalogs"),
228
- catalog_hash: stringValue(row, "catalog_hash", "release_catalogs"),
229
- byte_size: numberValue(row, "byte_size", "release_catalogs"),
230
- is_tombstone: booleanValue(row, "is_tombstone", "release_catalogs"),
231
- updated_at_ms: numberValue(row, "updated_at_ms", "release_catalogs")
232
- };
233
- };
234
- function parseD1Row(model, value) {
235
- if (!isRecord(value)) throw new InvalidD1RowError(model);
236
- switch (model) {
237
- case "bundles": return bundleRow(value);
238
- case "bundle_patches": return patchRow(value);
239
- case "channels": return channelRow(value);
240
- case "bundle_events": return eventRow(value);
241
- case "api_keys": return apiKeyRow(value);
242
- case "releases": return releaseRow(value);
243
- case "release_catalogs": return releaseCatalogRow(value);
244
- }
245
- }
246
- //#endregion
247
- //#region src/d1Sql.ts
248
- var InvalidD1PredicateError = class extends Error {
249
- name = "InvalidD1PredicateError";
250
- };
251
- const encodeD1Value = (value) => {
252
- const encoded = JSON.stringify(value);
253
- if (encoded === void 0) throw new TypeError("D1 values must be JSON-serializable.");
254
- return encoded;
255
- };
256
- const bind = (value) => ({
257
- sql: "json_extract(?, '$')",
258
- params: [encodeD1Value(value)]
259
- });
260
- const escapeLikePattern = (value) => value.replaceAll("\\", "\\\\").replaceAll("%", "\\%").replaceAll("_", "\\_");
261
- const stringPredicate = (condition, operator) => {
262
- if (typeof condition.value !== "string") throw new InvalidD1PredicateError();
263
- if (condition.mode !== "insensitive") {
264
- const parameter = bind(condition.value);
265
- const column = `${condition.field} COLLATE BINARY`;
266
- const value = `${parameter.sql} COLLATE BINARY`;
267
- if (operator === "contains" || operator === "starts_with") return {
268
- sql: `instr(${column}, ${value}) ${operator === "contains" ? "> 0" : "= 1"}`,
269
- params: parameter.params
270
- };
271
- return {
272
- sql: `substr(${column}, length(${condition.field}) - length(${parameter.sql}) + 1) = ${value}`,
273
- params: [...parameter.params, ...parameter.params]
274
- };
275
- }
276
- const literal = escapeLikePattern(condition.value);
277
- const parameter = bind(operator === "contains" ? `%${literal}%` : operator === "starts_with" ? `${literal}%` : `%${literal}`);
278
- return {
279
- sql: `lower(${condition.field}) LIKE lower(${parameter.sql}) ESCAPE '\\'`,
280
- params: parameter.params
281
- };
282
- };
283
- const predicate = (condition) => {
284
- const operator = condition.operator ?? "eq";
285
- switch (operator) {
286
- case "eq":
287
- case "ne": {
288
- if (condition.value === null) return {
289
- sql: `${condition.field} IS ${operator === "ne" ? "NOT " : ""}NULL`,
290
- params: []
291
- };
292
- const parameter = bind(condition.value);
293
- const insensitive = "mode" in condition && condition.mode === "insensitive";
294
- const column = insensitive ? `lower(${condition.field})` : condition.field;
295
- const value = insensitive ? `lower(${parameter.sql})` : parameter.sql;
296
- return {
297
- sql: `${column} ${operator === "eq" ? "=" : "<>"} ${value}`,
298
- params: parameter.params
299
- };
300
- }
301
- case "gt":
302
- case "gte":
303
- case "lt":
304
- case "lte": {
305
- const sqlOperator = {
306
- gt: ">",
307
- gte: ">=",
308
- lt: "<",
309
- lte: "<="
310
- }[operator];
311
- const parameter = bind(condition.value);
312
- return {
313
- sql: `${condition.field} ${sqlOperator} ${parameter.sql}`,
314
- params: parameter.params
315
- };
316
- }
317
- case "in":
318
- case "not_in":
319
- if (!Array.isArray(condition.value)) throw new InvalidD1PredicateError();
320
- if (condition.value.length === 0) return {
321
- sql: operator === "not_in" ? "1 = 1" : "1 = 0",
322
- params: []
323
- };
324
- return {
325
- sql: `${condition.field} ${operator === "not_in" ? "NOT " : ""}IN (SELECT value FROM json_each(?))`,
326
- params: [encodeD1Value(condition.value)]
327
- };
328
- case "contains":
329
- case "starts_with":
330
- case "ends_with": return stringPredicate(condition, operator);
60
+ os = __toESM(os, 1);
61
+ //#region src/d1Executor.ts
62
+ var D1ExecutionError = class extends Error {
63
+ name = "D1ExecutionError";
64
+ constructor() {
65
+ super("D1 did not successfully execute every requested statement");
331
66
  }
332
67
  };
333
- const buildD1Where = (where) => {
334
- const [first, ...rest] = where ?? [];
335
- if (first === void 0) return {
336
- sql: "",
337
- params: []
338
- };
339
- const initial = predicate(first);
340
- let sql = initial.sql;
341
- const params = [...initial.params];
342
- for (const condition of rest) {
343
- const next = predicate(condition);
344
- sql = `(${sql} ${condition.connector === "OR" ? "OR" : "AND"} ${next.sql})`;
345
- params.push(...next.params);
346
- }
68
+ const toSqlResult = (result) => {
69
+ if (result.success === false) throw new D1ExecutionError();
347
70
  return {
348
- sql: ` WHERE ${sql}`,
349
- params
71
+ rows: result.results ?? [],
72
+ changes: result.meta?.changes ?? 0
350
73
  };
351
74
  };
352
- const buildD1Order = (orderBy) => orderBy === void 0 ? "" : ` ORDER BY ${orderBy.map((clause) => `${clause.field} ${clause.direction.toUpperCase()}${clause.nulls ? ` NULLS ${clause.nulls.toUpperCase()}` : ""}`).join(", ")}`;
353
- const d1Placeholders = (count) => Array.from({ length: count }, () => "json_extract(?, '$')").join(", ");
354
- const encodeD1Values = (values) => values.map(encodeD1Value);
355
- //#endregion
356
- //#region src/d1Query.ts
357
- const d1TableNames = {
358
- bundles: "bundles",
359
- bundle_patches: "bundle_patches",
360
- channels: "channels",
361
- bundle_events: "bundle_events",
362
- api_keys: "api_keys",
363
- release_catalogs: "release_catalogs",
364
- releases: "releases"
365
- };
366
- var D1QueryResultError = class extends Error {
367
- name = "D1QueryResultError";
368
- operation = "count";
369
- constructor(result) {
370
- super("D1 count query returned a malformed first row");
371
- this.result = result;
372
- }
373
- };
374
- const countD1Rows = async (executor, input) => {
375
- const where = buildD1Where(input.where);
376
- const table = d1TableNames[input.model];
377
- const source = input.distinct === void 0 ? `${table}${where.sql}` : `(SELECT DISTINCT ${input.distinct.join(", ")} FROM ${table}${where.sql}) AS distinct_rows`;
378
- const row = (await executor.query(`SELECT COUNT(*) AS count FROM ${source}`, where.params))[0];
379
- if (typeof row !== "object" || row === null || Array.isArray(row)) throw new D1QueryResultError(row);
380
- const count = Reflect.get(row, "count");
381
- if (typeof count !== "number" || !Number.isFinite(count)) throw new D1QueryResultError(row);
382
- return count;
383
- };
384
- const findManyD1Rows = async (executor, input) => {
385
- const where = buildD1Where(input.where);
386
- const orderBy = input.orderBy;
387
- const order = buildD1Order(orderBy);
388
- const table = d1TableNames[input.model];
389
- const source = input.distinctOn === void 0 ? `SELECT * FROM ${table}${where.sql}${order}` : `SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY ${input.distinctOn.fields.join(", ")}${order}) AS __hot_updater_rank FROM ${table}${where.sql}) AS distinct_rows WHERE __hot_updater_rank = 1${order}`;
390
- const pageParams = encodeD1Values([input.limit, input.offset]);
391
- const rows = await executor.query(`${source} LIMIT json_extract(?, '$') OFFSET json_extract(?, '$')`, [...where.params, ...pageParams]);
392
- switch (input.model) {
393
- case "bundles": return rows.map((row) => parseD1Row("bundles", row));
394
- case "bundle_patches": return rows.map((row) => parseD1Row("bundle_patches", row));
395
- case "channels": return rows.map((row) => parseD1Row("channels", row));
396
- case "bundle_events": return rows.map((row) => parseD1Row("bundle_events", row));
397
- case "api_keys": return rows.map((row) => parseD1Row("api_keys", row));
398
- case "releases": return rows.map((row) => parseD1Row("releases", row));
399
- case "release_catalogs": return rows.map((row) => parseD1Row("release_catalogs", row));
400
- }
401
- };
402
- //#endregion
403
- //#region src/d1Implementation.ts
404
- const EXPECTATION_CONFLICT_MARKER = "HOT_UPDATER_COMMIT_EXPECTATION_CONFLICT";
405
- const expectationGuard = (expectations) => {
406
- const clauses = [];
407
- const params = [];
408
- for (const expectation of expectations) {
409
- const isRelease = expectation.model === "releases";
410
- const table = isRelease ? "releases" : "release_catalogs";
411
- const keyField = isRelease ? "id" : "scope_key";
412
- const versionField = isRelease ? "revision" : "generation";
413
- const key = isRelease ? expectation.id : expectation.scopeKey;
414
- const version = isRelease ? expectation.revision : expectation.generation;
415
- if (version === null) {
416
- clauses.push(`NOT EXISTS (SELECT 1 FROM ${table} WHERE ${keyField} = json_extract(?, '$'))`);
417
- params.push(...encodeD1Values([key]));
418
- } else {
419
- clauses.push(`EXISTS (SELECT 1 FROM ${table} WHERE ${keyField} = json_extract(?, '$') AND ${versionField} = json_extract(?, '$'))`);
420
- params.push(...encodeD1Values([key, version]));
421
- }
422
- }
423
- return {
424
- sql: clauses.join(" AND ") || "1",
425
- params
426
- };
427
- };
428
- const readVersion = (row, field) => {
429
- if (typeof row !== "object" || row === null) return null;
430
- const value = Reflect.get(row, field);
431
- return typeof value === "number" ? value : null;
432
- };
433
- const expectationConflict = async (executor, expectations) => {
434
- for (const expectation of expectations) {
435
- const isRelease = expectation.model === "releases";
436
- const table = isRelease ? "releases" : "release_catalogs";
437
- const keyField = isRelease ? "id" : "scope_key";
438
- const versionField = isRelease ? "revision" : "generation";
439
- const key = isRelease ? expectation.id : expectation.scopeKey;
440
- const expectedVersion = isRelease ? expectation.revision : expectation.generation;
441
- const actualVersion = readVersion((await executor.query(`SELECT ${versionField} FROM ${table} WHERE ${keyField} = json_extract(?, '$') LIMIT 1`, encodeD1Values([key])))[0], versionField);
442
- if (actualVersion !== expectedVersion) return {
443
- committed: false,
444
- conflict: {
445
- actualVersion,
446
- changeIndex: -1,
447
- expectedVersion,
448
- key,
449
- model: expectation.model,
450
- reason: "version_conflict"
451
- }
452
- };
453
- }
454
- return null;
455
- };
456
- const isExpectationConflictError = (error) => {
75
+ /** D1 reports SQLite errors in the message; the SQL core classifies codes. */
76
+ const withSqliteCode = (error) => {
457
77
  const message = error instanceof Error ? error.message : String(error);
458
- return message.includes(EXPECTATION_CONFLICT_MARKER) || message.toLowerCase().includes("malformed json");
459
- };
460
- const bundleValues = (row) => [
461
- row.id,
462
- row.platform,
463
- row.file_hash,
464
- row.git_commit_hash,
465
- row.storage_uri,
466
- row.archive_byte_size,
467
- row.metadata,
468
- row.manifest_storage_uri,
469
- row.manifest_file_hash,
470
- row.asset_base_storage_uri
471
- ];
472
- const patchValues = (row) => [
473
- row.id,
474
- row.bundle_id,
475
- row.base_bundle_id,
476
- row.base_file_hash,
477
- row.patch_file_hash,
478
- row.patch_storage_uri,
479
- row.byte_size,
480
- row.order_index
481
- ];
482
- const channelValues = (row) => [row.id, row.name];
483
- const insertQuery = (input, guard, conflictMode = "returnExisting") => {
484
- let columns;
485
- let values;
486
- switch (input.model) {
487
- case "bundles":
488
- columns = [
489
- "id",
490
- "platform",
491
- "file_hash",
492
- "git_commit_hash",
493
- "storage_uri",
494
- "archive_byte_size",
495
- "metadata",
496
- "manifest_storage_uri",
497
- "manifest_file_hash",
498
- "asset_base_storage_uri"
499
- ];
500
- values = bundleValues(input.data);
501
- break;
502
- case "bundle_patches":
503
- columns = [
504
- "id",
505
- "bundle_id",
506
- "base_bundle_id",
507
- "base_file_hash",
508
- "patch_file_hash",
509
- "patch_storage_uri",
510
- "byte_size",
511
- "order_index"
512
- ];
513
- values = patchValues(input.data);
514
- break;
515
- case "channels":
516
- columns = ["id", "name"];
517
- values = channelValues(input.data);
518
- break;
519
- case "bundle_events":
520
- case "api_keys":
521
- case "release_catalogs":
522
- case "releases":
523
- columns = Object.keys(input.data);
524
- values = Object.values(input.data);
525
- break;
526
- }
527
- const conflict = input.onConflict !== "ignore" ? "" : input.model === "channels" ? conflictMode === "ignore" ? " ON CONFLICT(name) DO NOTHING" : " ON CONFLICT(name) DO UPDATE SET name = excluded.name" : input.model === "api_keys" ? conflictMode === "ignore" ? " ON CONFLICT(hash) DO NOTHING" : " ON CONFLICT(hash) DO UPDATE SET hash = excluded.hash" : "";
528
- return {
529
- sql: `INSERT INTO ${d1TableNames[input.model]} (${columns.join(", ")}) ${guard === void 0 ? `VALUES (${d1Placeholders(values.length)})` : `SELECT ${d1Placeholders(values.length)} WHERE ${guard.sql}`}${conflict} RETURNING *`,
530
- params: [...encodeD1Values(values), ...guard?.params ?? []]
531
- };
532
- };
533
- const updateEntries = (update) => Object.entries(update);
534
- const updateQuery = (input, guard) => {
535
- const entries = updateEntries(input.update);
536
- const where = buildD1Where(input.where);
537
- if (entries.length === 0) return {
538
- sql: `SELECT * FROM ${d1TableNames[input.model]}${where.sql}${guard ? ` AND ${guard.sql}` : ""} LIMIT 1`,
539
- params: [...where.params, ...guard?.params ?? []]
540
- };
541
- const assignments = entries.map(([field]) => `${field} = json_extract(?, '$')`).join(", ");
542
- return {
543
- sql: `UPDATE ${d1TableNames[input.model]} SET ${assignments}${where.sql}${guard ? ` AND ${guard.sql}` : ""} RETURNING *`,
544
- params: [
545
- ...encodeD1Values(entries.map(([, value]) => value)),
546
- ...where.params,
547
- ...guard?.params ?? []
548
- ]
549
- };
550
- };
551
- const deleteQuery = (input, guard) => {
552
- const where = buildD1Where(input.where);
553
- return {
554
- sql: `DELETE FROM ${d1TableNames[input.model]}${where.sql}${guard ? ` AND ${guard.sql}` : ""}`,
555
- params: [...where.params, ...guard?.params ?? []]
556
- };
557
- };
558
- const insertedKey = (change) => {
559
- if (change.operation !== "insert") return void 0;
560
- if (change.model === "bundles") return `bundles:${change.row.id}`;
561
- if (change.model === "apiKeys") return `api_keys:${change.row.id}`;
562
- if (change.model === "releases") return `releases:${change.row.id}`;
563
- };
564
- const requiredRow = (change, changeIndex) => {
565
- if (change.operation !== "update") return void 0;
566
- if (change.model === "bundles") return {
567
- model: "bundles",
568
- id: change.where.id,
569
- changeIndex
570
- };
571
- if (change.model === "apiKeys") return {
572
- model: "api_keys",
573
- id: change.where.id,
574
- changeIndex
575
- };
576
- if (change.model === "releases") return {
577
- model: "releases",
578
- id: change.where.id,
579
- changeIndex
580
- };
581
- };
582
- const channelDeletePrecondition = (changes, changeIndex, channelId) => {
583
- const releaseEffects = /* @__PURE__ */ new Map();
584
- for (const change of changes.slice(0, changeIndex)) {
585
- if (change.model !== "releases") continue;
586
- switch (change.operation) {
587
- case "insert":
588
- releaseEffects.set(change.row.id, change.row.channel_id);
589
- break;
590
- case "update": break;
591
- case "delete":
592
- releaseEffects.set(change.where.id, null);
593
- break;
594
- }
595
- }
596
- return {
597
- id: channelId,
598
- excludedReleaseIds: [...releaseEffects.keys()],
599
- addedReferenceReleaseIds: [...releaseEffects].filter(([, finalChannelId]) => finalChannelId === channelId).map(([releaseId]) => releaseId)
600
- };
601
- };
602
- const changeQuery = (change, guard) => {
603
- switch (change.model) {
604
- case "bundles": switch (change.operation) {
605
- case "insert": return insertQuery({
606
- model: "bundles",
607
- data: change.row
608
- }, guard);
609
- case "update": return updateQuery({
610
- model: "bundles",
611
- where: [{
612
- field: "id",
613
- value: change.where.id
614
- }],
615
- update: change.update
616
- }, guard);
617
- case "delete": return deleteQuery({
618
- model: "bundles",
619
- where: [{
620
- field: "id",
621
- value: change.where.id
622
- }]
623
- }, guard);
624
- }
625
- case "bundlePatches": return change.operation === "insert" ? insertQuery({
626
- model: "bundle_patches",
627
- data: change.row
628
- }, guard) : deleteQuery({
629
- model: "bundle_patches",
630
- where: [{
631
- field: "bundle_id",
632
- value: change.where.bundleId
633
- }]
634
- }, guard);
635
- case "releases": switch (change.operation) {
636
- case "insert": return insertQuery({
637
- model: "releases",
638
- data: change.row
639
- }, guard);
640
- case "update": return updateQuery({
641
- model: "releases",
642
- where: [{
643
- field: "id",
644
- value: change.where.id
645
- }],
646
- update: change.update
647
- }, guard);
648
- case "delete": return deleteQuery({
649
- model: "releases",
650
- where: [{
651
- field: "id",
652
- value: change.where.id
653
- }]
654
- }, guard);
655
- }
656
- case "releaseCatalogs": return {
657
- sql: `INSERT INTO release_catalogs (${Object.keys(change.row).join(", ")}) SELECT ${d1Placeholders(Object.keys(change.row).length)} WHERE ${guard.sql} ON CONFLICT(scope_key) DO UPDATE SET ${Object.keys(change.row).filter((field) => field !== "scope_key").map((field) => `${field} = excluded.${field}`).join(", ")} RETURNING *`,
658
- params: [...encodeD1Values(Object.values(change.row)), ...guard.params]
659
- };
660
- case "channels": return change.operation === "insert" ? insertQuery({
661
- model: "channels",
662
- data: change.row,
663
- onConflict: change.onConflict
664
- }, guard, "ignore") : {
665
- sql: `DELETE FROM channels WHERE id = json_extract(?, '$') AND NOT EXISTS (SELECT 1 FROM releases WHERE channel_id = json_extract(?, '$')) AND ${guard.sql}`,
666
- params: [...encodeD1Values([change.where.id, change.where.id]), ...guard.params]
667
- };
668
- case "analytics": return insertQuery({
669
- model: "bundle_events",
670
- data: change.row
671
- }, guard);
672
- case "apiKeys": return change.operation === "insert" ? insertQuery({
673
- model: "api_keys",
674
- data: change.row,
675
- onConflict: change.onConflict
676
- }, guard, "ignore") : updateQuery({
677
- model: "api_keys",
678
- where: [{
679
- field: "id",
680
- value: change.where.id
681
- }],
682
- update: { revoked_at_ms: change.update.revokedAtMs }
683
- }, guard);
684
- }
685
- };
686
- const createCommitPlan = (input) => {
687
- const checks = [];
688
- const statements = [];
689
- const expectations = input.expectations ?? [];
690
- if (expectations.length > 0) {
691
- const guard = expectationGuard(expectations);
692
- statements.push({
693
- sql: `SELECT CASE WHEN ${guard.sql} THEN 1 ELSE json_extract('${EXPECTATION_CONFLICT_MARKER}', '$') END AS expectation_guard`,
694
- params: guard.params
695
- });
696
- }
697
- const requiredRows = [];
698
- const channelDeletes = [];
699
- const inserted = /* @__PURE__ */ new Set();
700
- for (const [changeIndex, change] of input.changes.entries()) {
701
- const required = requiredRow(change, changeIndex);
702
- if (required !== void 0) {
703
- if (!inserted.has(`${required.model}:${required.id}`)) {
704
- requiredRows.push(required);
705
- checks.push({
706
- changeIndex,
707
- resultIndex: statements.length,
708
- conflictWhen: "empty",
709
- reason: "not_found"
710
- });
711
- statements.push({
712
- sql: `SELECT id FROM ${d1TableNames[required.model]} WHERE id = json_extract(?, '$') LIMIT 1`,
713
- params: encodeD1Values([required.id])
714
- });
715
- }
716
- }
717
- if (change.model === "channels" && change.operation === "delete") {
718
- const precondition = channelDeletePrecondition(input.changes, changeIndex, change.where.id);
719
- channelDeletes.push(precondition);
720
- checks.push({
721
- changeIndex,
722
- resultIndex: statements.length,
723
- conflictWhen: "nonempty",
724
- reason: "referenced"
725
- });
726
- statements.push({
727
- sql: "SELECT id FROM releases WHERE channel_id = json_extract(?, '$') AND id NOT IN (SELECT value FROM json_each(?)) UNION ALL SELECT value AS id FROM json_each(?) LIMIT 1",
728
- params: encodeD1Values([
729
- precondition.id,
730
- precondition.excludedReleaseIds,
731
- precondition.addedReferenceReleaseIds
732
- ])
733
- });
734
- }
735
- const key = insertedKey(change);
736
- if (key !== void 0) inserted.add(key);
737
- }
738
- const guard = {
739
- sql: `NOT EXISTS (
740
- SELECT 1 FROM json_each(?) AS required
741
- WHERE NOT EXISTS (
742
- SELECT 1 FROM bundles
743
- WHERE json_extract(required.value, '$.model') = 'bundles'
744
- AND bundles.id = json_extract(required.value, '$.id')
745
- UNION ALL
746
- SELECT 1 FROM api_keys
747
- WHERE json_extract(required.value, '$.model') = 'api_keys'
748
- AND api_keys.id = json_extract(required.value, '$.id')
749
- UNION ALL
750
- SELECT 1 FROM channels
751
- WHERE json_extract(required.value, '$.model') = 'channels'
752
- AND channels.id = json_extract(required.value, '$.id')
753
- UNION ALL
754
- SELECT 1 FROM releases
755
- WHERE json_extract(required.value, '$.model') = 'releases'
756
- AND releases.id = json_extract(required.value, '$.id')
757
- )
758
- ) AND NOT EXISTS (
759
- SELECT 1 FROM json_each(?) AS channel_delete
760
- WHERE EXISTS (
761
- SELECT 1 FROM releases
762
- WHERE releases.channel_id = json_extract(channel_delete.value, '$.id')
763
- AND releases.id NOT IN (
764
- SELECT value FROM json_each(
765
- json_extract(channel_delete.value, '$.excludedReleaseIds')
766
- )
767
- )
768
- UNION ALL
769
- SELECT value FROM json_each(
770
- json_extract(channel_delete.value, '$.addedReferenceReleaseIds')
771
- )
772
- )
773
- )`,
774
- params: encodeD1Values([requiredRows.map(({ model, id }) => ({
775
- model,
776
- id
777
- })), channelDeletes])
778
- };
779
- statements.push(...input.changes.map((change) => changeQuery(change, guard)));
780
- return {
781
- checks,
782
- statements
783
- };
784
- };
785
- const resultForPlan = (plan, results) => {
786
- const missing = plan.checks.find(({ conflictWhen, resultIndex }) => conflictWhen === "empty" ? (results[resultIndex]?.length ?? 0) === 0 : (results[resultIndex]?.length ?? 0) > 0);
787
- return missing === void 0 ? { committed: true } : {
788
- committed: false,
789
- conflict: {
790
- changeIndex: missing.changeIndex,
791
- reason: missing.reason
792
- }
793
- };
794
- };
795
- const insertChannel = async (executor, input) => {
796
- const insert = insertQuery({
797
- model: "channels",
798
- data: input.row,
799
- onConflict: "ignore"
800
- }, void 0, "ignore");
801
- const select = {
802
- sql: "SELECT id, name FROM channels WHERE name = json_extract(?, '$') LIMIT 1",
803
- params: encodeD1Values([input.row.name])
804
- };
805
- const [insertedRows = [], canonicalRows = []] = await executor.batch([insert, select]);
806
- return {
807
- row: parseD1Row("channels", canonicalRows[0]),
808
- inserted: insertedRows.length > 0
809
- };
810
- };
811
- const deleteChannel = async (executor, input) => {
812
- const [channelRows = [], referenceRows = [], deletedRows = []] = await executor.batch([
813
- {
814
- sql: "SELECT id FROM channels WHERE id = json_extract(?, '$') LIMIT 1",
815
- params: encodeD1Values([input.id])
816
- },
817
- {
818
- sql: "SELECT id FROM releases WHERE channel_id = json_extract(?, '$') LIMIT 1",
819
- params: encodeD1Values([input.id])
820
- },
821
- {
822
- sql: "DELETE FROM channels WHERE id = json_extract(?, '$') AND NOT EXISTS (SELECT 1 FROM releases WHERE channel_id = json_extract(?, '$')) RETURNING id",
823
- params: encodeD1Values([input.id, input.id])
824
- }
825
- ]);
826
- if (channelRows.length === 0) return {
827
- deleted: false,
828
- reason: "not_found"
829
- };
830
- if (referenceRows.length > 0) return {
831
- deleted: false,
832
- reason: "not_empty"
833
- };
834
- return deletedRows.length > 0 ? { deleted: true } : {
835
- deleted: false,
836
- reason: "not_empty"
837
- };
78
+ const code = /UNIQUE constraint failed|constraint failed: .*PRIMARY/iu.test(message) ? "SQLITE_CONSTRAINT_UNIQUE" : /SQLITE_BUSY|database is locked/iu.test(message) ? "SQLITE_BUSY" : void 0;
79
+ return code === void 0 ? error : Object.assign(new Error(message, { cause: error }), { code });
838
80
  };
839
- const createD1Implementation = (executor) => ({
840
- async create(input) {
841
- const query = insertQuery(input);
842
- const rows = await executor.query(query.sql, query.params);
843
- switch (input.model) {
844
- case "bundles": return parseD1Row("bundles", rows[0]);
845
- case "bundle_patches": return parseD1Row("bundle_patches", rows[0]);
846
- case "channels": return parseD1Row("channels", rows[0]);
847
- case "bundle_events": return parseD1Row("bundle_events", rows[0]);
848
- case "api_keys": return parseD1Row("api_keys", rows[0]);
849
- case "releases": return parseD1Row("releases", rows[0]);
850
- case "release_catalogs": return parseD1Row("release_catalogs", rows[0]);
851
- }
852
- },
853
- async update(input) {
854
- const query = updateQuery(input);
855
- const rows = await executor.query(query.sql, query.params);
856
- if (rows[0] === void 0) return null;
857
- switch (input.model) {
858
- case "bundles": return parseD1Row("bundles", rows[0]);
859
- case "api_keys": return parseD1Row("api_keys", rows[0]);
860
- case "releases": return parseD1Row("releases", rows[0]);
861
- case "release_catalogs": return parseD1Row("release_catalogs", rows[0]);
862
- }
863
- },
864
- async delete(input) {
865
- const query = deleteQuery(input);
866
- await executor.query(query.sql, query.params);
867
- },
868
- count: (input) => countD1Rows(executor, input),
869
- async findOne(input) {
870
- const where = buildD1Where(input.where);
871
- const rows = await executor.query(`SELECT * FROM ${d1TableNames[input.model]}${where.sql} LIMIT 1`, where.params);
872
- if (rows[0] === void 0) return null;
873
- switch (input.model) {
874
- case "bundles": return parseD1Row("bundles", rows[0]);
875
- case "bundle_patches": return parseD1Row("bundle_patches", rows[0]);
876
- case "channels": return parseD1Row("channels", rows[0]);
877
- case "api_keys": return parseD1Row("api_keys", rows[0]);
878
- case "releases": return parseD1Row("releases", rows[0]);
879
- case "release_catalogs": return parseD1Row("release_catalogs", rows[0]);
880
- }
881
- },
882
- findMany: (input) => findManyD1Rows(executor, input),
883
- insertChannel: (input) => insertChannel(executor, input),
884
- deleteChannel: (input) => deleteChannel(executor, input),
885
- async commit(input) {
886
- if (input.changes.length === 0) return { committed: true };
887
- const expectations = input.expectations ?? [];
888
- const conflict = await expectationConflict(executor, expectations);
889
- if (conflict !== null) return conflict;
890
- const plan = createCommitPlan(input);
891
- try {
892
- return resultForPlan(plan, await executor.batch(plan.statements));
893
- } catch (error) {
894
- if (expectations.length === 0 || !isExpectationConflictError(error)) throw error;
895
- return await expectationConflict(executor, expectations) ?? {
896
- committed: false,
897
- conflict: {
898
- actualVersion: expectations[0].model === "releases" ? expectations[0].revision : expectations[0].generation,
899
- changeIndex: -1,
900
- expectedVersion: expectations[0].model === "releases" ? expectations[0].revision : expectations[0].generation,
901
- key: expectations[0].model === "releases" ? expectations[0].id : expectations[0].scopeKey,
902
- model: expectations[0].model,
903
- reason: "version_conflict"
81
+ /**
82
+ * Hot Updater's database on D1: the storage engine through the shared SQL
83
+ * core, fenced by the schema settings. D1 has no interactive transactions,
84
+ * so each write is one atomic batch that evaluates its guards first
85
+ * (`_hu_write`).
86
+ */
87
+ const createD1Database = (runner) => {
88
+ return (0, _hot_updater_server_database.createEngineDatabase)({
89
+ name: "d1Database",
90
+ adapter: (0, _hot_updater_server_database.createSqlAdapter)({
91
+ executor: {
92
+ dialect: "sqlite",
93
+ execute: (statement) => runner.query(statement).catch((error) => {
94
+ throw withSqliteCode(error);
95
+ }),
96
+ batch: (statements) => runner.batch(statements).catch((error) => {
97
+ throw withSqliteCode(error);
98
+ }),
99
+ transaction: () => {
100
+ throw new Error("D1 has no interactive transactions; writes are batches.");
904
101
  }
905
- };
906
- }
907
- }
908
- });
102
+ },
103
+ maxOps: 450,
104
+ maxParams: 100
105
+ })
106
+ });
107
+ };
108
+ //#endregion
109
+ //#region src/d1Schema.ts
110
+ /**
111
+ * D1's schema: the guard table batch writes need, then the shared SQL
112
+ * schema, settings last. Every statement can run again, so a migration for a
113
+ * server's plugin tables repeats the built-in ones.
114
+ */
115
+ const d1SchemaStatements = ({ schema, settings } = _hot_updater_server_database.builtInTarget) => [...(0, _hot_updater_server_database.createTableStatements)("sqlite", [_hot_updater_server_database.WRITE_GUARD_TABLE]), ...(0, _hot_updater_server_db.generateEngineSql)("sqlite", schema, settings)];
116
+ /** The schema as a D1 migration, which `wrangler d1 migrations apply` runs. */
117
+ const d1SchemaSql = (target) => `-- HotUpdater.schema\n\n${d1SchemaStatements(target).map((statement) => `${statement};`).join("\n\n")}\n`;
909
118
  //#endregion
910
119
  //#region src/d1Database.ts
120
+ /** The REST API binds text: each value goes as JSON and is read back with `json_extract`. */
121
+ const encode = ({ sql, params }) => ({
122
+ sql: sql.replaceAll("?", () => "json_extract(?, '$')"),
123
+ params: params.map((value) => JSON.stringify(value ?? null))
124
+ });
125
+ /**
126
+ * Hot Updater's database on D1 through the Cloudflare REST API, for the CLI
127
+ * and console. `hot-updater db generate` writes a D1 migration of the built-in
128
+ * tables and the server's plugin tables to `migrations`, and
129
+ * `hot-updater db migrate` applies them through the API.
130
+ */
911
131
  const d1Database = (config) => {
912
132
  const cloudflare$1 = new cloudflare.default({ apiToken: config.cloudflareApiToken });
913
133
  const execute = async (statements) => {
914
- const first = statements[0];
134
+ const [first] = statements;
915
135
  if (first === void 0) return [];
916
136
  const body = statements.length === 1 ? {
917
137
  account_id: config.accountId,
918
- sql: first.sql,
919
- params: [...first.params]
138
+ ...encode(first)
920
139
  } : {
921
140
  account_id: config.accountId,
922
- batch: statements.map(({ sql, params }) => ({
923
- sql,
924
- params: [...params]
925
- }))
141
+ batch: statements.map(encode)
926
142
  };
927
- const page = await cloudflare$1.d1.database.query(config.databaseId, { ...body });
143
+ const page = await cloudflare$1.d1.database.query(config.databaseId, body);
928
144
  const results = [];
929
- for await (const resultPage of page.iterPages()) for (const result of resultPage.result) results.push(result.results ?? []);
145
+ for await (const resultPage of page.iterPages()) for (const result of resultPage.result) results.push(toSqlResult(result));
146
+ if (results.length !== statements.length) throw new D1ExecutionError();
930
147
  return results;
931
148
  };
932
- const adapter = (0, _hot_updater_plugin_core_internal.createDatabasePluginAdapter)("d1Database", createD1Implementation({
933
- async query(sql, params) {
934
- return (await execute([{
935
- sql,
936
- params
937
- }])).flat();
938
- },
939
- batch: execute
940
- }));
941
- return (0, _hot_updater_plugin_core.createDatabasePlugin)({
942
- name: "d1Database",
943
- models: adapter.models,
944
- commit: adapter.commit,
945
- ...adapter.dispose ? { dispose: adapter.dispose } : {}
946
- });
149
+ return {
150
+ ...createD1Database({
151
+ query: async (statement) => (await execute([statement]))[0],
152
+ batch: execute
153
+ }),
154
+ generateSchema: ((version, _name, target = _hot_updater_server_database.builtInTarget) => {
155
+ if (version !== "latest" && version !== _hot_updater_server_database.builtInSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
156
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
157
+ return {
158
+ code: d1SchemaSql(target),
159
+ path: `migrations/${timestamp}_hot-updater.sql`
160
+ };
161
+ })
162
+ };
947
163
  };
948
164
  //#endregion
165
+ //#region src/plugins.ts
166
+ /**
167
+ * The plugins the managed Cloudflare server runs: Insights, and API keys on every
168
+ * client route. Its Worker imports this list.
169
+ */
170
+ const plugins = [(0, _hot_updater_server_plugins_insights.insights)(), (0, _hot_updater_server_plugins_api_keys.apiKeys)()];
171
+ //#endregion
949
172
  //#region ../../node_modules/.pnpm/is-plain-obj@4.1.0/node_modules/is-plain-obj/index.js
950
173
  function isPlainObject(value) {
951
174
  if (typeof value !== "object" || value === null) return false;
@@ -1044,7 +267,8 @@ const parseTemplate = ({ templates, expressions, tokens, index, template }) => {
1044
267
  const newTokens = concatTokens(tokens, nextTokens, leadingWhitespaces);
1045
268
  if (index === expressions.length) return newTokens;
1046
269
  const expression = expressions[index];
1047
- return concatTokens(newTokens, Array.isArray(expression) ? expression.map((expression) => parseExpression(expression)) : [parseExpression(expression)], trailingWhitespaces);
270
+ const expressionTokens = Array.isArray(expression) ? expression.map((expression) => parseExpression(expression)) : [parseExpression(expression)];
271
+ return concatTokens(newTokens, expressionTokens, trailingWhitespaces);
1048
272
  };
1049
273
  const splitByWhitespaces = (template, rawTemplate) => {
1050
274
  if (rawTemplate.length === 0) return {
@@ -1077,7 +301,7 @@ const splitByWhitespaces = (template, rawTemplate) => {
1077
301
  trailingWhitespaces
1078
302
  };
1079
303
  };
1080
- const DELIMITERS = new Set([
304
+ const DELIMITERS = /* @__PURE__ */ new Set([
1081
305
  " ",
1082
306
  " ",
1083
307
  "\r",
@@ -1129,7 +353,8 @@ const normalizeFdSpecificOptions = (options) => {
1129
353
  };
1130
354
  const normalizeFdSpecificOption = (options, optionName) => {
1131
355
  const optionBaseArray = Array.from({ length: getStdioLength(options) + 1 });
1132
- return addDefaultValue$1(normalizeFdSpecificValue(options[optionName], optionBaseArray, optionName), optionName);
356
+ const optionArray = normalizeFdSpecificValue(options[optionName], optionBaseArray, optionName);
357
+ return addDefaultValue$1(optionArray, optionName);
1133
358
  };
1134
359
  const getStdioLength = ({ stdio }) => Array.isArray(stdio) ? Math.max(stdio.length, STANDARD_STREAMS_ALIASES.length) : STANDARD_STREAMS_ALIASES.length;
1135
360
  const normalizeFdSpecificValue = (optionValue, optionArray, optionName) => isPlainObject(optionValue) ? normalizeOptionObject(optionValue, optionArray, optionName) : optionArray.fill(optionValue);
@@ -1162,7 +387,7 @@ const addDefaultValue$1 = (optionArray, optionName) => optionArray.map((optionVa
1162
387
  const DEFAULT_OPTIONS = {
1163
388
  lines: false,
1164
389
  buffer: true,
1165
- maxBuffer: 1e3 * 1e3 * 100,
390
+ maxBuffer: 1e8,
1166
391
  verbose: (0, node_util.debuglog)("execa").enabled ? "full" : "none",
1167
392
  stripFinalNewline: true
1168
393
  };
@@ -1210,7 +435,7 @@ const escapeControlCharacter = (character) => {
1210
435
  };
1211
436
  const getSpecialCharRegExp = () => {
1212
437
  try {
1213
- return /* @__PURE__ */ new RegExp("\\p{Separator}|\\p{Other}", "gu");
438
+ return new RegExp("\\p{Separator}|\\p{Other}", "gu");
1214
439
  } catch {
1215
440
  return /[\s\u0000-\u001F\u007F-\u009F\u00AD]/g;
1216
441
  }
@@ -1630,11 +855,13 @@ const appendNewline = (printedLine) => printedLine.endsWith("\n") ? printedLine
1630
855
  //#endregion
1631
856
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/verbose/log.js
1632
857
  const verboseLog = ({ type, verboseMessage, fdNumber, verboseInfo, result }) => {
1633
- const finalLines = applyVerboseOnLines(getPrintedLines(verboseMessage, getVerboseObject({
858
+ const verboseObject = getVerboseObject({
1634
859
  type,
1635
860
  result,
1636
861
  verboseInfo
1637
- })), verboseInfo, fdNumber);
862
+ });
863
+ const printedLines = getPrintedLines(verboseMessage, verboseObject);
864
+ const finalLines = applyVerboseOnLines(printedLines, verboseInfo, fdNumber);
1638
865
  if (finalLines !== "") console.warn(finalLines.slice(0, -1));
1639
866
  };
1640
867
  const getVerboseObject = ({ type, result, verboseInfo: { escapedCommand, commandId, rawOptions: { piped = false, ...options } } }) => ({
@@ -1657,7 +884,8 @@ const getPrintedLine = (verboseObject) => {
1657
884
  };
1658
885
  };
1659
886
  const serializeVerboseMessage = (message) => {
1660
- return escapeLines(typeof message === "string" ? message : (0, node_util.inspect)(message)).replaceAll(" ", " ".repeat(TAB_SIZE));
887
+ const messageString = typeof message === "string" ? message : (0, node_util.inspect)(message);
888
+ return escapeLines(messageString).replaceAll(" ", " ".repeat(TAB_SIZE));
1661
889
  };
1662
890
  const TAB_SIZE = 2;
1663
891
  //#endregion
@@ -1702,7 +930,8 @@ const getDurationMs = (startTime) => Number(node_process.hrtime.bigint() - start
1702
930
  const handleCommand = (filePath, rawArguments, rawOptions) => {
1703
931
  const startTime = getStartTime();
1704
932
  const { command, escapedCommand } = joinCommand(filePath, rawArguments);
1705
- const verboseInfo = getVerboseInfo(normalizeFdSpecificOption(rawOptions, "verbose"), escapedCommand, { ...rawOptions });
933
+ const verbose = normalizeFdSpecificOption(rawOptions, "verbose");
934
+ const verboseInfo = getVerboseInfo(verbose, escapedCommand, { ...rawOptions });
1706
935
  logCommand(escapedCommand, verboseInfo);
1707
936
  return {
1708
937
  command,
@@ -1823,7 +1052,8 @@ var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1823
1052
  const getNotFoundError = (cmd) => Object.assign(/* @__PURE__ */ new Error(`not found: ${cmd}`), { code: "ENOENT" });
1824
1053
  const getPathInfo = (cmd, opt) => {
1825
1054
  const colon = opt.colon || COLON;
1826
- const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [...isWindows ? [process.cwd()] : [], ...(opt.path || process.env.PATH || "").split(colon)];
1055
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [...isWindows ? [process.cwd()] : [], ...(opt.path || process.env.PATH ||
1056
+ /* istanbul ignore next: very unusual */ "").split(colon)];
1827
1057
  const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
1828
1058
  const pathExt = isWindows ? pathExtExe.split(colon) : [""];
1829
1059
  if (isWindows) {
@@ -1848,14 +1078,17 @@ var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1848
1078
  const ppRaw = pathEnv[i];
1849
1079
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
1850
1080
  const pCmd = path$13.join(pathPart, cmd);
1851
- resolve(subStep(!pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd, i, 0));
1081
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
1082
+ resolve(subStep(p, i, 0));
1852
1083
  });
1853
1084
  const subStep = (p, i, ii) => new Promise((resolve, reject) => {
1854
1085
  if (ii === pathExt.length) return resolve(step(i + 1));
1855
1086
  const ext = pathExt[ii];
1856
1087
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
1857
- if (!er && is) if (opt.all) found.push(p + ext);
1858
- else return resolve(p + ext);
1088
+ if (!er && is) {
1089
+ if (opt.all) found.push(p + ext);
1090
+ else return resolve(p + ext);
1091
+ }
1859
1092
  return resolve(subStep(p, i, ii + 1));
1860
1093
  });
1861
1094
  });
@@ -1873,8 +1106,10 @@ var require_which = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1873
1106
  for (let j = 0; j < pathExt.length; j++) {
1874
1107
  const cur = p + pathExt[j];
1875
1108
  try {
1876
- if (isexe.sync(cur, { pathExt: pathExtExe })) if (opt.all) found.push(cur);
1877
- else return cur;
1109
+ if (isexe.sync(cur, { pathExt: pathExtExe })) {
1110
+ if (opt.all) found.push(cur);
1111
+ else return cur;
1112
+ }
1878
1113
  } catch (ex) {}
1879
1114
  }
1880
1115
  }
@@ -2565,7 +1800,7 @@ const normalizeForceKillAfterDelay = (forceKillAfterDelay) => {
2565
1800
  if (!Number.isFinite(forceKillAfterDelay) || forceKillAfterDelay < 0) throw new TypeError(`Expected the \`forceKillAfterDelay\` option to be a non-negative integer, got \`${forceKillAfterDelay}\` (${typeof forceKillAfterDelay})`);
2566
1801
  return forceKillAfterDelay;
2567
1802
  };
2568
- const DEFAULT_FORCE_KILL_TIMEOUT = 1e3 * 5;
1803
+ const DEFAULT_FORCE_KILL_TIMEOUT = 5e3;
2569
1804
  const subprocessKill = ({ kill, options: { forceKillAfterDelay, killSignal }, onInternalError, context, controller }, signalOrError, errorArgument) => {
2570
1805
  const { signal, error } = parseKillArguments(signalOrError, errorArgument, killSignal);
2571
1806
  emitKillError(error, onInternalError);
@@ -2667,7 +1902,7 @@ const handleSerializationError = ({ error, methodName, isSubprocess, message })
2667
1902
  if (isSerializationError(error)) throw new Error(`${getMethodName(methodName, isSubprocess)}'s argument type is invalid: the message cannot be serialized: ${String(message)}.`, { cause: error });
2668
1903
  };
2669
1904
  const isSerializationError = ({ code, message }) => SERIALIZATION_ERROR_CODES.has(code) || SERIALIZATION_ERROR_MESSAGES.some((serializationErrorMessage) => message.includes(serializationErrorMessage));
2670
- const SERIALIZATION_ERROR_CODES = new Set(["ERR_MISSING_ARGS", "ERR_INVALID_ARG_TYPE"]);
1905
+ const SERIALIZATION_ERROR_CODES = /* @__PURE__ */ new Set(["ERR_MISSING_ARGS", "ERR_INVALID_ARG_TYPE"]);
2671
1906
  const SERIALIZATION_ERROR_MESSAGES = [
2672
1907
  "could not be cloned",
2673
1908
  "circular structure",
@@ -2877,7 +2112,8 @@ const isConnected = (anyProcess) => {
2877
2112
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/ipc/strict.js
2878
2113
  const handleSendStrict = ({ anyProcess, channel, isSubprocess, message, strict }) => {
2879
2114
  if (!strict) return message;
2880
- const hasListeners = hasMessageListeners(anyProcess, getIpcEmitter(anyProcess, channel, isSubprocess));
2115
+ const ipcEmitter = getIpcEmitter(anyProcess, channel, isSubprocess);
2116
+ const hasListeners = hasMessageListeners(anyProcess, ipcEmitter);
2881
2117
  return {
2882
2118
  id: count++,
2883
2119
  type: REQUEST_TYPE,
@@ -3109,7 +2345,8 @@ const throwOnGracefulCancel = ({ subprocess, cancelSignal, gracefulCancel, force
3109
2345
  })] : [];
3110
2346
  const sendOnAbort = async ({ subprocess, cancelSignal, forceKillAfterDelay, context, controller: { signal } }) => {
3111
2347
  await onAbortedSignal(cancelSignal, signal);
3112
- await sendAbort(subprocess, getReason(cancelSignal));
2348
+ const reason = getReason(cancelSignal);
2349
+ await sendAbort(subprocess, reason);
3113
2350
  killOnTimeout({
3114
2351
  kill: subprocess.kill,
3115
2352
  forceKillAfterDelay,
@@ -3221,8 +2458,8 @@ Please rename it to ${serializeEncoding(correctEncoding)}.`);
3221
2458
  throw new TypeError(`Invalid option \`encoding: ${serializeEncoding(encoding)}\`.
3222
2459
  Please rename it to one of: ${correctEncodings}.`);
3223
2460
  };
3224
- const TEXT_ENCODINGS = new Set(["utf8", "utf16le"]);
3225
- const BINARY_ENCODINGS = new Set([
2461
+ const TEXT_ENCODINGS = /* @__PURE__ */ new Set(["utf8", "utf16le"]);
2462
+ const BINARY_ENCODINGS = /* @__PURE__ */ new Set([
3226
2463
  "buffer",
3227
2464
  "hex",
3228
2465
  "base64",
@@ -3230,7 +2467,7 @@ const BINARY_ENCODINGS = new Set([
3230
2467
  "latin1",
3231
2468
  "ascii"
3232
2469
  ]);
3233
- const ENCODINGS = new Set([...TEXT_ENCODINGS, ...BINARY_ENCODINGS]);
2470
+ const ENCODINGS = /* @__PURE__ */ new Set([...TEXT_ENCODINGS, ...BINARY_ENCODINGS]);
3234
2471
  const getCorrectEncoding = (encoding) => {
3235
2472
  if (encoding === null) return "buffer";
3236
2473
  if (typeof encoding !== "string") return;
@@ -3277,7 +2514,8 @@ const normalizeOptions = (filePath, rawArguments, rawOptions) => {
3277
2514
  rawOptions.cwd = normalizeCwd(rawOptions.cwd);
3278
2515
  const [processedFile, processedArguments, processedOptions] = handleNodeOption(filePath, rawArguments, rawOptions);
3279
2516
  const { command: file, args: commandArguments, options: initialOptions } = import_cross_spawn.default._parse(processedFile, processedArguments, processedOptions);
3280
- const options = addDefaultOptions(normalizeFdSpecificOptions(initialOptions));
2517
+ const fdOptions = normalizeFdSpecificOptions(initialOptions);
2518
+ const options = addDefaultOptions(fdOptions);
3281
2519
  validateTimeout(options);
3282
2520
  validateEncoding(options);
3283
2521
  validateIpcInputOption(options);
@@ -3478,14 +2716,17 @@ const getStreamContents$1 = async (stream, { init, convertChunk, getSize, trunca
3478
2716
  const state = init();
3479
2717
  state.length = 0;
3480
2718
  try {
3481
- for await (const chunk of asyncIterable) appendChunk({
3482
- convertedChunk: convertChunk[getChunkType(chunk)](chunk, state),
3483
- state,
3484
- getSize,
3485
- truncateChunk,
3486
- addChunk,
3487
- maxBuffer
3488
- });
2719
+ for await (const chunk of asyncIterable) {
2720
+ const convertedChunk = convertChunk[getChunkType(chunk)](chunk, state);
2721
+ appendChunk({
2722
+ convertedChunk,
2723
+ state,
2724
+ getSize,
2725
+ truncateChunk,
2726
+ addChunk,
2727
+ maxBuffer
2728
+ });
2729
+ }
3489
2730
  appendFinalChunk({
3490
2731
  state,
3491
2732
  convertChunk,
@@ -3771,7 +3012,8 @@ const getErrorPrefix = ({ originalError, timedOut, timeout, isMaxBuffer, maxBuff
3771
3012
  const getForcefulSuffix = (isForcefullyTerminated, forceKillAfterDelay) => isForcefullyTerminated ? ` and was forcefully terminated after ${forceKillAfterDelay} milliseconds` : "";
3772
3013
  const getOriginalMessage = (originalError, cwd) => {
3773
3014
  if (originalError instanceof DiscardedError) return;
3774
- const escapedOriginalMessage = escapeLines(fixCwdError(isExecaError(originalError) ? originalError.originalMessage : String(originalError?.message ?? originalError), cwd));
3015
+ const originalMessage = isExecaError(originalError) ? originalError.originalMessage : String(originalError?.message ?? originalError);
3016
+ const escapedOriginalMessage = escapeLines(fixCwdError(originalMessage, cwd));
3775
3017
  return escapedOriginalMessage === "" ? void 0 : escapedOriginalMessage;
3776
3018
  };
3777
3019
  const serializeIpcMessage = (ipcMessage) => typeof ipcMessage === "string" ? ipcMessage : (0, node_util.inspect)(ipcMessage);
@@ -3982,26 +3224,28 @@ function prettyMilliseconds(milliseconds, options) {
3982
3224
  add(Number(parsed.hours), "hour", "h");
3983
3225
  }
3984
3226
  add(Number(parsed.minutes), "minute", "m");
3985
- if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) {
3986
- const seconds = Number(parsed.seconds);
3987
- const milliseconds = Number(parsed.milliseconds);
3988
- const microseconds = Number(parsed.microseconds);
3989
- const nanoseconds = Number(parsed.nanoseconds);
3990
- add(seconds, "second", "s");
3991
- if (options.formatSubMilliseconds) {
3992
- add(milliseconds, "millisecond", "ms");
3993
- add(microseconds, "microsecond", "µs");
3994
- add(nanoseconds, "nanosecond", "ns");
3227
+ if (!options.hideSeconds) {
3228
+ if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) {
3229
+ const seconds = Number(parsed.seconds);
3230
+ const milliseconds = Number(parsed.milliseconds);
3231
+ const microseconds = Number(parsed.microseconds);
3232
+ const nanoseconds = Number(parsed.nanoseconds);
3233
+ add(seconds, "second", "s");
3234
+ if (options.formatSubMilliseconds) {
3235
+ add(milliseconds, "millisecond", "ms");
3236
+ add(microseconds, "microsecond", "µs");
3237
+ add(nanoseconds, "nanosecond", "ns");
3238
+ } else {
3239
+ const millisecondsAndBelow = milliseconds + microseconds / 1e3 + nanoseconds / 1e6;
3240
+ const millisecondsDecimalDigits = typeof options.millisecondsDecimalDigits === "number" ? options.millisecondsDecimalDigits : 0;
3241
+ const millisecondsString = millisecondsDecimalDigits ? millisecondsAndBelow.toFixed(millisecondsDecimalDigits) : millisecondsAndBelow >= 1 ? Math.round(millisecondsAndBelow) : Math.ceil(millisecondsAndBelow);
3242
+ add(Number.parseFloat(millisecondsString), "millisecond", "ms", millisecondsString);
3243
+ }
3995
3244
  } else {
3996
- const millisecondsAndBelow = milliseconds + microseconds / 1e3 + nanoseconds / 1e6;
3997
- const millisecondsDecimalDigits = typeof options.millisecondsDecimalDigits === "number" ? options.millisecondsDecimalDigits : 0;
3998
- const millisecondsString = millisecondsDecimalDigits ? millisecondsAndBelow.toFixed(millisecondsDecimalDigits) : millisecondsAndBelow >= 1 ? Math.round(millisecondsAndBelow) : Math.ceil(millisecondsAndBelow);
3999
- add(Number.parseFloat(millisecondsString), "millisecond", "ms", millisecondsString);
3245
+ const secondsFixed = floorDecimals((isBigInt ? Number(milliseconds % ONE_DAY_IN_MILLISECONDS) : milliseconds) / 1e3 % 60, typeof options.secondsDecimalDigits === "number" ? options.secondsDecimalDigits : 1);
3246
+ const secondsString = options.keepDecimalsOnWholeSeconds ? secondsFixed : secondsFixed.replace(/\.0+$/, "");
3247
+ add(Number.parseFloat(secondsString), "second", "s", secondsString);
4000
3248
  }
4001
- } else {
4002
- const secondsFixed = floorDecimals((isBigInt ? Number(milliseconds % ONE_DAY_IN_MILLISECONDS) : milliseconds) / 1e3 % 60, typeof options.secondsDecimalDigits === "number" ? options.secondsDecimalDigits : 1);
4003
- const secondsString = options.keepDecimalsOnWholeSeconds ? secondsFixed : secondsFixed.replace(/\.0+$/, "");
4004
- add(Number.parseFloat(secondsString), "second", "s", secondsString);
4005
3249
  }
4006
3250
  if (result.length === 0) return sign + "0" + (options.verbose ? " milliseconds" : "ms");
4007
3251
  const separator = options.colonNotation ? ":" : " ";
@@ -4026,9 +3270,10 @@ const logResult = (result, verboseInfo) => {
4026
3270
  logDuration(result, verboseInfo);
4027
3271
  };
4028
3272
  const logDuration = (result, verboseInfo) => {
3273
+ const verboseMessage = `(done in ${prettyMilliseconds(result.durationMs)})`;
4029
3274
  verboseLog({
4030
3275
  type: "duration",
4031
- verboseMessage: `(done in ${prettyMilliseconds(result.durationMs)})`,
3276
+ verboseMessage,
4032
3277
  verboseInfo,
4033
3278
  result
4034
3279
  });
@@ -4096,10 +3341,10 @@ const isTransformOptions = (value) => isPlainObject(value) && (value.transform !
4096
3341
  const isUrl = (value) => Object.prototype.toString.call(value) === "[object URL]";
4097
3342
  const isRegularUrl = (value) => isUrl(value) && value.protocol !== "file:";
4098
3343
  const isFilePathObject = (value) => isPlainObject(value) && Object.keys(value).length > 0 && Object.keys(value).every((key) => FILE_PATH_KEYS.has(key)) && isFilePathString(value.file);
4099
- const FILE_PATH_KEYS = new Set(["file", "append"]);
3344
+ const FILE_PATH_KEYS = /* @__PURE__ */ new Set(["file", "append"]);
4100
3345
  const isFilePathString = (file) => typeof file === "string";
4101
3346
  const isUnknownStdioString = (type, value) => type === "native" && typeof value === "string" && !KNOWN_STDIO_STRINGS.has(value);
4102
- const KNOWN_STDIO_STRINGS = new Set([
3347
+ const KNOWN_STDIO_STRINGS = /* @__PURE__ */ new Set([
4103
3348
  "ipc",
4104
3349
  "ignore",
4105
3350
  "inherit",
@@ -4113,24 +3358,24 @@ const isTransformStream = (value) => isReadableStream(value?.readable) && isWrit
4113
3358
  const isAsyncIterableObject = (value) => isObject(value) && typeof value[Symbol.asyncIterator] === "function";
4114
3359
  const isIterableObject = (value) => isObject(value) && typeof value[Symbol.iterator] === "function";
4115
3360
  const isObject = (value) => typeof value === "object" && value !== null;
4116
- const TRANSFORM_TYPES = new Set([
3361
+ const TRANSFORM_TYPES = /* @__PURE__ */ new Set([
4117
3362
  "generator",
4118
3363
  "asyncGenerator",
4119
3364
  "duplex",
4120
3365
  "webTransform"
4121
3366
  ]);
4122
- const FILE_TYPES = new Set([
3367
+ const FILE_TYPES = /* @__PURE__ */ new Set([
4123
3368
  "fileUrl",
4124
3369
  "filePath",
4125
3370
  "fileNumber"
4126
3371
  ]);
4127
- const SPECIAL_DUPLICATE_TYPES_SYNC = new Set(["fileUrl", "filePath"]);
4128
- const SPECIAL_DUPLICATE_TYPES = new Set([
3372
+ const SPECIAL_DUPLICATE_TYPES_SYNC = /* @__PURE__ */ new Set(["fileUrl", "filePath"]);
3373
+ const SPECIAL_DUPLICATE_TYPES = /* @__PURE__ */ new Set([
4129
3374
  ...SPECIAL_DUPLICATE_TYPES_SYNC,
4130
3375
  "webStream",
4131
3376
  "nodeStream"
4132
3377
  ]);
4133
- const FORBID_DUPLICATE_TYPES = new Set(["webTransform", "duplex"]);
3378
+ const FORBID_DUPLICATE_TYPES = /* @__PURE__ */ new Set(["webTransform", "duplex"]);
4134
3379
  const TYPE_TO_MESSAGE = {
4135
3380
  generator: "a generator",
4136
3381
  asyncGenerator: "an async generator",
@@ -4463,7 +3708,8 @@ const validateDuplicateStreamSync = ({ otherStdioItems, type, value, optionName,
4463
3708
  const getDuplicateStreamInstance = ({ otherStdioItems, type, value, optionName, direction }) => {
4464
3709
  const duplicateStdioItems = otherStdioItems.filter((stdioItem) => hasSameValue(stdioItem, value));
4465
3710
  if (duplicateStdioItems.length === 0) return;
4466
- throwOnDuplicateStream(duplicateStdioItems.find((stdioItem) => stdioItem.direction !== direction), optionName, type);
3711
+ const differentStdioItem = duplicateStdioItems.find((stdioItem) => stdioItem.direction !== direction);
3712
+ throwOnDuplicateStream(differentStdioItem, optionName, type);
4467
3713
  return direction === "output" ? duplicateStdioItems[0].stream : void 0;
4468
3714
  };
4469
3715
  const hasSameValue = ({ type, value }, secondValue) => {
@@ -4472,7 +3718,8 @@ const hasSameValue = ({ type, value }, secondValue) => {
4472
3718
  return value === secondValue;
4473
3719
  };
4474
3720
  const validateDuplicateTransform = ({ otherStdioItems, type, value, optionName }) => {
4475
- throwOnDuplicateStream(otherStdioItems.find(({ value: { transform } }) => transform === value.transform), optionName, type);
3721
+ const duplicateStdioItem = otherStdioItems.find(({ value: { transform } }) => transform === value.transform);
3722
+ throwOnDuplicateStream(duplicateStdioItem, optionName, type);
4476
3723
  };
4477
3724
  const throwOnDuplicateStream = (stdioItem, optionName, type) => {
4478
3725
  if (stdioItem !== void 0) throw new TypeError(`The \`${stdioItem.optionName}\` and \`${optionName}\` options must not target ${TYPE_TO_MESSAGE[type]} that is the same.`);
@@ -4480,13 +3727,14 @@ const throwOnDuplicateStream = (stdioItem, optionName, type) => {
4480
3727
  //#endregion
4481
3728
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/stdio/handle.js
4482
3729
  const handleStdio = (addProperties, options, verboseInfo, isSync) => {
3730
+ const initialFileDescriptors = normalizeStdioOption(options, verboseInfo, isSync).map((stdioOption, fdNumber) => getFileDescriptor({
3731
+ stdioOption,
3732
+ fdNumber,
3733
+ options,
3734
+ isSync
3735
+ }));
4483
3736
  const fileDescriptors = getFinalFileDescriptors({
4484
- initialFileDescriptors: normalizeStdioOption(options, verboseInfo, isSync).map((stdioOption, fdNumber) => getFileDescriptor({
4485
- stdioOption,
4486
- fdNumber,
4487
- options,
4488
- isSync
4489
- })),
3737
+ initialFileDescriptors,
4490
3738
  addProperties,
4491
3739
  options,
4492
3740
  isSync
@@ -4503,13 +3751,14 @@ const getFileDescriptor = ({ stdioOption, fdNumber, options, isSync }) => {
4503
3751
  optionName
4504
3752
  });
4505
3753
  const direction = getStreamDirection(initialStdioItems, fdNumber, optionName);
4506
- const normalizedStdioItems = normalizeTransforms(initialStdioItems.map((stdioItem) => handleNativeStream({
3754
+ const stdioItems = initialStdioItems.map((stdioItem) => handleNativeStream({
4507
3755
  stdioItem,
4508
3756
  isStdioArray,
4509
3757
  fdNumber,
4510
3758
  direction,
4511
3759
  isSync
4512
- })), optionName, direction, options);
3760
+ }));
3761
+ const normalizedStdioItems = normalizeTransforms(stdioItems, optionName, direction, options);
4513
3762
  const objectMode = getFdObjectMode(normalizedStdioItems, direction);
4514
3763
  validateFileObjectMode(normalizedStdioItems, objectMode);
4515
3764
  return {
@@ -4519,7 +3768,8 @@ const getFileDescriptor = ({ stdioOption, fdNumber, options, isSync }) => {
4519
3768
  };
4520
3769
  };
4521
3770
  const initializeStdioItems = ({ stdioOption, fdNumber, options, optionName }) => {
4522
- const stdioItems = filterDuplicates([...(Array.isArray(stdioOption) ? stdioOption : [stdioOption]).map((value) => initializeStdioItem(value, optionName)), ...handleInputOptions(options, fdNumber)]);
3771
+ const initialStdioItems = [...(Array.isArray(stdioOption) ? stdioOption : [stdioOption]).map((value) => initializeStdioItem(value, optionName)), ...handleInputOptions(options, fdNumber)];
3772
+ const stdioItems = filterDuplicates(initialStdioItems);
4523
3773
  const isStdioArray = stdioItems.length > 1;
4524
3774
  validateStdioArray(stdioItems, isStdioArray, optionName);
4525
3775
  validateStreams(stdioItems);
@@ -4538,7 +3788,7 @@ const validateStdioArray = (stdioItems, isStdioArray, optionName) => {
4538
3788
  if (!isStdioArray) return;
4539
3789
  for (const { value, optionName } of stdioItems) if (INVALID_STDIO_ARRAY_OPTIONS.has(value)) throw new Error(`The \`${optionName}\` option must not include \`${value}\`.`);
4540
3790
  };
4541
- const INVALID_STDIO_ARRAY_OPTIONS = new Set(["ignore", "ipc"]);
3791
+ const INVALID_STDIO_ARRAY_OPTIONS = /* @__PURE__ */ new Set(["ignore", "ipc"]);
4542
3792
  const validateStreams = (stdioItems) => {
4543
3793
  for (const stdioItem of stdioItems) validateFileStdio(stdioItem);
4544
3794
  };
@@ -4867,7 +4117,10 @@ const generatorToStream = ({ value, value: { transform, final, writableObjectMod
4867
4117
  const runGeneratorsSync = (chunks, stdioItems, encoding, isInput) => {
4868
4118
  const generators = stdioItems.filter(({ type }) => type === "generator");
4869
4119
  const reversedGenerators = isInput ? generators.reverse() : generators;
4870
- for (const { value, optionName } of reversedGenerators) chunks = runTransformSync(addInternalGenerators(value, encoding, optionName), chunks);
4120
+ for (const { value, optionName } of reversedGenerators) {
4121
+ const generators = addInternalGenerators(value, encoding, optionName);
4122
+ chunks = runTransformSync(generators, chunks);
4123
+ }
4871
4124
  return chunks;
4872
4125
  };
4873
4126
  const addInternalGenerators = ({ transform, final, binary, writableObjectMode, readableObjectMode, preserveNewlines }, encoding, optionName) => {
@@ -4903,7 +4156,8 @@ const addInputOptionSync = (fileDescriptors, fdNumber, options) => {
4903
4156
  const [{ type, optionName }] = allStdioItems;
4904
4157
  throw new TypeError(`Only the \`stdin\` option, not \`${optionName}\`, can be ${TYPE_TO_MESSAGE[type]} with synchronous methods.`);
4905
4158
  }
4906
- options.input = joinToUint8Array(allStdioItems.map(({ contents }) => contents).map((contents) => applySingleInputGeneratorsSync(contents, stdioItems)));
4159
+ const transformedContents = allStdioItems.map(({ contents }) => contents).map((contents) => applySingleInputGeneratorsSync(contents, stdioItems));
4160
+ options.input = joinToUint8Array(transformedContents);
4907
4161
  };
4908
4162
  const applySingleInputGeneratorsSync = (contents, stdioItems) => {
4909
4163
  const newContents = runGeneratorsSync(contents, stdioItems, "utf8", true);
@@ -4918,7 +4172,7 @@ const validateSerializable = (newContents) => {
4918
4172
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/verbose/output.js
4919
4173
  const shouldLogOutput = ({ stdioItems, encoding, verboseInfo, fdNumber }) => fdNumber !== "all" && isFullVerbose(verboseInfo, fdNumber) && !BINARY_ENCODINGS.has(encoding) && fdUsesVerbose(fdNumber) && (stdioItems.some(({ type, value }) => type === "native" && PIPED_STDIO_VALUES.has(value)) || stdioItems.every(({ type }) => TRANSFORM_TYPES.has(type)));
4920
4174
  const fdUsesVerbose = (fdNumber) => fdNumber === 1 || fdNumber === 2;
4921
- const PIPED_STDIO_VALUES = new Set(["pipe", "overlapped"]);
4175
+ const PIPED_STDIO_VALUES = /* @__PURE__ */ new Set(["pipe", "overlapped"]);
4922
4176
  const logLines = async (linesIterable, stream, fdNumber, verboseInfo) => {
4923
4177
  for await (const line of linesIterable) if (!isPipingStream(stream)) logLine(line, fdNumber, verboseInfo);
4924
4178
  };
@@ -4927,9 +4181,10 @@ const logLinesSync = (linesArray, fdNumber, verboseInfo) => {
4927
4181
  };
4928
4182
  const isPipingStream = (stream) => stream._readableState.pipes.length > 0;
4929
4183
  const logLine = (line, fdNumber, verboseInfo) => {
4184
+ const verboseMessage = serializeVerboseMessage(line);
4930
4185
  verboseLog({
4931
4186
  type: "output",
4932
- verboseMessage: serializeVerboseMessage(line),
4187
+ verboseMessage,
4933
4188
  fdNumber,
4934
4189
  verboseInfo
4935
4190
  });
@@ -4955,10 +4210,12 @@ const transformOutputSync = ({ fileDescriptors, syncResult: { output }, options,
4955
4210
  };
4956
4211
  const transformOutputResultSync = ({ result, fileDescriptors, fdNumber, state, outputFiles, isMaxBuffer, verboseInfo }, { buffer, encoding, lines, stripFinalNewline, maxBuffer }) => {
4957
4212
  if (result === null) return;
4958
- const uint8ArrayResult = bufferToUint8Array(truncateMaxBufferSync(result, isMaxBuffer, maxBuffer));
4213
+ const truncatedResult = truncateMaxBufferSync(result, isMaxBuffer, maxBuffer);
4214
+ const uint8ArrayResult = bufferToUint8Array(truncatedResult);
4959
4215
  const { stdioItems, objectMode } = fileDescriptors[fdNumber];
4216
+ const chunks = runOutputGeneratorsSync([uint8ArrayResult], stdioItems, encoding, state);
4960
4217
  const { serializedResult, finalResult = serializedResult } = serializeChunks({
4961
- chunks: runOutputGeneratorsSync([uint8ArrayResult], stdioItems, encoding, state),
4218
+ chunks,
4962
4219
  objectMode,
4963
4220
  encoding,
4964
4221
  lines,
@@ -5082,7 +4339,7 @@ const getResultError = (error, exitCode, signal) => {
5082
4339
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/methods/main-sync.js
5083
4340
  const execaCoreSync = (rawFile, rawArguments, rawOptions) => {
5084
4341
  const { file, commandArguments, command, escapedCommand, startTime, verboseInfo, options, fileDescriptors } = handleSyncArguments(rawFile, rawArguments, rawOptions);
5085
- return handleResult(spawnSubprocessSync({
4342
+ const result = spawnSubprocessSync({
5086
4343
  file,
5087
4344
  commandArguments,
5088
4345
  options,
@@ -5091,11 +4348,13 @@ const execaCoreSync = (rawFile, rawArguments, rawOptions) => {
5091
4348
  verboseInfo,
5092
4349
  fileDescriptors,
5093
4350
  startTime
5094
- }), verboseInfo, options);
4351
+ });
4352
+ return handleResult(result, verboseInfo, options);
5095
4353
  };
5096
4354
  const handleSyncArguments = (rawFile, rawArguments, rawOptions) => {
5097
4355
  const { command, escapedCommand, startTime, verboseInfo } = handleCommand(rawFile, rawArguments, rawOptions);
5098
- const { file, commandArguments, options } = normalizeOptions(rawFile, rawArguments, normalizeSyncOptions(rawOptions));
4356
+ const syncOptions = normalizeSyncOptions(rawOptions);
4357
+ const { file, commandArguments, options } = normalizeOptions(rawFile, rawArguments, syncOptions);
5099
4358
  validateSyncOptions(options);
5100
4359
  return {
5101
4360
  file,
@@ -5140,14 +4399,16 @@ const spawnSubprocessSync = ({ file, commandArguments, options, command, escaped
5140
4399
  isMaxBuffer,
5141
4400
  verboseInfo
5142
4401
  });
4402
+ const stdio = output.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options, fdNumber));
4403
+ const all = stripNewline(getAllSync(output, options), options, "all");
5143
4404
  return getSyncResult({
5144
4405
  error,
5145
4406
  exitCode,
5146
4407
  signal,
5147
4408
  timedOut,
5148
4409
  isMaxBuffer,
5149
- stdio: output.map((stdioOutput, fdNumber) => stripNewline(stdioOutput, options, fdNumber)),
5150
- all: stripNewline(getAllSync(output, options), options, "all"),
4410
+ stdio,
4411
+ all,
5151
4412
  options,
5152
4413
  command,
5153
4414
  escapedCommand,
@@ -5157,7 +4418,8 @@ const spawnSubprocessSync = ({ file, commandArguments, options, command, escaped
5157
4418
  const runSubprocessSync = ({ file, commandArguments, options, command, escapedCommand, fileDescriptors, startTime }) => {
5158
4419
  try {
5159
4420
  addInputOptionsSync(fileDescriptors, options);
5160
- return (0, node_child_process.spawnSync)(file, commandArguments, normalizeSpawnSyncOptions(options));
4421
+ const normalizedOptions = normalizeSpawnSyncOptions(options);
4422
+ return (0, node_child_process.spawnSync)(file, commandArguments, normalizedOptions);
5161
4423
  } catch (error) {
5162
4424
  return makeEarlyError({
5163
4425
  error,
@@ -5371,17 +4633,18 @@ const handleEarlyError = ({ error, command, escapedCommand, fileDescriptors, opt
5371
4633
  writable,
5372
4634
  duplex
5373
4635
  });
4636
+ const earlyError = makeEarlyError({
4637
+ error,
4638
+ command,
4639
+ escapedCommand,
4640
+ fileDescriptors,
4641
+ options,
4642
+ startTime,
4643
+ isSync: false
4644
+ });
5374
4645
  return {
5375
4646
  subprocess,
5376
- promise: handleDummyPromise(makeEarlyError({
5377
- error,
5378
- command,
5379
- escapedCommand,
5380
- fileDescriptors,
5381
- options,
5382
- startTime,
5383
- isSync: false
5384
- }), verboseInfo, options)
4647
+ promise: handleDummyPromise(earlyError, verboseInfo, options)
5385
4648
  };
5386
4649
  };
5387
4650
  const createDummyStreams = (subprocess, fileDescriptors) => {
@@ -5565,8 +4828,10 @@ const endWhenStreamsDone = async ({ passThroughStream, stream, streams, ended, a
5565
4828
  controller.abort();
5566
4829
  updateMaxListeners(passThroughStream, -PASSTHROUGH_LISTENERS_PER_STREAM);
5567
4830
  }
5568
- if (streams.size > 0 && streams.size === ended.size + aborted.size) if (ended.size === 0 && aborted.size > 0) abortStream(passThroughStream);
5569
- else endStream(passThroughStream);
4831
+ if (streams.size > 0 && streams.size === ended.size + aborted.size) {
4832
+ if (ended.size === 0 && aborted.size > 0) abortStream(passThroughStream);
4833
+ else endStream(passThroughStream);
4834
+ }
5570
4835
  };
5571
4836
  const afterMergedStreamFinished = async (onFinished, stream, { signal }) => {
5572
4837
  try {
@@ -5672,7 +4937,10 @@ const pipeOutputAsync = (subprocess, fileDescriptors, controller) => {
5672
4937
  controller
5673
4938
  });
5674
4939
  }
5675
- for (const [outputStream, inputStreams] of pipeGroups.entries()) pipeStreams(inputStreams.length === 1 ? inputStreams[0] : mergeStreams(inputStreams), outputStream);
4940
+ for (const [outputStream, inputStreams] of pipeGroups.entries()) {
4941
+ const inputStream = inputStreams.length === 1 ? inputStreams[0] : mergeStreams(inputStreams);
4942
+ pipeStreams(inputStream, outputStream);
4943
+ }
5676
4944
  };
5677
4945
  const pipeTransform = (subprocess, stream, direction, fdNumber) => {
5678
4946
  if (direction === "output") pipeStreams(subprocess.stdio[fdNumber], stream);
@@ -6161,12 +5429,13 @@ const stopReadingOnStreamEnd = async (onStreamEnd, controller, stream) => {
6161
5429
  }
6162
5430
  };
6163
5431
  const iterateOnStream = ({ stream, controller, binary, shouldEncode, encoding, shouldSplit, preserveNewlines }) => {
5432
+ const onStdoutChunk = (0, node_events.on)(stream, "data", {
5433
+ signal: controller.signal,
5434
+ highWaterMark: HIGH_WATER_MARK,
5435
+ highWatermark: HIGH_WATER_MARK
5436
+ });
6164
5437
  return iterateOnData({
6165
- onStdoutChunk: (0, node_events.on)(stream, "data", {
6166
- signal: controller.signal,
6167
- highWaterMark: HIGH_WATER_MARK,
6168
- highWatermark: HIGH_WATER_MARK
6169
- }),
5438
+ onStdoutChunk,
6170
5439
  controller,
6171
5440
  binary,
6172
5441
  shouldEncode,
@@ -6210,12 +5479,13 @@ const getStreamOutput = async ({ stream, onStreamEnd, fdNumber, encoding, buffer
6210
5479
  await Promise.all([resumeStream(stream), logPromise]);
6211
5480
  return;
6212
5481
  }
5482
+ const stripFinalNewlineValue = getStripFinalNewline(stripFinalNewline, fdNumber);
6213
5483
  const iterable = iterateForResult({
6214
5484
  stream,
6215
5485
  onStreamEnd,
6216
5486
  lines,
6217
5487
  encoding,
6218
- stripFinalNewline: getStripFinalNewline(stripFinalNewline, fdNumber),
5488
+ stripFinalNewline: stripFinalNewlineValue,
6219
5489
  allMixed
6220
5490
  });
6221
5491
  const [output] = await Promise.all([getStreamContents({
@@ -6235,14 +5505,15 @@ const logOutputAsync = async ({ stream, onStreamEnd, fdNumber, encoding, allMixe
6235
5505
  verboseInfo,
6236
5506
  fdNumber
6237
5507
  })) return;
6238
- await logLines(iterateForResult({
5508
+ const linesIterable = iterateForResult({
6239
5509
  stream,
6240
5510
  onStreamEnd,
6241
5511
  lines: true,
6242
5512
  encoding,
6243
5513
  stripFinalNewline: true,
6244
5514
  allMixed
6245
- }), stream, fdNumber, verboseInfo);
5515
+ });
5516
+ await logLines(linesIterable, stream, fdNumber, verboseInfo);
6246
5517
  };
6247
5518
  const resumeStream = async (stream) => {
6248
5519
  await (0, node_timers_promises.setImmediate)();
@@ -6388,9 +5659,10 @@ const getAllMixed = ({ all, stdout, stderr }) => all && stdout && stderr && stdo
6388
5659
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/verbose/ipc.js
6389
5660
  const shouldLogIpc = (verboseInfo) => isFullVerbose(verboseInfo, "ipc");
6390
5661
  const logIpcOutput = (message, verboseInfo) => {
5662
+ const verboseMessage = serializeVerboseMessage(message);
6391
5663
  verboseLog({
6392
5664
  type: "ipc",
6393
- verboseMessage: serializeVerboseMessage(message),
5665
+ verboseMessage,
6394
5666
  fdNumber: "ipc",
6395
5667
  verboseInfo
6396
5668
  });
@@ -6786,14 +6058,15 @@ const onDuplexDestroy = async ({ subprocessStdout, subprocessStdin, subprocess,
6786
6058
  const createIterable = (subprocess, encoding, { from, binary: binaryOption = false, preserveNewlines = false } = {}) => {
6787
6059
  const binary = binaryOption || BINARY_ENCODINGS.has(encoding);
6788
6060
  const subprocessStdout = getFromStream(subprocess, from);
6789
- return iterateOnStdoutData(iterateOnSubprocessStream({
6061
+ const onStdoutData = iterateOnSubprocessStream({
6790
6062
  subprocessStdout,
6791
6063
  subprocess,
6792
6064
  binary,
6793
6065
  shouldEncode: true,
6794
6066
  encoding,
6795
6067
  preserveNewlines
6796
- }), subprocessStdout, subprocess);
6068
+ });
6069
+ return iterateOnStdoutData(onStdoutData, subprocessStdout, subprocess);
6797
6070
  };
6798
6071
  const iterateOnStdoutData = async function* (onStdoutData, subprocessStdout, subprocess) {
6799
6072
  try {
@@ -6953,19 +6226,22 @@ const handlePromise = async ({ subprocess, options, startTime, verboseInfo, file
6953
6226
  });
6954
6227
  controller.abort();
6955
6228
  onInternalError.resolve();
6956
- return handleResult(getAsyncResult({
6229
+ const stdio = stdioResults.map((stdioResult, fdNumber) => stripNewline(stdioResult, options, fdNumber));
6230
+ const all = stripNewline(allResult, options, "all");
6231
+ const result = getAsyncResult({
6957
6232
  errorInfo,
6958
6233
  exitCode,
6959
6234
  signal,
6960
- stdio: stdioResults.map((stdioResult, fdNumber) => stripNewline(stdioResult, options, fdNumber)),
6961
- all: stripNewline(allResult, options, "all"),
6235
+ stdio,
6236
+ all,
6962
6237
  ipcOutput,
6963
6238
  context,
6964
6239
  options,
6965
6240
  command,
6966
6241
  escapedCommand,
6967
6242
  startTime
6968
- }), verboseInfo, options);
6243
+ });
6244
+ return handleResult(result, verboseInfo, options);
6969
6245
  };
6970
6246
  const getAsyncResult = ({ errorInfo, exitCode, signal, stdio, all, ipcOutput, context, options, command, escapedCommand, startTime }) => "error" in errorInfo ? makeError({
6971
6247
  error: errorInfo.error,
@@ -7009,7 +6285,7 @@ const mergeOption = (optionName, boundOptionValue, optionValue) => {
7009
6285
  };
7010
6286
  return optionValue;
7011
6287
  };
7012
- const DEEP_OPTIONS = new Set(["env", ...FD_SPECIFIC_OPTIONS]);
6288
+ const DEEP_OPTIONS = /* @__PURE__ */ new Set(["env", ...FD_SPECIFIC_OPTIONS]);
7013
6289
  //#endregion
7014
6290
  //#region ../../node_modules/.pnpm/execa@9.5.2/node_modules/execa/lib/methods/create.js
7015
6291
  const createExeca = (mapArguments, boundOptions, deepOptions, setBoundExeca) => {
@@ -7036,7 +6312,8 @@ const callBoundExeca = ({ mapArguments, deepOptions = {}, boundOptions = {}, set
7036
6312
  return isSync ? execaCoreSync(file, commandArguments, options) : execaCoreAsync(file, commandArguments, options, createNested);
7037
6313
  };
7038
6314
  const parseArguments = ({ mapArguments, firstArgument, nextArguments, deepOptions, boundOptions }) => {
7039
- const [initialFile, initialArguments, initialOptions] = normalizeParameters(...isTemplateString(firstArgument) ? parseTemplates(firstArgument, nextArguments) : [firstArgument, ...nextArguments]);
6315
+ const callArguments = isTemplateString(firstArgument) ? parseTemplates(firstArgument, nextArguments) : [firstArgument, ...nextArguments];
6316
+ const [initialFile, initialArguments, initialOptions] = normalizeParameters(...callArguments);
7040
6317
  const mergedOptions = mergeOptions(mergeOptions(deepOptions, boundOptions), initialOptions);
7041
6318
  const { file = initialFile, commandArguments = initialArguments, options = mergedOptions, isSync = false } = mapArguments({
7042
6319
  file: initialFile,
@@ -7150,6 +6427,8 @@ const isCloudflareAuthenticationError = (error) => {
7150
6427
  ].some((pattern) => pattern.test(getErrorOutput(error)));
7151
6428
  };
7152
6429
  var CloudflareAuthenticationError = class extends _hot_updater_cli_tools.InitError {
6430
+ source;
6431
+ accountId;
7153
6432
  name = "CloudflareAuthenticationError";
7154
6433
  constructor(source, accountId, options) {
7155
6434
  super([
@@ -7164,6 +6443,7 @@ var CloudflareAuthenticationError = class extends _hot_updater_cli_tools.InitErr
7164
6443
  }
7165
6444
  };
7166
6445
  var CloudflarePermissionError = class extends _hot_updater_cli_tools.InitError {
6446
+ source;
7167
6447
  name = "CloudflarePermissionError";
7168
6448
  constructor(source, { accountId, check, requiredPermission }, options) {
7169
6449
  super([
@@ -9302,12 +8582,14 @@ var require_parser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
9302
8582
  s2 = peg$FAILED;
9303
8583
  if (peg$silentFails === 0) peg$fail(peg$c39);
9304
8584
  }
9305
- if (s2 === peg$FAILED) if (input.charCodeAt(peg$currPos) === 69) {
9306
- s2 = peg$c40;
9307
- peg$currPos++;
9308
- } else {
9309
- s2 = peg$FAILED;
9310
- if (peg$silentFails === 0) peg$fail(peg$c41);
8585
+ if (s2 === peg$FAILED) {
8586
+ if (input.charCodeAt(peg$currPos) === 69) {
8587
+ s2 = peg$c40;
8588
+ peg$currPos++;
8589
+ } else {
8590
+ s2 = peg$FAILED;
8591
+ if (peg$silentFails === 0) peg$fail(peg$c41);
8592
+ }
9311
8593
  }
9312
8594
  if (s2 !== peg$FAILED) {
9313
8595
  s3 = peg$parseinteger_text();
@@ -10476,12 +9758,14 @@ var require_parser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
10476
9758
  s11 = peg$FAILED;
10477
9759
  if (peg$silentFails === 0) peg$fail(peg$c48);
10478
9760
  }
10479
- if (s11 === peg$FAILED) if (input.charCodeAt(peg$currPos) === 43) {
10480
- s11 = peg$c44;
10481
- peg$currPos++;
10482
- } else {
10483
- s11 = peg$FAILED;
10484
- if (peg$silentFails === 0) peg$fail(peg$c45);
9761
+ if (s11 === peg$FAILED) {
9762
+ if (input.charCodeAt(peg$currPos) === 43) {
9763
+ s11 = peg$c44;
9764
+ peg$currPos++;
9765
+ } else {
9766
+ s11 = peg$FAILED;
9767
+ if (peg$silentFails === 0) peg$fail(peg$c45);
9768
+ }
10485
9769
  }
10486
9770
  if (s11 !== peg$FAILED) {
10487
9771
  s12 = peg$parseDIGIT_OR_UNDER();
@@ -11238,9 +10522,7 @@ var require_compiler = /* @__PURE__ */ __commonJSMin(((exports, module) => {
11238
10522
  case "ObjectPath":
11239
10523
  setPath(node);
11240
10524
  break;
11241
- case "ArrayPath":
11242
- addTableArray(node);
11243
- break;
10525
+ case "ArrayPath": addTableArray(node);
11244
10526
  }
11245
10527
  }
11246
10528
  return data;
@@ -11320,9 +10602,10 @@ var require_compiler = /* @__PURE__ */ __commonJSMin(((exports, module) => {
11320
10602
  var key = keys[i];
11321
10603
  traversed.push(key);
11322
10604
  traversedPath = traversed.join(".");
11323
- if (typeof ctx[key] === "undefined") if (i === keys.length - 1) ctx[key] = value;
11324
- else ctx[key] = Object.create(null);
11325
- else if (i !== keys.length - 1 && valueAssignments.indexOf(traversedPath) > -1) genError("Cannot redefine existing key '" + traversedPath + "'.", line, column);
10605
+ if (typeof ctx[key] === "undefined") {
10606
+ if (i === keys.length - 1) ctx[key] = value;
10607
+ else ctx[key] = Object.create(null);
10608
+ } else if (i !== keys.length - 1 && valueAssignments.indexOf(traversedPath) > -1) genError("Cannot redefine existing key '" + traversedPath + "'.", line, column);
11326
10609
  ctx = ctx[key];
11327
10610
  if (ctx instanceof Array && ctx.length && i < keys.length - 1) ctx = ctx[ctx.length - 1];
11328
10611
  }
@@ -12115,7 +11398,7 @@ const inputCloudflareInitSecrets = async ({ accountId, bucketName, apiToken, acc
12115
11398
  }, { onCancel: () => process.exit(1) });
12116
11399
  };
12117
11400
  //#endregion
12118
- //#region iac/index.ts
11401
+ //#region iac/configTemplate.ts
12119
11402
  const getConfigScaffold = (build) => {
12120
11403
  return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setStorage({
12121
11404
  imports: [{
@@ -12142,6 +11425,8 @@ const getConfigScaffold = (build) => {
12142
11425
  })`
12143
11426
  }));
12144
11427
  };
11428
+ //#endregion
11429
+ //#region iac/index.ts
12145
11430
  const SOURCE_TEMPLATE = `// add this to your App.tsx
12146
11431
  import { HotUpdater } from "@hot-updater/react-native";
12147
11432
 
@@ -12162,7 +11447,8 @@ export default App;`;
12162
11447
  const deployWorker = async (apiToken, accountId, { credentialSource, d1DatabaseId, d1DatabaseName, nonInteractive, r2BucketName, workerName }) => {
12163
11448
  const cwd = (0, _hot_updater_cli_tools.getCwd)();
12164
11449
  const cloudflarePackagePath = require.resolve("@hot-updater/cloudflare/package.json", { paths: [cwd] });
12165
- const { tmpDir, removeTmpDir } = await (0, _hot_updater_cli_tools.copyDirToTmp)(path.default.dirname(cloudflarePackagePath));
11450
+ const cloudflarePackageRoot = path.default.dirname(cloudflarePackagePath);
11451
+ const { tmpDir, removeTmpDir } = await (0, _hot_updater_cli_tools.copyDirToTmp)(cloudflarePackageRoot);
12166
11452
  const workerRoot = path.default.join(tmpDir, "worker");
12167
11453
  try {
12168
11454
  const wranglerConfig = JSON.parse(await fs_promises.default.readFile(path.default.join(workerRoot, "wrangler.json"), "utf-8"));
@@ -12432,13 +11718,16 @@ const runInit = async ({ build, envFile }) => {
12432
11718
  for await (const resultPage of page.iterPages()) for (const result of resultPage.result) rows.push(...result.results ?? []);
12433
11719
  return rows;
12434
11720
  };
12435
- if (!createD1Database) assertCloudflareInfrastructureCanInitialize((await queryD1(`
11721
+ if (!createD1Database) {
11722
+ const tables = await queryD1(`
12436
11723
  SELECT name
12437
11724
  FROM sqlite_schema
12438
11725
  WHERE type = 'table'
12439
11726
  AND name IN ('bundles', 'release_catalogs')
12440
11727
  ORDER BY name
12441
- `)).flatMap(({ name }) => typeof name === "string" ? [name] : []), d1DatabaseName);
11728
+ `);
11729
+ assertCloudflareInfrastructureCanInitialize(tables.flatMap(({ name }) => typeof name === "string" ? [name] : []), d1DatabaseName);
11730
+ }
12442
11731
  const workerScripts = await runCloudflareApiRequest({
12443
11732
  request: () => cf.workers.scripts.list({ account_id: accountId }),
12444
11733
  source: infrastructureCredentialSource
@@ -12465,13 +11754,14 @@ const runInit = async ({ build, envFile }) => {
12465
11754
  secretAccessKey,
12466
11755
  workerName
12467
11756
  };
11757
+ const persistCredentialInputs = await (0, _hot_updater_cli_tools.confirmInitInputPersistence)({
11758
+ existingEnv: managedEnv,
11759
+ inputs: resolvedInputs,
11760
+ nonInteractive,
11761
+ provider: initProvider
11762
+ });
12468
11763
  await (0, _hot_updater_cli_tools.makeEnv)({ ...(0, _hot_updater_cli_tools.getInitProviderEnvVars)({
12469
- includeConsentInputs: await (0, _hot_updater_cli_tools.confirmInitInputPersistence)({
12470
- existingEnv: managedEnv,
12471
- inputs: resolvedInputs,
12472
- nonInteractive,
12473
- provider: initProvider
12474
- }),
11764
+ includeConsentInputs: persistCredentialInputs,
12475
11765
  inputs: resolvedInputs,
12476
11766
  provider: initProvider
12477
11767
  }) });
@@ -12532,27 +11822,27 @@ const runInit = async ({ build, envFile }) => {
12532
11822
  r2BucketName: selectedBucketName,
12533
11823
  workerName
12534
11824
  });
12535
- const databasePlugin = d1Database({
11825
+ const database = d1Database({
12536
11826
  accountId,
12537
11827
  cloudflareApiToken: apiToken,
12538
11828
  databaseId: selectedD1DatabaseId
12539
11829
  });
12540
11830
  let apiKey;
12541
11831
  try {
12542
- apiKey = (await (0, _hot_updater_server.provisionApiKey)({
12543
- apiKeys: databasePlugin.models.apiKeys,
11832
+ apiKey = (await (0, _hot_updater_server_db.createDatabasePluginApis)(database, plugins).apiKeys.provision({
12544
11833
  existingApiKey: initInputEnv.HOT_UPDATER_API_KEY,
12545
11834
  name: "Cloudflare init"
12546
11835
  })).apiKey;
12547
11836
  await (0, _hot_updater_cli_tools.makeEnv)({ HOT_UPDATER_API_KEY: apiKey });
12548
11837
  } finally {
12549
- await databasePlugin.dispose?.();
11838
+ await database.dispose?.();
12550
11839
  }
12551
11840
  const configWriteResult = await (0, _hot_updater_cli_tools.writeHotUpdaterConfig)(getConfigScaffold(build));
12552
11841
  _hot_updater_cli_tools.p.log.success("Generated '.env.hotupdater' file with Cloudflare settings.");
12553
11842
  if (configWriteResult.status === "created") _hot_updater_cli_tools.p.log.success("Generated 'hot-updater.config.ts' file with Cloudflare settings.");
12554
11843
  else if (configWriteResult.status === "merged") _hot_updater_cli_tools.p.log.success("Updated 'hot-updater.config.ts' file with Cloudflare settings.");
12555
11844
  else _hot_updater_cli_tools.p.log.warn(`Kept existing 'hot-updater.config.ts' unchanged: ${configWriteResult.reason}`);
11845
+ await (0, _hot_updater_cli_tools.generateHotUpdaterPlugins)("@hot-updater/cloudflare");
12556
11846
  if (subdomains.subdomain) _hot_updater_cli_tools.p.note((0, _hot_updater_cli_tools.transformTemplate)(SOURCE_TEMPLATE, {
12557
11847
  apiKey: JSON.stringify(apiKey),
12558
11848
  source: `https://${workerName}.${subdomains.subdomain}.workers.dev`