naro-cli 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,11 +4,11 @@ import {
4
4
  } from "./chunk-K3NQKI34.js";
5
5
 
6
6
  // src/deploy.ts
7
- import { existsSync as existsSync7 } from "fs";
7
+ import { existsSync as existsSync10 } from "fs";
8
8
  import { mkdtemp as mkdtemp2, readFile as readFile15, rm as rm5 } from "fs/promises";
9
9
  import { tmpdir as tmpdir2 } from "os";
10
- import { basename as basename4, dirname as dirname6, join as join26, resolve as resolve11 } from "path";
11
- import { fileURLToPath } from "url";
10
+ import { basename as basename5, dirname as dirname10, join as join32, resolve as resolve14 } from "path";
11
+ import { fileURLToPath as fileURLToPath4 } from "url";
12
12
 
13
13
  // ../../packages/build/src/artifact-upload.ts
14
14
  function artifactUploadEntries(artifact) {
@@ -41,7 +41,7 @@ function parseArtifactPutUrls(payload) {
41
41
  }
42
42
  async function eachWithinBudget(items, limit, budget, weigh, work) {
43
43
  if (items.length === 0) return;
44
- await new Promise((resolve12, reject) => {
44
+ await new Promise((resolve15, reject) => {
45
45
  let next = 0;
46
46
  let running = 0;
47
47
  let weight = 0;
@@ -58,7 +58,7 @@ async function eachWithinBudget(items, limit, budget, weigh, work) {
58
58
  running -= 1;
59
59
  weight -= itemWeight;
60
60
  finished += 1;
61
- if (finished === items.length) resolve12();
61
+ if (finished === items.length) resolve15();
62
62
  else pump();
63
63
  }, reject);
64
64
  }
@@ -98,11 +98,11 @@ async function uploadArtifactFiles(artifact, ports, limits = {}) {
98
98
  await ports.putProxied(entry);
99
99
  }
100
100
  }
101
- const bytes = entries.reduce(
101
+ const bytes2 = entries.reduce(
102
102
  (total, entry) => total + entry.file.data.byteLength,
103
103
  0
104
104
  );
105
- return { proxied, total: entries.length, bytes };
105
+ return { proxied, total: entries.length, bytes: bytes2 };
106
106
  }
107
107
  function artifactUploadSummary(report, elapsedMs) {
108
108
  const kilobytes = Math.ceil(report.bytes / 1e3);
@@ -450,14 +450,14 @@ function bare(match, command, rest, after, slug, switchContext) {
450
450
  return match;
451
451
  }
452
452
  }
453
- function environmentGuidance(text2, slug) {
454
- if (slug === null || !text2.includes("naro ")) return text2;
455
- const switchContext = SWITCH_CONTEXT.test(text2);
453
+ function environmentGuidance(text3, slug) {
454
+ if (slug === null || !text3.includes("naro ")) return text3;
455
+ const switchContext = SWITCH_CONTEXT.test(text3);
456
456
  const spans = [];
457
- const marked = text2.replaceAll(
457
+ const marked = text3.replaceAll(
458
458
  QUOTED,
459
459
  (match, span, offset) => {
460
- const noted = text2.startsWith(
460
+ const noted = text3.startsWith(
461
461
  ` (${PRODUCTION_SWITCH_NOTE})`,
462
462
  offset + match.length
463
463
  );
@@ -621,7 +621,11 @@ var DeploymentError = class extends Error {
621
621
  };
622
622
 
623
623
  // ../../packages/core/src/functions.ts
624
+ var FUNCTION_NAME_RE = /^[a-z][a-z0-9_-]{0,63}$/;
624
625
  var FUNCTION_WORKER_NAME_PREFIX = "naro-fn-";
626
+ function isFunctionName(name) {
627
+ return FUNCTION_NAME_RE.test(name);
628
+ }
625
629
 
626
630
  // ../../packages/core/src/git-remote.ts
627
631
  var SCP_LIKE = /^[^@\s/]+@([^:\s/]+):(.+)$/;
@@ -1934,16 +1938,16 @@ function cleanEnum(obj) {
1934
1938
  }
1935
1939
  function base64ToUint8Array(base643) {
1936
1940
  const binaryString = atob(base643);
1937
- const bytes = new Uint8Array(binaryString.length);
1941
+ const bytes2 = new Uint8Array(binaryString.length);
1938
1942
  for (let i = 0; i < binaryString.length; i++) {
1939
- bytes[i] = binaryString.charCodeAt(i);
1943
+ bytes2[i] = binaryString.charCodeAt(i);
1940
1944
  }
1941
- return bytes;
1945
+ return bytes2;
1942
1946
  }
1943
- function uint8ArrayToBase64(bytes) {
1947
+ function uint8ArrayToBase64(bytes2) {
1944
1948
  let binaryString = "";
1945
- for (let i = 0; i < bytes.length; i++) {
1946
- binaryString += String.fromCharCode(bytes[i]);
1949
+ for (let i = 0; i < bytes2.length; i++) {
1950
+ binaryString += String.fromCharCode(bytes2[i]);
1947
1951
  }
1948
1952
  return btoa(binaryString);
1949
1953
  }
@@ -1952,22 +1956,22 @@ function base64urlToUint8Array(base64url3) {
1952
1956
  const padding = "=".repeat((4 - base643.length % 4) % 4);
1953
1957
  return base64ToUint8Array(base643 + padding);
1954
1958
  }
1955
- function uint8ArrayToBase64url(bytes) {
1956
- return uint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1959
+ function uint8ArrayToBase64url(bytes2) {
1960
+ return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
1957
1961
  }
1958
1962
  function hexToUint8Array(hex3) {
1959
1963
  const cleanHex = hex3.replace(/^0x/, "");
1960
1964
  if (cleanHex.length % 2 !== 0) {
1961
1965
  throw new Error("Invalid hex string length");
1962
1966
  }
1963
- const bytes = new Uint8Array(cleanHex.length / 2);
1967
+ const bytes2 = new Uint8Array(cleanHex.length / 2);
1964
1968
  for (let i = 0; i < cleanHex.length; i += 2) {
1965
- bytes[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1969
+ bytes2[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
1966
1970
  }
1967
- return bytes;
1971
+ return bytes2;
1968
1972
  }
1969
- function uint8ArrayToHex(bytes) {
1970
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1973
+ function uint8ArrayToHex(bytes2) {
1974
+ return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
1971
1975
  }
1972
1976
  var Class = class {
1973
1977
  constructor(..._args) {
@@ -2273,10 +2277,10 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
2273
2277
  var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
2274
2278
  var extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
2275
2279
  var guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
2276
- var uuid = (version2) => {
2277
- if (!version2)
2280
+ var uuid = (version3) => {
2281
+ if (!version3)
2278
2282
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
2279
- return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version2}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
2283
+ return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version3}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
2280
2284
  };
2281
2285
  var uuid4 = /* @__PURE__ */ uuid(4);
2282
2286
  var uuid6 = /* @__PURE__ */ uuid(6);
@@ -3758,7 +3762,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3758
3762
  const _normalized = cached(() => normalizeDef(def));
3759
3763
  const generateFastpass = (shape) => {
3760
3764
  const doc = new Doc(["shape", "payload", "ctx"]);
3761
- const normalized = _normalized.value;
3765
+ const normalized2 = _normalized.value;
3762
3766
  const parseStr = (key) => {
3763
3767
  const k = esc(key);
3764
3768
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
@@ -3766,11 +3770,11 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3766
3770
  doc.write(`const input = payload.value;`);
3767
3771
  const ids = /* @__PURE__ */ Object.create(null);
3768
3772
  let counter = 0;
3769
- for (const key of normalized.keys) {
3773
+ for (const key of normalized2.keys) {
3770
3774
  ids[key] = `key_${counter++}`;
3771
3775
  }
3772
3776
  doc.write(`const newResult = {};`);
3773
- for (const key of normalized.keys) {
3777
+ for (const key of normalized2.keys) {
3774
3778
  const id = ids[key];
3775
3779
  const k = esc(key);
3776
3780
  const schema = shape[key];
@@ -8317,8 +8321,8 @@ function ko_default() {
8317
8321
  }
8318
8322
 
8319
8323
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/lt.js
8320
- var capitalizeFirstCharacter = (text2) => {
8321
- return text2.charAt(0).toUpperCase() + text2.slice(1);
8324
+ var capitalizeFirstCharacter = (text3) => {
8325
+ return text3.charAt(0).toUpperCase() + text3.slice(1);
8322
8326
  };
8323
8327
  function getUnitTypeFromNumber(number4) {
8324
8328
  const abs = Math.abs(number4);
@@ -15146,23 +15150,23 @@ function fromJSONSchema(schema, params) {
15146
15150
  if (typeof schema === "boolean") {
15147
15151
  return schema ? z.any() : z.never();
15148
15152
  }
15149
- let normalized;
15153
+ let normalized2;
15150
15154
  try {
15151
- normalized = JSON.parse(JSON.stringify(schema));
15155
+ normalized2 = JSON.parse(JSON.stringify(schema));
15152
15156
  } catch {
15153
15157
  throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
15154
15158
  }
15155
- const version2 = detectVersion(normalized, params?.defaultTarget);
15156
- const defs = normalized.$defs || normalized.definitions || {};
15159
+ const version3 = detectVersion(normalized2, params?.defaultTarget);
15160
+ const defs = normalized2.$defs || normalized2.definitions || {};
15157
15161
  const ctx = {
15158
- version: version2,
15162
+ version: version3,
15159
15163
  defs,
15160
15164
  refs: /* @__PURE__ */ new Map(),
15161
15165
  processing: /* @__PURE__ */ new Set(),
15162
- rootSchema: normalized,
15166
+ rootSchema: normalized2,
15163
15167
  registry: params?.registry ?? globalRegistry
15164
15168
  };
15165
- return convertSchema(normalized, ctx);
15169
+ return convertSchema(normalized2, ctx);
15166
15170
  }
15167
15171
 
15168
15172
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
@@ -15307,8 +15311,8 @@ var ISSPACE = /[ \t\n\r\f\v]/;
15307
15311
  var NUL = String.fromCharCode(0);
15308
15312
  var BOM = 65279;
15309
15313
  var PRAGMA_PREFIX = "PRAGMA_";
15310
- function asciiUpper(text2) {
15311
- return text2.replace(/[a-z]+/g, (run) => run.toUpperCase());
15314
+ function asciiUpper(text3) {
15315
+ return text3.replace(/[a-z]+/g, (run) => run.toUpperCase());
15312
15316
  }
15313
15317
  function pragmaCandidate(sql, start, end, doubled) {
15314
15318
  const prefix = sql.slice(start + 1, start + 1 + PRAGMA_PREFIX.length);
@@ -15666,46 +15670,46 @@ function supportEndsAt(major) {
15666
15670
  function compare(a, b) {
15667
15671
  return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
15668
15672
  }
15669
- function withinVerifiedRange(version2) {
15670
- if (version2.major === 15) return compare(version2, VERIFIED_15_FLOOR) >= 0;
15671
- if (version2.major === 16) return compare(version2, VERIFIED_16_FLOOR) >= 0;
15672
- return version2.major > 16;
15673
+ function withinVerifiedRange(version3) {
15674
+ if (version3.major === 15) return compare(version3, VERIFIED_15_FLOOR) >= 0;
15675
+ if (version3.major === 16) return compare(version3, VERIFIED_16_FLOOR) >= 0;
15676
+ return version3.major > 16;
15673
15677
  }
15674
15678
  function formatDate(date5) {
15675
15679
  return date5.toISOString().slice(0, 10);
15676
15680
  }
15677
15681
  function classifyNextVersion(raw, now) {
15678
- const version2 = parseNextVersion(raw);
15679
- if (!version2) {
15682
+ const version3 = parseNextVersion(raw);
15683
+ if (!version3) {
15680
15684
  return {
15681
15685
  status: "unknown",
15682
15686
  version: null,
15683
15687
  reason: `Could not read a Next.js version from "${raw}".`
15684
15688
  };
15685
15689
  }
15686
- const windowEnd = supportEndsAt(version2.major);
15687
- if (!windowEnd || version2.major < VERIFIED_15_FLOOR.major) {
15690
+ const windowEnd = supportEndsAt(version3.major);
15691
+ if (!windowEnd || version3.major < VERIFIED_15_FLOOR.major) {
15688
15692
  return {
15689
15693
  status: "too-old",
15690
- version: version2,
15694
+ version: version3,
15691
15695
  reason: `Next.js ${raw} is too old to deploy. Naro deploys Next.js 15 or newer. Upgrade to Next.js 16.`
15692
15696
  };
15693
15697
  }
15694
15698
  if (now > windowEnd) {
15695
15699
  return {
15696
15700
  status: "needs-unsupported-flag",
15697
- version: version2,
15698
- reason: `Next.js ${version2.major} left its support window on ${formatDate(windowEnd)}. The build continues, but unsupported releases stop receiving security patches \u2014 upgrade to Next.js 16. See https://nextjs.org/support-policy`
15701
+ version: version3,
15702
+ reason: `Next.js ${version3.major} left its support window on ${formatDate(windowEnd)}. The build continues, but unsupported releases stop receiving security patches \u2014 upgrade to Next.js 16. See https://nextjs.org/support-policy`
15699
15703
  };
15700
15704
  }
15701
- if (!withinVerifiedRange(version2)) {
15705
+ if (!withinVerifiedRange(version3)) {
15702
15706
  return {
15703
15707
  status: "outside-peer-range",
15704
- version: version2,
15708
+ version: version3,
15705
15709
  reason: `Next.js ${raw} is outside the range Naro verifies deploys on (>=15.5.21 <16 || >=16.2.11). The build may fail in ways Naro cannot explain.`
15706
15710
  };
15707
15711
  }
15708
- return { status: "supported", version: version2, reason: "" };
15712
+ return { status: "supported", version: version3, reason: "" };
15709
15713
  }
15710
15714
 
15711
15715
  // ../../packages/build/src/package-manager.ts
@@ -15743,8 +15747,8 @@ async function usesModernYarn(root) {
15743
15747
  const raw = await readFile2(join2(root, "package.json"), "utf8");
15744
15748
  const packageJson = JSON.parse(raw);
15745
15749
  if (typeof packageJson.packageManager !== "string") return false;
15746
- const version2 = /^yarn@(\d+)/.exec(packageJson.packageManager)?.[1];
15747
- return version2 !== void 0 && Number(version2) >= 2;
15750
+ const version3 = /^yarn@(\d+)/.exec(packageJson.packageManager)?.[1];
15751
+ return version3 !== void 0 && Number(version3) >= 2;
15748
15752
  } catch {
15749
15753
  return false;
15750
15754
  }
@@ -16632,8 +16636,8 @@ var FRAMEWORK_LABELS = {
16632
16636
  static: "static files"
16633
16637
  };
16634
16638
  function dependencyVersion(packageJson, name) {
16635
- const version2 = packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];
16636
- return typeof version2 === "string" && version2.trim() !== "" ? version2 : null;
16639
+ const version3 = packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];
16640
+ return typeof version3 === "string" && version3.trim() !== "" ? version3 : null;
16637
16641
  }
16638
16642
  var STATIC_EXPORT = /(?:^|[\s,{;])output\s*:\s*(["'`])export\1/;
16639
16643
  function declaresStaticExport(source) {
@@ -16822,13 +16826,13 @@ async function detectFramework(root, overrides = {}) {
16822
16826
  `The project must declare a "${buildScript}" script.`
16823
16827
  );
16824
16828
  }
16825
- const version2 = packageJson && preset.detectDependency ? dependencyVersion(packageJson, preset.detectDependency) : null;
16829
+ const version3 = packageJson && preset.detectDependency ? dependencyVersion(packageJson, preset.detectDependency) : null;
16826
16830
  return {
16827
16831
  preset,
16828
16832
  buildScript,
16829
16833
  outputDirectory: overrides.outputDirectory ?? (preset.id === "angular" ? await angularOutput(root) : preset.defaultOutputDirectory),
16830
- description: version2 ? `${FRAMEWORK_LABELS[preset.id]} ${version2}` : FRAMEWORK_LABELS[preset.id],
16831
- dependencyRange: version2
16834
+ description: version3 ? `${FRAMEWORK_LABELS[preset.id]} ${version3}` : FRAMEWORK_LABELS[preset.id],
16835
+ dependencyRange: version3
16832
16836
  };
16833
16837
  }
16834
16838
 
@@ -17362,11 +17366,11 @@ function adapterKeyFromConfigSource(source) {
17362
17366
  return EXPERIMENTAL_ADAPTER_PATH.test(code) ? "experimental.adapterPath" : "adapterPath";
17363
17367
  }
17364
17368
  function keysNextReads(nextVersion) {
17365
- const version2 = parseNextVersion(nextVersion);
17366
- if (!version2) return ["adapterPath", "experimental.adapterPath"];
17367
- if (version2.major < 15 || version2.major === 15 && version2.minor < 4)
17369
+ const version3 = parseNextVersion(nextVersion);
17370
+ if (!version3) return ["adapterPath", "experimental.adapterPath"];
17371
+ if (version3.major < 15 || version3.major === 15 && version3.minor < 4)
17368
17372
  return [];
17369
- if (version2.major > 16 || version2.major === 16 && version2.minor >= 2)
17373
+ if (version3.major > 16 || version3.major === 16 && version3.minor >= 2)
17370
17374
  return ["adapterPath", "experimental.adapterPath"];
17371
17375
  return ["experimental.adapterPath"];
17372
17376
  }
@@ -17434,10 +17438,10 @@ async function exists4(path) {
17434
17438
  return false;
17435
17439
  }
17436
17440
  }
17437
- async function findSourceFile(appRoot, basename5) {
17441
+ async function findSourceFile(appRoot, basename6) {
17438
17442
  for (const dir of SOURCE_DIRECTORIES) {
17439
17443
  for (const ext of SOURCE_EXTENSIONS2) {
17440
- const rel = dir ? `${dir}/${basename5}.${ext}` : `${basename5}.${ext}`;
17444
+ const rel = dir ? `${dir}/${basename6}.${ext}` : `${basename6}.${ext}`;
17441
17445
  if (await exists4(join12(appRoot, rel))) return rel;
17442
17446
  }
17443
17447
  }
@@ -17514,11 +17518,11 @@ async function collectProjectFacts(appRoot) {
17514
17518
  function label(strategy) {
17515
17519
  return `P${String(strategy.priority)} ${strategy.id}`;
17516
17520
  }
17517
- function clause(text2) {
17518
- return text2.endsWith(".") && !text2.endsWith("..") ? text2.slice(0, -1) : text2;
17521
+ function clause(text3) {
17522
+ return text3.endsWith(".") && !text3.endsWith("..") ? text3.slice(0, -1) : text3;
17519
17523
  }
17520
- function sentence(text2) {
17521
- return text2.endsWith(".") ? text2 : `${text2}.`;
17524
+ function sentence(text3) {
17525
+ return text3.endsWith(".") ? text3 : `${text3}.`;
17522
17526
  }
17523
17527
  function describeOutcome(outcome) {
17524
17528
  switch (outcome.status) {
@@ -18799,8 +18803,8 @@ async function readInstalledNextVersion(appRoot, checkout) {
18799
18803
  join18(dir, "node_modules", "next", "package.json"),
18800
18804
  "utf8"
18801
18805
  );
18802
- const version2 = JSON.parse(source).version;
18803
- return typeof version2 === "string" ? version2 : null;
18806
+ const version3 = JSON.parse(source).version;
18807
+ return typeof version3 === "string" ? version3 : null;
18804
18808
  } catch {
18805
18809
  }
18806
18810
  if (dir === stop) return null;
@@ -19689,8 +19693,8 @@ function sendPage(res, status, html) {
19689
19693
  async function startCallbackServer() {
19690
19694
  let resolveCode;
19691
19695
  let rejectCode;
19692
- const codePromise = new Promise((resolve12, reject) => {
19693
- resolveCode = resolve12;
19696
+ const codePromise = new Promise((resolve15, reject) => {
19697
+ resolveCode = resolve15;
19694
19698
  rejectCode = reject;
19695
19699
  });
19696
19700
  const server = createServer2((req, res) => {
@@ -19719,7 +19723,7 @@ async function startCallbackServer() {
19719
19723
  sendPage(res, 200, successPage());
19720
19724
  resolveCode(code);
19721
19725
  });
19722
- await new Promise((resolve12) => server.listen(0, "127.0.0.1", resolve12));
19726
+ await new Promise((resolve15) => server.listen(0, "127.0.0.1", resolve15));
19723
19727
  const port = server.address().port;
19724
19728
  return {
19725
19729
  port,
@@ -20127,6 +20131,7 @@ var NaroClient = class _NaroClient {
20127
20131
  method: options.method ?? "GET",
20128
20132
  headers: {
20129
20133
  Authorization: `Bearer ${token}`,
20134
+ "X-Naro-Client": this.options.clientName ?? "next-deploy-sdk",
20130
20135
  ...options.body !== void 0 ? { "Content-Type": "application/json" } : {}
20131
20136
  },
20132
20137
  ...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {},
@@ -20170,9 +20175,9 @@ var TeamsApi = class {
20170
20175
  async usage(teamSlug, query = {}) {
20171
20176
  const params = new URLSearchParams();
20172
20177
  if (query.month !== void 0) params.set("month", query.month);
20173
- const text2 = params.toString();
20178
+ const text3 = params.toString();
20174
20179
  return this.client.request(
20175
- `/api/teams/${encodeURIComponent(teamSlug)}/usage${text2 ? `?${text2}` : ""}`,
20180
+ `/api/teams/${encodeURIComponent(teamSlug)}/usage${text3 ? `?${text3}` : ""}`,
20176
20181
  { context: "Read team usage" }
20177
20182
  );
20178
20183
  }
@@ -20397,7 +20402,7 @@ var DeploymentsApi = class {
20397
20402
  async wait(deploymentId, options = {}) {
20398
20403
  const intervalMs = options.intervalMs ?? 2500;
20399
20404
  const timeoutMs = options.timeoutMs ?? 15 * 6e4;
20400
- const sleep2 = options.sleep ?? ((ms) => new Promise((resolve12) => setTimeout(resolve12, ms)));
20405
+ const sleep2 = options.sleep ?? ((ms) => new Promise((resolve15) => setTimeout(resolve15, ms)));
20401
20406
  const startedAt = Date.now();
20402
20407
  let lastStatus = null;
20403
20408
  let lastSequence = -1;
@@ -20690,8 +20695,8 @@ function insightsQuery(options) {
20690
20695
  if (options.environment !== void 0) params.set("env", options.environment);
20691
20696
  if (options.route !== void 0) params.set("route", options.route);
20692
20697
  appendFilters(params, SPEED_INSIGHTS_FILTER_KEYS, options.filters);
20693
- const text2 = params.toString();
20694
- return text2 ? `?${text2}` : "";
20698
+ const text3 = params.toString();
20699
+ return text3 ? `?${text3}` : "";
20695
20700
  }
20696
20701
  var InsightsApi = class {
20697
20702
  constructor(client) {
@@ -20769,9 +20774,9 @@ var AnalyticsApi = class {
20769
20774
  const params = new URLSearchParams();
20770
20775
  if (options.range !== void 0) params.set("range", options.range);
20771
20776
  appendFilters(params, ANALYTICS_FILTER_KEYS, options.filters);
20772
- const text2 = params.toString();
20777
+ const text3 = params.toString();
20773
20778
  return this.client.request(
20774
- `/api/projects/${encodeURIComponent(projectId)}/analytics${text2 ? `?${text2}` : ""}`,
20779
+ `/api/projects/${encodeURIComponent(projectId)}/analytics${text3 ? `?${text3}` : ""}`,
20775
20780
  { context: "Read Analytics" }
20776
20781
  );
20777
20782
  }
@@ -21009,7 +21014,7 @@ var DbApi = class {
21009
21014
  */
21010
21015
  async export(projectId, options = {}, wait = {}) {
21011
21016
  const timeoutMs = wait.timeoutMs ?? EXPORT_TIMEOUT_MS;
21012
- const sleep2 = wait.sleep ?? ((ms) => new Promise((resolve12) => setTimeout(resolve12, ms)));
21017
+ const sleep2 = wait.sleep ?? ((ms) => new Promise((resolve15) => setTimeout(resolve15, ms)));
21013
21018
  const given = wait.pollIntervalMs;
21014
21019
  const firstPollMs = given !== void 0 && Number.isFinite(given) && given > 0 ? given : EXPORT_FIRST_POLL_MS;
21015
21020
  const maxPollMs = Math.max(EXPORT_MAX_POLL_MS, firstPollMs);
@@ -21952,16 +21957,17 @@ var FunctionsApi = class {
21952
21957
  * `BACKEND_BUSY` (the project's Naro worker is not the current version and
21953
21958
  * could not be brought up to date just now), `FUNCTION_LIMIT` (a new name
21954
21959
  * over the plan's cap) and `FUNCTION_BUSY` (the function is being deleted).
21955
- * It never turns the backend on. Two minutes.
21960
+ * It never turns the backend on. Two minutes, or `options.timeoutMs`
21961
+ * (naro-mcp's deploy_function shares two minutes across its steps).
21956
21962
  */
21957
- async createVersion(projectId, name, request2) {
21963
+ async createVersion(projectId, name, request2, options = {}) {
21958
21964
  return this.client.request(
21959
21965
  this.functionPath(projectId, name, "/versions"),
21960
21966
  {
21961
21967
  method: "POST",
21962
21968
  body: request2,
21963
21969
  context: "Create a function version",
21964
- timeoutMs: PROVISION_TIMEOUT_MS
21970
+ timeoutMs: options.timeoutMs ?? PROVISION_TIMEOUT_MS
21965
21971
  }
21966
21972
  );
21967
21973
  }
@@ -21978,9 +21984,10 @@ var FunctionsApi = class {
21978
21984
  * not take it, so callers may still get the previous `verifyJwt` setting
21979
21985
  * or 404 — deploy again) and `BACKEND_OUTDATED` (the project's
21980
21986
  * database predates the function list — `backend.enable` updates it).
21981
- * Two minutes.
21987
+ * Two minutes, or `options.timeoutMs`; a timeout here does not say
21988
+ * whether the version went live — `get` does.
21982
21989
  */
21983
- async deploy(projectId, name, versionId) {
21990
+ async deploy(projectId, name, versionId, options = {}) {
21984
21991
  const body = await this.client.request(
21985
21992
  this.functionPath(
21986
21993
  projectId,
@@ -21990,7 +21997,7 @@ var FunctionsApi = class {
21990
21997
  {
21991
21998
  method: "POST",
21992
21999
  context: "Deploy a function",
21993
- timeoutMs: PROVISION_TIMEOUT_MS
22000
+ timeoutMs: options.timeoutMs ?? PROVISION_TIMEOUT_MS
21994
22001
  }
21995
22002
  );
21996
22003
  return body.function;
@@ -22004,12 +22011,12 @@ var FunctionsApi = class {
22004
22011
  * `VERSION_NOT_FOUND` also says there is no earlier deployed version.
22005
22012
  * Two minutes.
22006
22013
  */
22007
- async rollback(projectId, name, version2) {
22014
+ async rollback(projectId, name, version3) {
22008
22015
  const body = await this.client.request(
22009
22016
  this.functionPath(projectId, name, "/rollback"),
22010
22017
  {
22011
22018
  method: "POST",
22012
- body: version2 === void 0 ? {} : { version: version2 },
22019
+ body: version3 === void 0 ? {} : { version: version3 },
22013
22020
  context: "Roll back a function",
22014
22021
  timeoutMs: PROVISION_TIMEOUT_MS
22015
22022
  }
@@ -22058,10 +22065,13 @@ var FunctionsApi = class {
22058
22065
  return body.entries;
22059
22066
  }
22060
22067
  /** The project's function secrets: names, digests and when — never a value. `env.read`. */
22061
- async secrets(projectId) {
22068
+ async secrets(projectId, options = {}) {
22062
22069
  const body = await this.client.request(
22063
22070
  this.path(projectId, "-secrets"),
22064
- { context: "List function secrets" }
22071
+ {
22072
+ context: "List function secrets",
22073
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
22074
+ }
22065
22075
  );
22066
22076
  return body.secrets;
22067
22077
  }
@@ -22121,8 +22131,8 @@ function cellText(statement2, row, column2) {
22121
22131
  var MAX_CELL_CHARS = 60;
22122
22132
  function formatCell(value) {
22123
22133
  if (value === null || value === void 0) return "NULL";
22124
- const text2 = typeof value === "string" ? value : typeof value === "object" ? JSON.stringify(value) : String(value);
22125
- const oneLine2 = text2.replace(/\s+/g, " ");
22134
+ const text3 = typeof value === "string" ? value : typeof value === "object" ? JSON.stringify(value) : String(value);
22135
+ const oneLine2 = text3.replace(/\s+/g, " ");
22126
22136
  return oneLine2.length > MAX_CELL_CHARS ? `${oneLine2.slice(0, MAX_CELL_CHARS - 1)}\u2026` : oneLine2;
22127
22137
  }
22128
22138
  function renderRows(statement2) {
@@ -22154,10 +22164,10 @@ import { existsSync, readFileSync as readFileSync2 } from "fs";
22154
22164
  import { join as join20 } from "path";
22155
22165
  var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/dgm;
22156
22166
  var QUOTES = /* @__PURE__ */ new Set(["'", '"', "`"]);
22157
- function parseDotenvDetailed(text2) {
22167
+ function parseDotenvDetailed(text3) {
22158
22168
  const vars = {};
22159
22169
  const unclosedQuotes = [];
22160
- const lines = text2.replace(/\r\n?/g, "\n");
22170
+ const lines = text3.replace(/\r\n?/g, "\n");
22161
22171
  let line = 1;
22162
22172
  let counted = 0;
22163
22173
  for (const match of lines.matchAll(LINE)) {
@@ -22177,8 +22187,8 @@ function parseDotenvDetailed(text2) {
22177
22187
  }
22178
22188
  return { vars, unclosedQuotes };
22179
22189
  }
22180
- function parseDotenv(text2) {
22181
- return parseDotenvDetailed(text2).vars;
22190
+ function parseDotenv(text3) {
22191
+ return parseDotenvDetailed(text3).vars;
22182
22192
  }
22183
22193
  function readProjectEnv(dir) {
22184
22194
  for (const name of [".env.local", ".env.production", ".env"]) {
@@ -22309,14 +22319,14 @@ function scanEnvReferences(dir) {
22309
22319
  const files = [];
22310
22320
  collect(dir, files);
22311
22321
  for (const file2 of files) {
22312
- let text2;
22322
+ let text3;
22313
22323
  try {
22314
22324
  if (statSync(file2).size > MAX_FILE_BYTES2) continue;
22315
- text2 = readFileSync3(file2, "utf8");
22325
+ text3 = readFileSync3(file2, "utf8");
22316
22326
  } catch {
22317
22327
  continue;
22318
22328
  }
22319
- for (const match of text2.matchAll(REFERENCE)) {
22329
+ for (const match of text3.matchAll(REFERENCE)) {
22320
22330
  const key = match[1] ?? match[2];
22321
22331
  if (!key || ignored(key)) continue;
22322
22332
  found.set(key, "code");
@@ -22504,15 +22514,15 @@ var SYSTEM_TABLE_PREFIXES = [
22504
22514
  "sqlite_"
22505
22515
  ];
22506
22516
  var SYSTEM_TABLE_NAMES = ["d1_migrations"];
22507
- function asciiLower(text2) {
22508
- return text2.replace(/[A-Z]+/g, (run) => run.toLowerCase());
22517
+ function asciiLower(text3) {
22518
+ return text3.replace(/[A-Z]+/g, (run) => run.toLowerCase());
22509
22519
  }
22510
22520
  function isSystemTable(name) {
22511
22521
  const lower = asciiLower(name);
22512
22522
  return SYSTEM_TABLE_PREFIXES.some((prefix) => lower.startsWith(prefix)) || SYSTEM_TABLE_NAMES.includes(lower);
22513
22523
  }
22514
- function likeLiteral(text2) {
22515
- return text2.replace(/[\\%_]/g, (char) => `\\${char}`).replace(/'/g, "''");
22524
+ function likeLiteral(text3) {
22525
+ return text3.replace(/[\\%_]/g, (char) => `\\${char}`).replace(/'/g, "''");
22516
22526
  }
22517
22527
  var COLUMN_REFERENCE = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;
22518
22528
  function systemTablePredicate(column2 = "name") {
@@ -22538,8 +22548,8 @@ function isSpace(char) {
22538
22548
  function isWordChar(char) {
22539
22549
  return /[A-Za-z0-9_$]/.test(char) || char.charCodeAt(0) >= 128;
22540
22550
  }
22541
- function asciiUpper2(text2) {
22542
- return text2.replace(/[a-z]/g, (letter) => letter.toUpperCase());
22551
+ function asciiUpper2(text3) {
22552
+ return text3.replace(/[a-z]/g, (letter) => letter.toUpperCase());
22543
22553
  }
22544
22554
  function quoted2(sql, start, close, doubles) {
22545
22555
  let value = "";
@@ -22677,16 +22687,16 @@ function declaredCollations(sql, columns) {
22677
22687
  }
22678
22688
 
22679
22689
  // ../../packages/data-core/src/unicode-controls.ts
22680
- function hasControlCharacter(text2) {
22681
- for (let i = 0; i < text2.length; i += 1) {
22682
- const code = text2.charCodeAt(i);
22690
+ function hasControlCharacter(text3) {
22691
+ for (let i = 0; i < text3.length; i += 1) {
22692
+ const code = text3.charCodeAt(i);
22683
22693
  if (code <= 31 || code >= 127 && code <= 159) return true;
22684
22694
  }
22685
22695
  return false;
22686
22696
  }
22687
- function hasBidiControl(text2) {
22688
- for (let i = 0; i < text2.length; i += 1) {
22689
- const code = text2.charCodeAt(i);
22697
+ function hasBidiControl(text3) {
22698
+ for (let i = 0; i < text3.length; i += 1) {
22699
+ const code = text3.charCodeAt(i);
22690
22700
  if (code === 1564 || code === 8206 || code === 8207 || code >= 8234 && code <= 8238 || code >= 8294 && code <= 8297)
22691
22701
  return true;
22692
22702
  }
@@ -22711,8 +22721,8 @@ var RESERVED = new Set(STORAGE_RESERVED_WORDS);
22711
22721
  var ENCODER = new TextEncoder();
22712
22722
  var LONE_SURROGATE2 = /[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/;
22713
22723
  var LONE_SURROGATES = new RegExp(LONE_SURROGATE2.source, "g");
22714
- function hasLoneSurrogate(text2) {
22715
- return LONE_SURROGATE2.test(text2);
22724
+ function hasLoneSurrogate(text3) {
22725
+ return LONE_SURROGATE2.test(text3);
22716
22726
  }
22717
22727
  function refuse(reason) {
22718
22728
  return { ok: false, reason };
@@ -22754,9 +22764,9 @@ function parseCacheControl(header) {
22754
22764
  return maxAge <= MAX_MAX_AGE ? { ok: true, maxAge } : { ok: false };
22755
22765
  }
22756
22766
  var MAX_NAME_IN_MESSAGE = 256;
22757
- function storageName(text2) {
22758
- if (text2.length <= MAX_NAME_IN_MESSAGE) return text2;
22759
- const cut = text2.slice(0, MAX_NAME_IN_MESSAGE);
22767
+ function storageName(text3) {
22768
+ if (text3.length <= MAX_NAME_IN_MESSAGE) return text3;
22769
+ const cut = text3.slice(0, MAX_NAME_IN_MESSAGE);
22760
22770
  const last = cut.charCodeAt(MAX_NAME_IN_MESSAGE - 1);
22761
22771
  return last >= 55296 && last <= 56319 ? cut.slice(0, MAX_NAME_IN_MESSAGE - 1) : cut;
22762
22772
  }
@@ -22901,15 +22911,15 @@ var CATALOG = {
22901
22911
  policy,
22902
22912
  recursion,
22903
22913
  values,
22904
- bytes,
22914
+ bytes: bytes2,
22905
22915
  depth
22906
22916
  }) => {
22907
22917
  if (recursion)
22908
22918
  return `Infinite recursion detected in policy for relation ${table}.`;
22909
22919
  if (values)
22910
22920
  return `The policies of ${table} bind more than ${values === true ? "50" : String(values)} values in one statement.`;
22911
- if (bytes)
22912
- return `The policies of ${table} write more than ${bytes === true ? "50000" : String(bytes)} bytes of SQL into one statement.`;
22921
+ if (bytes2)
22922
+ return `The policies of ${table} write more than ${bytes2 === true ? "50000" : String(bytes2)} bytes of SQL into one statement.`;
22913
22923
  if (depth)
22914
22924
  return `The policies of ${table} nest an expression more than 100 deep into one statement.`;
22915
22925
  if (policy !== void 0)
@@ -23110,11 +23120,11 @@ function isDigit(char) {
23110
23120
  return char >= "0" && char <= "9";
23111
23121
  }
23112
23122
  var NUMBER = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/;
23113
- function tokenize2(text2) {
23123
+ function tokenize2(text3) {
23114
23124
  const tokens = [];
23115
23125
  let index = 0;
23116
- const at = (offset = 0) => text2.charAt(index + offset);
23117
- while (index < text2.length) {
23126
+ const at = (offset = 0) => text3.charAt(index + offset);
23127
+ while (index < text3.length) {
23118
23128
  const char = at();
23119
23129
  const position = index + 1;
23120
23130
  if (char === "\0")
@@ -23124,12 +23134,12 @@ function tokenize2(text2) {
23124
23134
  continue;
23125
23135
  }
23126
23136
  if (char === "-" && at(1) === "-") {
23127
- while (index < text2.length && at() !== "\n" && at() !== "\r") index++;
23137
+ while (index < text3.length && at() !== "\n" && at() !== "\r") index++;
23128
23138
  continue;
23129
23139
  }
23130
23140
  if (char === "/" && at(1) === "*") {
23131
23141
  let depth = 0;
23132
- while (index < text2.length) {
23142
+ while (index < text3.length) {
23133
23143
  if (at() === "/" && at(1) === "*") {
23134
23144
  depth++;
23135
23145
  index += 2;
@@ -23147,7 +23157,7 @@ function tokenize2(text2) {
23147
23157
  let value = "";
23148
23158
  index++;
23149
23159
  for (; ; ) {
23150
- if (index >= text2.length)
23160
+ if (index >= text3.length)
23151
23161
  throw new PolicySyntaxError("unterminated quoted string", position);
23152
23162
  if (at() === "'") {
23153
23163
  if (at(1) === "'") {
@@ -23168,7 +23178,7 @@ function tokenize2(text2) {
23168
23178
  let value = "";
23169
23179
  index++;
23170
23180
  for (; ; ) {
23171
- if (index >= text2.length)
23181
+ if (index >= text3.length)
23172
23182
  throw new PolicySyntaxError(
23173
23183
  "unterminated quoted identifier",
23174
23184
  position
@@ -23196,10 +23206,10 @@ function tokenize2(text2) {
23196
23206
  position
23197
23207
  );
23198
23208
  if (isDigit(char) || char === "." && isDigit(at(1))) {
23199
- const match = NUMBER.exec(text2.slice(index));
23209
+ const match = NUMBER.exec(text3.slice(index));
23200
23210
  const value = match?.[0] ?? char;
23201
23211
  index += value.length;
23202
- if (index < text2.length && isIdentChar(at()))
23212
+ if (index < text3.length && isIdentChar(at()))
23203
23213
  throw new PolicySyntaxError(
23204
23214
  `trailing junk after numeric literal ${value}`,
23205
23215
  position
@@ -23209,9 +23219,9 @@ function tokenize2(text2) {
23209
23219
  }
23210
23220
  if (isIdentStart(char)) {
23211
23221
  let end = index + 1;
23212
- while (end < text2.length && isIdentChar(text2.charAt(end))) end++;
23213
- const value = text2.slice(index, end);
23214
- if (text2.charAt(end) === "'")
23222
+ while (end < text3.length && isIdentChar(text3.charAt(end))) end++;
23223
+ const value = text3.slice(index, end);
23224
+ if (text3.charAt(end) === "'")
23215
23225
  throw new PolicySyntaxError(
23216
23226
  `${value}'\u2026' strings are not supported: use a plain '\u2026' string`,
23217
23227
  position
@@ -23221,7 +23231,7 @@ function tokenize2(text2) {
23221
23231
  continue;
23222
23232
  }
23223
23233
  const operator = OPERATORS.find(
23224
- (candidate) => text2.startsWith(candidate, index)
23234
+ (candidate) => text3.startsWith(candidate, index)
23225
23235
  );
23226
23236
  if (!operator)
23227
23237
  throw new PolicySyntaxError(
@@ -23235,7 +23245,7 @@ function tokenize2(text2) {
23235
23245
  kind: "eof",
23236
23246
  value: "",
23237
23247
  quoted: false,
23238
- position: text2.length + 1
23248
+ position: text3.length + 1
23239
23249
  });
23240
23250
  return tokens;
23241
23251
  }
@@ -23564,21 +23574,21 @@ function toBoundValue(value) {
23564
23574
  if (typeof value === "string" || typeof value === "number") return value;
23565
23575
  return JSON.stringify(value);
23566
23576
  }
23567
- function utf8ByteLength(text2) {
23568
- let bytes = 0;
23569
- for (let index = 0; index < text2.length; index++) {
23570
- const unit = text2.charCodeAt(index);
23571
- if (unit < 128) bytes += 1;
23572
- else if (unit < 2048) bytes += 2;
23573
- else if (unit >= 55296 && unit <= 56319 && index + 1 < text2.length) {
23574
- const next = text2.charCodeAt(index + 1);
23577
+ function utf8ByteLength(text3) {
23578
+ let bytes2 = 0;
23579
+ for (let index = 0; index < text3.length; index++) {
23580
+ const unit = text3.charCodeAt(index);
23581
+ if (unit < 128) bytes2 += 1;
23582
+ else if (unit < 2048) bytes2 += 2;
23583
+ else if (unit >= 55296 && unit <= 56319 && index + 1 < text3.length) {
23584
+ const next = text3.charCodeAt(index + 1);
23575
23585
  if (next >= 56320 && next <= 57343) {
23576
- bytes += 4;
23586
+ bytes2 += 4;
23577
23587
  index++;
23578
- } else bytes += 3;
23579
- } else bytes += 3;
23588
+ } else bytes2 += 3;
23589
+ } else bytes2 += 3;
23580
23590
  }
23581
- return bytes;
23591
+ return bytes2;
23582
23592
  }
23583
23593
 
23584
23594
  // ../../packages/data-core/src/sql-fragments.ts
@@ -23672,9 +23682,9 @@ function isNumeric(item) {
23672
23682
  const affinity2 = columnAffinity(item);
23673
23683
  return affinity2 !== "TEXT" && affinity2 !== "BLOB";
23674
23684
  }
23675
- function refusesText(item, text2) {
23685
+ function refusesText(item, text3) {
23676
23686
  const kind = numberClass(item.type);
23677
- return kind === "number" || kind === "fallback" && storesAsNumber(text2);
23687
+ return kind === "number" || kind === "fallback" && storesAsNumber(text3);
23678
23688
  }
23679
23689
  function readsAsIs(item, value) {
23680
23690
  return typeof value === "string" && numberClass(item.type) === "fallback" && !storesAsNumber(value);
@@ -23700,15 +23710,15 @@ function asStored(item, sql) {
23700
23710
  var LITERAL_DEFAULT = /^(?:null|true|false|[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|'(?:[^']|'')*')$/i;
23701
23711
  function omittedSql(item) {
23702
23712
  if (item.primaryKey > 0) return void 0;
23703
- const text2 = item.defaultValue;
23704
- if (text2 === null) return "NULL";
23705
- if (!LITERAL_DEFAULT.test(text2)) return void 0;
23706
- const word = asciiLower(text2);
23713
+ const text3 = item.defaultValue;
23714
+ if (text3 === null) return "NULL";
23715
+ if (!LITERAL_DEFAULT.test(text3)) return void 0;
23716
+ const word = asciiLower(text3);
23707
23717
  if (word === "null") return "NULL";
23708
23718
  if (word === "true" || word === "false")
23709
23719
  return asStored(item, word === "true" ? "1" : "0");
23710
- if (text2.startsWith("'") && isNumeric(item)) return void 0;
23711
- return asStored(item, text2);
23720
+ if (text3.startsWith("'") && isNumeric(item)) return void 0;
23721
+ return asStored(item, text3);
23712
23722
  }
23713
23723
  var DEFAULT_KEYWORDS = /* @__PURE__ */ new Set([
23714
23724
  "true",
@@ -23719,27 +23729,27 @@ var DEFAULT_KEYWORDS = /* @__PURE__ */ new Set([
23719
23729
  "current_timestamp"
23720
23730
  ]);
23721
23731
  var BARE_WORD = /^[A-Za-z_\u0080-￿][A-Za-z0-9_$\u0080-￿]*$/;
23722
- function quotedName(text2) {
23723
- const double = /^"((?:[^"]|"")*)"$/.exec(text2);
23732
+ function quotedName(text3) {
23733
+ const double = /^"((?:[^"]|"")*)"$/.exec(text3);
23724
23734
  if (double) return (double[1] ?? "").replaceAll('""', '"');
23725
- const tick = /^`((?:[^`]|``)*)`$/.exec(text2);
23735
+ const tick = /^`((?:[^`]|``)*)`$/.exec(text3);
23726
23736
  if (tick) return (tick[1] ?? "").replaceAll("``", "`");
23727
- const bracket = /^\[([^\]]*)\]$/.exec(text2);
23737
+ const bracket = /^\[([^\]]*)\]$/.exec(text3);
23728
23738
  return bracket ? bracket[1] ?? "" : void 0;
23729
23739
  }
23730
23740
  function stringDefault(item) {
23731
- let text2 = item.defaultValue?.trim();
23732
- if (text2 === void 0) return void 0;
23733
- while (text2.startsWith("(") && text2.endsWith(")"))
23734
- text2 = text2.slice(1, -1).trim();
23735
- if (/^\+\s*(?:'|x')/i.test(text2)) text2 = text2.slice(1).trim();
23736
- if (/^'(?:[^']|'')*'$/.test(text2))
23737
- return { kind: "text", text: text2.slice(1, -1).replaceAll("''", "'") };
23738
- if (/^x'[0-9a-f]*'$/i.test(text2)) return { kind: "blob" };
23739
- const name = quotedName(text2);
23741
+ let text3 = item.defaultValue?.trim();
23742
+ if (text3 === void 0) return void 0;
23743
+ while (text3.startsWith("(") && text3.endsWith(")"))
23744
+ text3 = text3.slice(1, -1).trim();
23745
+ if (/^\+\s*(?:'|x')/i.test(text3)) text3 = text3.slice(1).trim();
23746
+ if (/^'(?:[^']|'')*'$/.test(text3))
23747
+ return { kind: "text", text: text3.slice(1, -1).replaceAll("''", "'") };
23748
+ if (/^x'[0-9a-f]*'$/i.test(text3)) return { kind: "blob" };
23749
+ const name = quotedName(text3);
23740
23750
  if (name !== void 0) return { kind: "text", text: name };
23741
- if (BARE_WORD.test(text2) && !DEFAULT_KEYWORDS.has(asciiLower(text2)))
23742
- return { kind: "text", text: text2 };
23751
+ if (BARE_WORD.test(text3) && !DEFAULT_KEYWORDS.has(asciiLower(text3)))
23752
+ return { kind: "text", text: text3 };
23743
23753
  return void 0;
23744
23754
  }
23745
23755
  var DEFAULT_CHECK_NONCE = "0";
@@ -23871,25 +23881,25 @@ function nested(state, token, read) {
23871
23881
  }
23872
23882
  }
23873
23883
  function truthProblem(operand) {
23874
- const text2 = "is text, where 'true' reads as false";
23884
+ const text3 = "is text, where 'true' reads as false";
23875
23885
  switch (operand.kind) {
23876
23886
  case "column":
23877
23887
  return void 0;
23878
23888
  case "literal":
23879
- return typeof operand.value === "string" ? `a '\u2026' string ${text2}: write TRUE or FALSE, or compare the string with =` : void 0;
23889
+ return typeof operand.value === "string" ? `a '\u2026' string ${text3}: write TRUE or FALSE, or compare the string with =` : void 0;
23880
23890
  case "jwt": {
23881
23891
  const claim = printValue(operand);
23882
- return `${claim} ${text2}: compare it with text, ${claim} = 'true'`;
23892
+ return `${claim} ${text3}: compare it with text, ${claim} = 'true'`;
23883
23893
  }
23884
23894
  case "auth":
23885
23895
  return operand.fn === "uid" ? "auth.uid() is text: compare it, auth.uid() = user_id, or test auth.uid() IS NOT NULL" : "auth.role() is text: compare it, auth.role() = 'authenticated'";
23886
23896
  case "cast":
23887
- return `a ::text cast ${text2}: compare it with text, (\u2026)::text = 'true'`;
23897
+ return `a ::text cast ${text3}: compare it with text, (\u2026)::text = 'true'`;
23888
23898
  case "func":
23889
23899
  switch (operand.name) {
23890
23900
  case "lower":
23891
23901
  case "upper":
23892
- return `${operand.name}(\u2026) ${text2}: compare it with text, ${operand.name}(\u2026) = 'true'`;
23902
+ return `${operand.name}(\u2026) ${text3}: compare it with text, ${operand.name}(\u2026) = 'true'`;
23893
23903
  case "coalesce":
23894
23904
  return "coalesce(\u2026) is not a boolean: compare it, coalesce(\u2026) = 'true'";
23895
23905
  case "length":
@@ -23899,10 +23909,10 @@ function truthProblem(operand) {
23899
23909
  }
23900
23910
  case "storage": {
23901
23911
  const call = operand.fn === "foldername" ? "(storage.foldername(\u2026))[n]" : `storage.${operand.fn}(\u2026)`;
23902
- return `${call} ${text2}: compare it with text, ${call} = 'true'`;
23912
+ return `${call} ${text3}: compare it with text, ${call} = 'true'`;
23903
23913
  }
23904
23914
  case "realtime":
23905
- return `realtime.topic() ${text2}: compare it with text, realtime.topic() = 'room:1'`;
23915
+ return `realtime.topic() ${text3}: compare it with text, realtime.topic() = 'room:1'`;
23906
23916
  }
23907
23917
  }
23908
23918
  function truthTestProblem(operand) {
@@ -23956,9 +23966,9 @@ function booleanComparisonProblem(expr) {
23956
23966
  const met = [...operandValues(left), ...operandValues(right)];
23957
23967
  if (!met.some(isBooleanConstant)) continue;
23958
23968
  const texts = met.filter(isTextValue);
23959
- const text2 = texts.find((value) => value.kind !== "literal") ?? texts[0];
23960
- if (text2 === void 0) continue;
23961
- const problem = text2.kind === "literal" ? "a '\u2026' string is text, where 'true' reads as false: write TRUE or FALSE on both sides, or a '\u2026' string on both" : truthProblem(text2);
23969
+ const text3 = texts.find((value) => value.kind !== "literal") ?? texts[0];
23970
+ if (text3 === void 0) continue;
23971
+ const problem = text3.kind === "literal" ? "a '\u2026' string is text, where 'true' reads as false: write TRUE or FALSE on both sides, or a '\u2026' string on both" : truthProblem(text3);
23962
23972
  return `a comparison with TRUE or FALSE compares a boolean, and ${String(problem)}`;
23963
23973
  }
23964
23974
  return void 0;
@@ -24036,17 +24046,17 @@ function readPredicate(state) {
24036
24046
  }
24037
24047
  const left = readValue(state);
24038
24048
  const next = stream.peek();
24039
- const compare2 = ["=", "<>", "!=", "<", "<=", ">", ">="].find(
24049
+ const compare3 = ["=", "<>", "!=", "<", "<=", ">", ">="].find(
24040
24050
  (op) => isOperator(next, op)
24041
24051
  );
24042
- if (compare2) {
24052
+ if (compare3) {
24043
24053
  stream.next();
24044
24054
  count(state, next);
24045
24055
  const right = readValue(state);
24046
24056
  return comparable(
24047
24057
  {
24048
24058
  kind: "compare",
24049
- op: compare2 === "!=" ? "<>" : compare2,
24059
+ op: compare3 === "!=" ? "<>" : compare3,
24050
24060
  left: requireValue(left, token),
24051
24061
  right: requireValue(right, next)
24052
24062
  },
@@ -24148,8 +24158,8 @@ function policyPatternProblem(pattern, ci) {
24148
24158
  if (!patternTooLong(pattern, ci)) return void 0;
24149
24159
  const chars = [...pattern];
24150
24160
  const shown = `${commentText(chars.slice(0, PATTERN_SHOWN).join(""))}${chars.length > PATTERN_SHOWN ? "\u2026" : ""}`;
24151
- const bytes = utf8ByteLength(boundPattern(pattern, ci));
24152
- return `${ci ? "an ILIKE" : "a LIKE"} pattern may be at most ${String(MAX_POLICY_PATTERN_LENGTH)} bytes of UTF-8, D1's limit, and '${shown}' is ${String(bytes)}${ci ? "" : " (LIKE counts each *, ? and [ as 3 bytes)"}`;
24161
+ const bytes2 = utf8ByteLength(boundPattern(pattern, ci));
24162
+ return `${ci ? "an ILIKE" : "a LIKE"} pattern may be at most ${String(MAX_POLICY_PATTERN_LENGTH)} bytes of UTF-8, D1's limit, and '${shown}' is ${String(bytes2)}${ci ? "" : " (LIKE counts each *, ? and [ as 3 bytes)"}`;
24153
24163
  }
24154
24164
  function checkPattern(token, ci) {
24155
24165
  const pattern = token.value;
@@ -24670,17 +24680,17 @@ function readCondition(stream) {
24670
24680
  return requireCondition(expr, token);
24671
24681
  }
24672
24682
  function checkExpressionSize(expr, position) {
24673
- const text2 = printExpr(expr);
24674
- if (utf8ByteLength(text2) > MAX_EXPRESSION_BYTES)
24683
+ const text3 = printExpr(expr);
24684
+ if (utf8ByteLength(text3) > MAX_EXPRESSION_BYTES)
24675
24685
  throw new PolicySyntaxError(
24676
24686
  `the expression is longer than ${String(MAX_EXPRESSION_BYTES)} bytes`,
24677
24687
  position
24678
24688
  );
24679
- return text2;
24689
+ return text3;
24680
24690
  }
24681
- function parseExpression(text2) {
24691
+ function parseExpression(text3) {
24682
24692
  try {
24683
- const stream = new TokenStream(tokenize2(text2));
24693
+ const stream = new TokenStream(tokenize2(text3));
24684
24694
  if (stream.peek().kind === "eof")
24685
24695
  throw new PolicySyntaxError("the expression is empty", 1);
24686
24696
  const expr = readCondition(stream);
@@ -24695,22 +24705,22 @@ function parseExpression(text2) {
24695
24705
  function quoteIdent(name) {
24696
24706
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && !SPECIAL_WORDS.has(asciiLower(name)) ? name : `"${name.replaceAll('"', '""')}"`;
24697
24707
  }
24698
- function commentText(text2) {
24708
+ function commentText(text3) {
24699
24709
  let out = "";
24700
- for (const char of text2) {
24710
+ for (const char of text3) {
24701
24711
  const code = char.charCodeAt(0);
24702
24712
  const control = code < 32 || code >= 127 && code <= 159 || code === 8232 || code === 8233;
24703
24713
  out += control ? `\\u${code.toString(16).padStart(4, "0")}` : char;
24704
24714
  }
24705
24715
  return out;
24706
24716
  }
24707
- function quoteString(text2) {
24708
- return `'${text2.replaceAll("'", "''")}'`;
24717
+ function quoteString(text3) {
24718
+ return `'${text3.replaceAll("'", "''")}'`;
24709
24719
  }
24710
24720
  function printNumber(value) {
24711
24721
  if (Object.is(value, -0)) return "-0.0";
24712
- const text2 = String(value);
24713
- return Number.isSafeInteger(value) || /[.e]/.test(text2) ? text2 : `${text2}.0`;
24722
+ const text3 = String(value);
24723
+ return Number.isSafeInteger(value) || /[.e]/.test(text3) ? text3 : `${text3}.0`;
24714
24724
  }
24715
24725
  function printLiteral(value) {
24716
24726
  if (value === null) return "NULL";
@@ -24964,8 +24974,8 @@ function ownerExpression(column2) {
24964
24974
  });
24965
24975
  }
24966
24976
  function ownerClauses(column2, command) {
24967
- const text2 = ownerExpression(column2);
24968
- return command === "insert" ? { using: null, check: text2 } : { using: text2, check: null };
24977
+ const text3 = ownerExpression(column2);
24978
+ return command === "insert" ? { using: null, check: text3 } : { using: text3, check: null };
24969
24979
  }
24970
24980
  var NAMED_POLICY_TABLE = "_naro_policies_v2";
24971
24981
  var NAMED_POLICY_TABLE_SQL = `CREATE TABLE IF NOT EXISTS ${NAMED_POLICY_TABLE} (table_name TEXT NOT NULL, name TEXT NOT NULL, kind TEXT NOT NULL DEFAULT 'permissive', command TEXT NOT NULL DEFAULT 'all', roles TEXT NOT NULL DEFAULT 'public', using_expr TEXT, check_expr TEXT, owner_column TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')), PRIMARY KEY (table_name, name))`;
@@ -25077,11 +25087,11 @@ function policiesOn(policies, table) {
25077
25087
  function foldPolicyName(name, quoted3) {
25078
25088
  return quoted3 ? name : asciiLower(name);
25079
25089
  }
25080
- function sqlStringLiteral(text2) {
25081
- return text2 === null ? "NULL" : quoteString(text2);
25090
+ function sqlStringLiteral(text3) {
25091
+ return text3 === null ? "NULL" : quoteString(text3);
25082
25092
  }
25083
- function policySqlTooLong(text2) {
25084
- return utf8ByteLength(text2) > MAX_POLICY_SQL_BYTES;
25093
+ function policySqlTooLong(text3) {
25094
+ return utf8ByteLength(text3) > MAX_POLICY_SQL_BYTES;
25085
25095
  }
25086
25096
 
25087
25097
  // ../../packages/data-core/src/query.ts
@@ -25171,11 +25181,11 @@ function readValue2(value, path, auth = false) {
25171
25181
  );
25172
25182
  return value;
25173
25183
  }
25174
- function longerThan(text2, max) {
25175
- if (text2.length <= max) return false;
25176
- if (text2.length > max * 2) return true;
25184
+ function longerThan(text3, max) {
25185
+ if (text3.length <= max) return false;
25186
+ if (text3.length > max * 2) return true;
25177
25187
  let count2 = 0;
25178
- for (const _ of text2) if (++count2 > max) return true;
25188
+ for (const _ of text3) if (++count2 > max) return true;
25179
25189
  return false;
25180
25190
  }
25181
25191
  function endsWithLoneEscape(pattern) {
@@ -25332,8 +25342,8 @@ function parseCondition(action, value) {
25332
25342
  }
25333
25343
  function conditionsTooLarge(texts) {
25334
25344
  let total = 0;
25335
- for (const text2 of texts)
25336
- if (typeof text2 === "string") total += utf8ByteLength(text2);
25345
+ for (const text3 of texts)
25346
+ if (typeof text3 === "string") total += utf8ByteLength(text3);
25337
25347
  return total > MAX_CONDITION_BYTES;
25338
25348
  }
25339
25349
  function isInvalidCondition(value) {
@@ -25419,14 +25429,14 @@ var POLICY_SQL = {
25419
25429
  */
25420
25430
  insertConverted: `INSERT OR IGNORE INTO _naro_policies_v2 (table_name, name, kind, command, roles, using_expr, check_expr, owner_column) SELECT ?, ?, ?, ?, ?, ?, ?, ? WHERE EXISTS (SELECT 1 FROM _naro_policies WHERE ${ROW_AS_READ})`
25421
25431
  };
25422
- function readStoredCondition(action, text2, tooLarge) {
25423
- if (text2 === void 0 || text2 === null) return "is missing";
25424
- if (typeof text2 !== "string") return "is not JSON";
25432
+ function readStoredCondition(action, text3, tooLarge) {
25433
+ if (text3 === void 0 || text3 === null) return "is missing";
25434
+ if (typeof text3 !== "string") return "is not JSON";
25425
25435
  if (tooLarge)
25426
25436
  return `the conditions of the policy are larger than ${String(MAX_CONDITION_BYTES)} bytes`;
25427
25437
  let value;
25428
25438
  try {
25429
- value = JSON.parse(text2);
25439
+ value = JSON.parse(text3);
25430
25440
  } catch {
25431
25441
  return "is not JSON";
25432
25442
  }
@@ -25441,7 +25451,7 @@ function policyFromRow(row, log2) {
25441
25451
  (action) => row[`${action}_rule`] === CONDITION_RULE ? row[`${action}_condition`] : void 0
25442
25452
  );
25443
25453
  const tooLarge = conditionsTooLarge(
25444
- texts.filter((text2) => typeof text2 === "string")
25454
+ texts.filter((text3) => typeof text3 === "string")
25445
25455
  );
25446
25456
  const read = POLICY_ACTIONS2.map(
25447
25457
  (action, index) => {
@@ -26619,13 +26629,13 @@ function boundBytes(value) {
26619
26629
  return typeof value === "string" ? utf8ByteLength(value) : 8;
26620
26630
  }
26621
26631
  function captureGuard(table, where, params, nonce, set2) {
26622
- const bytes = balancedSum(
26632
+ const bytes2 = balancedSum(
26623
26633
  table.columns.map(
26624
26634
  (item) => set2.has(item.name) ? String(boundBytes(set2.get(item.name) ?? null)) : `coalesce(length(CAST(${qualifiedColumn(table.name, item.name)} AS BLOB)), 8)`
26625
26635
  )
26626
26636
  );
26627
26637
  return statement(
26628
- `SELECT CASE WHEN n > ${String(MAX_CAPTURE_ROWS)} OR b > ${String(MAX_CAPTURE_BYTES)} THEN ${captureMarker(nonce)} ELSE 1 END AS ok FROM (SELECT count(*) AS n, coalesce(sum(r), 0) AS b FROM (SELECT ${bytes} AS r FROM ${quoteIdentifier(table.name)}${where} LIMIT ${String(MAX_CAPTURE_ROWS + 1)}))`,
26638
+ `SELECT CASE WHEN n > ${String(MAX_CAPTURE_ROWS)} OR b > ${String(MAX_CAPTURE_BYTES)} THEN ${captureMarker(nonce)} ELSE 1 END AS ok FROM (SELECT count(*) AS n, coalesce(sum(r), 0) AS b FROM (SELECT ${bytes2} AS r FROM ${quoteIdentifier(table.name)}${where} LIMIT ${String(MAX_CAPTURE_ROWS + 1)}))`,
26629
26639
  params
26630
26640
  );
26631
26641
  }
@@ -27280,18 +27290,18 @@ var Rls = class {
27280
27290
  }),
27281
27291
  `they bind ${String(count2)}`
27282
27292
  );
27283
- const bytes = parts.reduce(
27293
+ const bytes2 = parts.reduce(
27284
27294
  (sum, part) => sum + utf8ByteLength(part.sql),
27285
27295
  0
27286
27296
  );
27287
- if (bytes > MAX_POLICY_STATEMENT_BYTES)
27297
+ if (bytes2 > MAX_POLICY_STATEMENT_BYTES)
27288
27298
  fail(
27289
27299
  dataError("POLICY_INVALID", {
27290
27300
  action: "select",
27291
27301
  table: this.policyTable,
27292
27302
  bytes: true
27293
27303
  }),
27294
- `they write ${String(bytes)}`
27304
+ `they write ${String(bytes2)}`
27295
27305
  );
27296
27306
  }
27297
27307
  };
@@ -27980,11 +27990,11 @@ function tokenize3(sql) {
27980
27990
  at = closing("'") + 1;
27981
27991
  tokens.push({ kind: "literal" });
27982
27992
  } else if (isDigit2(code) || code === 46 && isDigit2(next)) {
27983
- const text2 = NUMBER2.exec(sql.slice(at, at + 64))?.[0] || sql[at] || "";
27993
+ const text3 = NUMBER2.exec(sql.slice(at, at + 64))?.[0] || sql[at] || "";
27984
27994
  tokens.push(
27985
- /^[0-9]+$/.test(text2) ? { kind: "literal", integer: Number(text2) } : { kind: "literal" }
27995
+ /^[0-9]+$/.test(text3) ? { kind: "literal", integer: Number(text3) } : { kind: "literal" }
27986
27996
  );
27987
- at += text2.length;
27997
+ at += text3.length;
27988
27998
  } else if (code === 63 || code === 58 || code === 64 || code === 36) {
27989
27999
  at++;
27990
28000
  while (at < length && isWordPart(sql.charCodeAt(at))) at++;
@@ -27992,8 +28002,8 @@ function tokenize3(sql) {
27992
28002
  } else if (isWordStart(code)) {
27993
28003
  const start = at;
27994
28004
  while (at < length && isWordPart(sql.charCodeAt(at))) at++;
27995
- const text2 = sql.slice(start, at);
27996
- tokens.push({ kind: "word", text: text2, upper: text2.toUpperCase() });
28005
+ const text3 = sql.slice(start, at);
28006
+ tokens.push({ kind: "word", text: text3, upper: text3.toUpperCase() });
27997
28007
  } else if (sql.startsWith("->>", at)) {
27998
28008
  tokens.push({ kind: "op", text: "->>" });
27999
28009
  at += 3;
@@ -28703,31 +28713,31 @@ function isWordStart2(char) {
28703
28713
  function isWordPart2(char) {
28704
28714
  return /[A-Za-z0-9_$]/.test(char) || char.charCodeAt(0) >= 128;
28705
28715
  }
28706
- function skipBlanks(text2, from) {
28716
+ function skipBlanks(text3, from) {
28707
28717
  let index = from;
28708
28718
  for (; ; ) {
28709
- const char = text2.charAt(index);
28719
+ const char = text3.charAt(index);
28710
28720
  if (isBlankStart(char)) {
28711
28721
  index++;
28712
- while (index < text2.length && isBlank(text2.charAt(index))) index++;
28713
- } else if (text2.charCodeAt(index) === BOM2) index++;
28714
- else if (char === "-" && text2.charAt(index + 1) === "-") {
28715
- const end = text2.indexOf("\n", index + 2);
28716
- index = end < 0 ? text2.length : end;
28717
- } else if (char === "/" && text2.charAt(index + 1) === "*") {
28718
- const end = text2.indexOf("*/", index + 2);
28719
- index = end < 0 ? text2.length : end + 2;
28722
+ while (index < text3.length && isBlank(text3.charAt(index))) index++;
28723
+ } else if (text3.charCodeAt(index) === BOM2) index++;
28724
+ else if (char === "-" && text3.charAt(index + 1) === "-") {
28725
+ const end = text3.indexOf("\n", index + 2);
28726
+ index = end < 0 ? text3.length : end;
28727
+ } else if (char === "/" && text3.charAt(index + 1) === "*") {
28728
+ const end = text3.indexOf("*/", index + 2);
28729
+ index = end < 0 ? text3.length : end + 2;
28720
28730
  } else return index;
28721
28731
  }
28722
28732
  }
28723
- function readQuoted(text2, start, delimiter) {
28733
+ function readQuoted(text3, start, delimiter) {
28724
28734
  let value = "";
28725
28735
  let index = start + 1;
28726
28736
  for (; ; ) {
28727
- const close = text2.indexOf(delimiter, index);
28737
+ const close = text3.indexOf(delimiter, index);
28728
28738
  if (close < 0) return void 0;
28729
- value += text2.slice(index, close);
28730
- if (text2.charAt(close + 1) === delimiter) {
28739
+ value += text3.slice(index, close);
28740
+ if (text3.charAt(close + 1) === delimiter) {
28731
28741
  value += delimiter;
28732
28742
  index = close + 2;
28733
28743
  continue;
@@ -28735,31 +28745,31 @@ function readQuoted(text2, start, delimiter) {
28735
28745
  return { text: value, end: close + 1 };
28736
28746
  }
28737
28747
  }
28738
- function headTokens(text2) {
28748
+ function headTokens(text3) {
28739
28749
  const tokens = [];
28740
28750
  let index = 0;
28741
28751
  while (tokens.length < HEAD_TOKENS) {
28742
- index = skipBlanks(text2, index);
28743
- const char = text2.charAt(index);
28744
- if (index >= text2.length) break;
28752
+ index = skipBlanks(text3, index);
28753
+ const char = text3.charAt(index);
28754
+ if (index >= text3.length) break;
28745
28755
  if (char === '"' || char === "`" || char === "'") {
28746
- const quoted3 = readQuoted(text2, index, char);
28756
+ const quoted3 = readQuoted(text3, index, char);
28747
28757
  if (!quoted3) break;
28748
28758
  tokens.push({ kind: "name", text: quoted3.text });
28749
28759
  index = quoted3.end;
28750
28760
  } else if (char === "[") {
28751
- const close = text2.indexOf("]", index + 1);
28761
+ const close = text3.indexOf("]", index + 1);
28752
28762
  if (close < 0) break;
28753
- tokens.push({ kind: "name", text: text2.slice(index + 1, close) });
28763
+ tokens.push({ kind: "name", text: text3.slice(index + 1, close) });
28754
28764
  index = close + 1;
28755
- } else if ((char === "x" || char === "X") && text2.charAt(index + 1) === "'") {
28765
+ } else if ((char === "x" || char === "X") && text3.charAt(index + 1) === "'") {
28756
28766
  break;
28757
28767
  } else if (isWordStart2(char)) {
28758
28768
  let end = index + 1;
28759
- while (end < text2.length && isWordPart2(text2.charAt(end))) end++;
28760
- tokens.push({ kind: "word", text: text2.slice(index, end) });
28769
+ while (end < text3.length && isWordPart2(text3.charAt(end))) end++;
28770
+ tokens.push({ kind: "word", text: text3.slice(index, end) });
28761
28771
  index = end;
28762
- } else if (char === "." && !/[0-9]/.test(text2.charAt(index + 1))) {
28772
+ } else if (char === "." && !/[0-9]/.test(text3.charAt(index + 1))) {
28763
28773
  tokens.push({ kind: "dot" });
28764
28774
  index++;
28765
28775
  } else break;
@@ -28899,10 +28909,10 @@ function readAlter(head) {
28899
28909
  return { kind: "rls" };
28900
28910
  return sqlite.ok ? OTHER : sqlite.head;
28901
28911
  }
28902
- function readSqlHead(text2) {
28903
- if (text2.includes("\0"))
28912
+ function readSqlHead(text3) {
28913
+ if (text3.includes("\0"))
28904
28914
  return { kind: "unreadable", reason: "the statement has a NUL character" };
28905
- const head = new Head(headTokens(text2));
28915
+ const head = new Head(headTokens(text3));
28906
28916
  if (head.is(0, "create")) return readCreate(head);
28907
28917
  if (head.is(0, "drop")) return readDrop(head);
28908
28918
  if (head.is(0, "alter")) return readAlter(head);
@@ -29423,15 +29433,15 @@ function storageStatementProblem(statement2, action) {
29423
29433
  }),
29424
29434
  reason: `the ${STORAGE_OBJECTS} policies need more than ${String(STORAGE_STATEMENT_PARAM_LIMIT)} values in one statement`
29425
29435
  };
29426
- const bytes = utf8ByteLength(statement2.sql);
29427
- if (bytes > STORAGE_STATEMENT_BYTE_LIMIT)
29436
+ const bytes2 = utf8ByteLength(statement2.sql);
29437
+ if (bytes2 > STORAGE_STATEMENT_BYTE_LIMIT)
29428
29438
  return {
29429
29439
  error: dataError("POLICY_INVALID", {
29430
29440
  action,
29431
29441
  table: STORAGE_OBJECTS,
29432
29442
  bytes: STORAGE_STATEMENT_BYTE_LIMIT
29433
29443
  }),
29434
- reason: `the ${STORAGE_OBJECTS} policies make one statement ${String(bytes)} bytes long, more than ${String(STORAGE_STATEMENT_BYTE_LIMIT)}`
29444
+ reason: `the ${STORAGE_OBJECTS} policies make one statement ${String(bytes2)} bytes long, more than ${String(STORAGE_STATEMENT_BYTE_LIMIT)}`
29435
29445
  };
29436
29446
  return void 0;
29437
29447
  }
@@ -29704,8 +29714,8 @@ function budgetProblem(fragment, action) {
29704
29714
  }),
29705
29715
  reason: `the ${STORAGE_OBJECTS} policies need more than ${String(STORAGE_STATEMENT_PARAM_LIMIT)} values in one statement`
29706
29716
  };
29707
- const bytes = utf8ByteLength(fragment.sql);
29708
- if (bytes > MAX_POLICY_STATEMENT_BYTES)
29717
+ const bytes2 = utf8ByteLength(fragment.sql);
29718
+ if (bytes2 > MAX_POLICY_STATEMENT_BYTES)
29709
29719
  return {
29710
29720
  ok: false,
29711
29721
  error: dataError("POLICY_INVALID", {
@@ -29713,7 +29723,7 @@ function budgetProblem(fragment, action) {
29713
29723
  table: STORAGE_OBJECTS,
29714
29724
  bytes: true
29715
29725
  }),
29716
- reason: `they write ${String(bytes)}`
29726
+ reason: `they write ${String(bytes2)}`
29717
29727
  };
29718
29728
  return void 0;
29719
29729
  }
@@ -29867,7 +29877,7 @@ function depthContexts(contexts, claims) {
29867
29877
  function readsClaims(policies) {
29868
29878
  return policies.some(
29869
29879
  (policy) => [policy.using, policy.check].some(
29870
- (text2) => text2 !== null && /auth\s*\.\s*jwt\s*\(/i.test(text2)
29880
+ (text3) => text3 !== null && /auth\s*\.\s*jwt\s*\(/i.test(text3)
29871
29881
  )
29872
29882
  );
29873
29883
  }
@@ -30497,15 +30507,15 @@ function readEnd(stream) {
30497
30507
  rest.position
30498
30508
  );
30499
30509
  }
30500
- function parsePolicyStatement(text2) {
30501
- if (policySqlTooLong(text2))
30510
+ function parsePolicyStatement(text3) {
30511
+ if (policySqlTooLong(text3))
30502
30512
  return {
30503
30513
  ok: false,
30504
30514
  reason: `the statement is longer than ${String(MAX_POLICY_SQL_BYTES)} bytes`,
30505
30515
  position: 1
30506
30516
  };
30507
30517
  try {
30508
- const stream = new TokenStream(tokenize2(text2));
30518
+ const stream = new TokenStream(tokenize2(text3));
30509
30519
  const start = stream.next();
30510
30520
  let statement2;
30511
30521
  if (isKeyword(start, "create")) statement2 = readCreate2(stream, start);
@@ -30529,10 +30539,10 @@ function parsePolicyStatement(text2) {
30529
30539
  throw error51;
30530
30540
  }
30531
30541
  }
30532
- function splitPolicyStatements(text2) {
30542
+ function splitPolicyStatements(text3) {
30533
30543
  let tokens;
30534
30544
  try {
30535
- tokens = tokenize2(text2);
30545
+ tokens = tokenize2(text3);
30536
30546
  } catch (error51) {
30537
30547
  if (error51 instanceof PolicySyntaxError)
30538
30548
  return { ok: false, reason: error51.reason, position: error51.position };
@@ -30544,20 +30554,20 @@ function splitPolicyStatements(text2) {
30544
30554
  if (token.kind === "eof") break;
30545
30555
  start ??= token.position - 1;
30546
30556
  if (token.kind === "op" && token.value === ";") {
30547
- statements.push(text2.slice(start, token.position).trim());
30557
+ statements.push(text3.slice(start, token.position).trim());
30548
30558
  start = void 0;
30549
30559
  }
30550
30560
  }
30551
30561
  if (start !== void 0) {
30552
- const last = text2.slice(start).trim();
30562
+ const last = text3.slice(start).trim();
30553
30563
  if (last !== "") statements.push(last);
30554
30564
  }
30555
30565
  return { ok: true, statements };
30556
30566
  }
30557
30567
  var OWNER_PREFIX = "naro:owner";
30558
- function ownerComment(text2, position) {
30559
- if (!text2.startsWith(OWNER_PREFIX)) return void 0;
30560
- const rest = text2.slice(OWNER_PREFIX.length);
30568
+ function ownerComment(text3, position) {
30569
+ if (!text3.startsWith(OWNER_PREFIX)) return void 0;
30570
+ const rest = text3.slice(OWNER_PREFIX.length);
30561
30571
  if (rest !== "" && !/^[ \t]/.test(rest)) return void 0;
30562
30572
  let column2 = rest.replace(/^[ \t]+|[ \t]+$/g, "");
30563
30573
  if (column2.startsWith('"')) {
@@ -30613,22 +30623,22 @@ function readRowLevelSecurity(stream) {
30613
30623
  stream.expectKeyword("security");
30614
30624
  return { kind: "rls", table, action };
30615
30625
  }
30616
- function parseMigrationPolicyStatement(text2) {
30617
- if (policySqlTooLong(text2))
30626
+ function parseMigrationPolicyStatement(text3) {
30627
+ if (policySqlTooLong(text3))
30618
30628
  return {
30619
30629
  ok: false,
30620
30630
  reason: `the statement is longer than ${String(MAX_POLICY_SQL_BYTES)} bytes`,
30621
30631
  position: 1
30622
30632
  };
30623
30633
  try {
30624
- const stream = new TokenStream(tokenize2(text2));
30634
+ const stream = new TokenStream(tokenize2(text3));
30625
30635
  let statement2;
30626
30636
  if (stream.acceptKeyword("comment")) statement2 = readComment(stream);
30627
30637
  else if (isKeyword(stream.peek(), "alter") && isKeyword(stream.peek(1), "table")) {
30628
30638
  stream.next();
30629
30639
  stream.next();
30630
30640
  statement2 = readRowLevelSecurity(stream);
30631
- } else return parsePolicyStatement(text2);
30641
+ } else return parsePolicyStatement(text3);
30632
30642
  readEnd(stream);
30633
30643
  return { ok: true, statement: statement2 };
30634
30644
  } catch (error51) {
@@ -30814,17 +30824,17 @@ function tablesChanged(head) {
30814
30824
  }
30815
30825
  }
30816
30826
  function readsBareSubqueryColumn(policy) {
30817
- return [policy.using, policy.check].some((text2) => {
30818
- if (text2 === null) return false;
30819
- const parsed = parseExpression(text2);
30827
+ return [policy.using, policy.check].some((text3) => {
30828
+ if (text3 === null) return false;
30829
+ const parsed = parseExpression(text3);
30820
30830
  return parsed.ok && unqualifiedInSubquery(parsed.expr) !== void 0;
30821
30831
  });
30822
30832
  }
30823
30833
  function tablesInScope(policy) {
30824
30834
  const tables = /* @__PURE__ */ new Set([asciiLower(policy.table)]);
30825
- for (const text2 of [policy.using, policy.check]) {
30826
- if (text2 === null) continue;
30827
- const parsed = parseExpression(text2);
30835
+ for (const text3 of [policy.using, policy.check]) {
30836
+ if (text3 === null) continue;
30837
+ const parsed = parseExpression(text3);
30828
30838
  if (!parsed.ok) continue;
30829
30839
  for (const subquery of subqueriesOf(parsed.expr))
30830
30840
  tables.add(asciiLower(subquery.table));
@@ -30832,9 +30842,9 @@ function tablesInScope(policy) {
30832
30842
  return tables;
30833
30843
  }
30834
30844
  function readsStorageObjects(policy) {
30835
- return [policy.using, policy.check].some((text2) => {
30836
- if (text2 === null) return false;
30837
- const parsed = parseExpression(text2);
30845
+ return [policy.using, policy.check].some((text3) => {
30846
+ if (text3 === null) return false;
30847
+ const parsed = parseExpression(text3);
30838
30848
  return parsed.ok && subqueriesOf(parsed.expr).some(
30839
30849
  (subquery) => isStorageObjects(subquery.table)
30840
30850
  );
@@ -30846,54 +30856,54 @@ function planPolicyMigration(statements) {
30846
30856
  let hasPolicyStatements = false;
30847
30857
  let touchesTables = false;
30848
30858
  let renamesColumns = false;
30849
- const heads = statements.map((text2) => readSqlHead(text2));
30859
+ const heads = statements.map((text3) => readSqlHead(text3));
30850
30860
  const changes = heads.map(tablesChanged);
30851
30861
  const changedAfter = (index, tables) => changes.slice(index + 1).some(
30852
30862
  (changed) => changed === "any" || changed.some((table) => tables.has(table))
30853
30863
  );
30854
- for (const [index, text2] of statements.entries()) {
30855
- const refuse2 = (message) => ({
30864
+ for (const [index, text3] of statements.entries()) {
30865
+ const refuse3 = (message) => ({
30856
30866
  ok: false,
30857
30867
  index,
30858
30868
  message: `Statement ${String(index + 1)} of ${String(count2)}: ${message}`
30859
30869
  });
30860
- const head = heads[index] ?? readSqlHead(text2);
30870
+ const head = heads[index] ?? readSqlHead(text3);
30861
30871
  switch (head.kind) {
30862
30872
  case "grant":
30863
30873
  case "revoke":
30864
- return refuse2(GRANT_REFUSAL);
30874
+ return refuse3(GRANT_REFUSAL);
30865
30875
  case "unreadable":
30866
- return refuse2(`${head.reason}.`);
30876
+ return refuse3(`${head.reason}.`);
30867
30877
  case "create-table":
30868
30878
  case "drop-table":
30869
30879
  case "rename-table":
30870
30880
  touchesTables = true;
30871
- planned.push({ kind: "verbatim", text: text2, head });
30881
+ planned.push({ kind: "verbatim", text: text3, head });
30872
30882
  continue;
30873
30883
  case "rename-column":
30874
30884
  renamesColumns = true;
30875
- planned.push({ kind: "verbatim", text: text2, head });
30885
+ planned.push({ kind: "verbatim", text: text3, head });
30876
30886
  continue;
30877
30887
  case "alter-table":
30878
30888
  case "other":
30879
- planned.push({ kind: "verbatim", text: text2, head });
30889
+ planned.push({ kind: "verbatim", text: text3, head });
30880
30890
  continue;
30881
30891
  default:
30882
30892
  break;
30883
30893
  }
30884
- const parsed = parseMigrationPolicyStatement(text2);
30894
+ const parsed = parseMigrationPolicyStatement(text3);
30885
30895
  if (!parsed.ok)
30886
- return refuse2(
30896
+ return refuse3(
30887
30897
  `${parsed.reason} at character ${String(parsed.position)}.`
30888
30898
  );
30889
30899
  const statement2 = parsed.statement;
30890
30900
  const table = statement2.kind === "create" ? statement2.policy.table : statement2.table;
30891
30901
  if (!isStorageObjects(table) && isSystemTable(table))
30892
- return refuse2(`${relationMissing(table)}.`);
30902
+ return refuse3(`${relationMissing(table)}.`);
30893
30903
  switch (statement2.kind) {
30894
30904
  case "create":
30895
30905
  if (readsBareSubqueryColumn(statement2.policy) && changedAfter(index, tablesInScope(statement2.policy)))
30896
- return refuse2(LATER_TABLE_CHANGE);
30906
+ return refuse3(LATER_TABLE_CHANGE);
30897
30907
  hasPolicyStatements = true;
30898
30908
  planned.push({ kind: "create-policy", policy: statement2.policy });
30899
30909
  break;
@@ -30921,7 +30931,7 @@ function planPolicyMigration(statements) {
30921
30931
  break;
30922
30932
  case "rls":
30923
30933
  if (statement2.action === "disable")
30924
- return refuse2(disableRefusal(table));
30934
+ return refuse3(disableRefusal(table));
30925
30935
  planned.push({ kind: "noop" });
30926
30936
  break;
30927
30937
  }
@@ -31001,19 +31011,19 @@ var TYPED_PATH = /^[a-z][a-z0-9+.-]*:\/\/[^/]*(\/.*)?$/i;
31001
31011
  var SEGMENT = /^[A-Za-z0-9._~-]+$/;
31002
31012
  function parseRedirectEntry(value) {
31003
31013
  if (typeof value !== "string") return null;
31004
- const text2 = value.trim();
31005
- if (text2 === "" || text2.length > MAX_ENTRY_LENGTH) return null;
31006
- if (/[\s?#*%\\]/.test(text2)) return null;
31014
+ const text3 = value.trim();
31015
+ if (text3 === "" || text3.length > MAX_ENTRY_LENGTH) return null;
31016
+ if (/[\s?#*%\\]/.test(text3)) return null;
31007
31017
  let url2;
31008
31018
  try {
31009
- url2 = new URL(text2);
31019
+ url2 = new URL(text3);
31010
31020
  } catch {
31011
31021
  return null;
31012
31022
  }
31013
31023
  if (url2.username !== "" || url2.password !== "") return null;
31014
31024
  if (url2.search !== "" || url2.hash !== "") return null;
31015
31025
  if (!isSecureOrLoopback(url2)) return null;
31016
- const typed = TYPED_PATH.exec(text2)?.[1] ?? "/";
31026
+ const typed = TYPED_PATH.exec(text3)?.[1] ?? "/";
31017
31027
  if (typed !== url2.pathname) return null;
31018
31028
  const path = url2.pathname;
31019
31029
  if (path !== "/") {
@@ -31535,13 +31545,13 @@ function listMigrationFiles(dir) {
31535
31545
  );
31536
31546
  }
31537
31547
  function nextMigrationFileName(existing, name) {
31538
- const normalized = normalizeMigrationName(name);
31539
- if (normalized === "")
31548
+ const normalized2 = normalizeMigrationName(name);
31549
+ if (normalized2 === "")
31540
31550
  throw new NaroError(
31541
31551
  "VALIDATION_FAILED",
31542
31552
  "Migration name must contain letters or digits."
31543
31553
  );
31544
- return numberedMigrationName(existing, normalized);
31554
+ return numberedMigrationName(existing, normalized2);
31545
31555
  }
31546
31556
  function compareMigrations(local, applied) {
31547
31557
  const ledger = new Map(applied.map((row) => [row.name, row]));
@@ -32042,10 +32052,10 @@ var SUPPORTED_REMOTE = [
32042
32052
  /^ssh:\/\/[^\s]+$/,
32043
32053
  /^git@[A-Za-z0-9.-]+:[A-Za-z0-9._/-]+(\.git)?$/
32044
32054
  ];
32045
- var defaultExec = (args, cwd) => new Promise((resolve12, reject) => {
32055
+ var defaultExec = (args, cwd) => new Promise((resolve15, reject) => {
32046
32056
  execFile2("git", args, { cwd }, (error51, stdout) => {
32047
32057
  if (error51) reject(error51);
32048
- else resolve12(stdout);
32058
+ else resolve15(stdout);
32049
32059
  });
32050
32060
  });
32051
32061
  async function tryExec(exec, args, cwd) {
@@ -32194,6 +32204,24 @@ async function uploadArtifact(artifact, opts) {
32194
32204
  };
32195
32205
  }
32196
32206
 
32207
+ // src/version.ts
32208
+ import { readFileSync as readFileSync6 } from "fs";
32209
+ import { dirname as dirname5, join as join25 } from "path";
32210
+ import { fileURLToPath } from "url";
32211
+ function version2() {
32212
+ try {
32213
+ const pkg = JSON.parse(
32214
+ readFileSync6(
32215
+ join25(dirname5(fileURLToPath(import.meta.url)), "..", "package.json"),
32216
+ "utf8"
32217
+ )
32218
+ );
32219
+ return pkg.version ?? "unknown";
32220
+ } catch {
32221
+ return "unknown";
32222
+ }
32223
+ }
32224
+
32197
32225
  // src/working-tree.ts
32198
32226
  import { execFile as execFile3 } from "child_process";
32199
32227
  import {
@@ -32211,9 +32239,9 @@ import {
32211
32239
  } from "fs/promises";
32212
32240
  import {
32213
32241
  basename as basename3,
32214
- dirname as dirname5,
32242
+ dirname as dirname6,
32215
32243
  isAbsolute as isAbsolute4,
32216
- join as join25,
32244
+ join as join26,
32217
32245
  relative as relative6,
32218
32246
  resolve as resolve10,
32219
32247
  sep as sep5
@@ -32252,15 +32280,15 @@ async function committedEnvFiles(sourceDir) {
32252
32280
  return [];
32253
32281
  });
32254
32282
  }
32255
- async function staysInside(link, text2, root) {
32283
+ async function staysInside(link, text3, root) {
32256
32284
  try {
32257
32285
  return inside(await realpath3(link), root);
32258
32286
  } catch (error51) {
32259
- return error51.code === "ENOENT" && !text2.split(/[\\/]/).includes("..");
32287
+ return error51.code === "ENOENT" && !text3.split(/[\\/]/).includes("..");
32260
32288
  }
32261
32289
  }
32262
- function climbsOnlyFirst(text2) {
32263
- const segments = text2.split(/[\\/]/).filter((s) => s !== "" && s !== ".");
32290
+ function climbsOnlyFirst(text3) {
32291
+ const segments = text3.split(/[\\/]/).filter((s) => s !== "" && s !== ".");
32264
32292
  const down = segments.findIndex((segment) => segment !== "..");
32265
32293
  return down < 0 || !segments.slice(down).includes("..");
32266
32294
  }
@@ -32280,11 +32308,11 @@ async function readLocal(path) {
32280
32308
  return readFile14(path).catch(() => null);
32281
32309
  }
32282
32310
  async function realAncestor(dir) {
32283
- for (let current = dir; ; current = dirname5(current)) {
32311
+ for (let current = dir; ; current = dirname6(current)) {
32284
32312
  try {
32285
32313
  return await realpath3(current);
32286
32314
  } catch {
32287
- if (dirname5(current) === current)
32315
+ if (dirname6(current) === current)
32288
32316
  throw new Error(`No ancestor of ${dir}`);
32289
32317
  }
32290
32318
  }
@@ -32322,7 +32350,7 @@ async function copyWorkingTree(source, checkout) {
32322
32350
  absoluteLinks.push(path);
32323
32351
  return false;
32324
32352
  }
32325
- if (!inside(resolve10(dirname5(src), target2), sourceDir)) {
32353
+ if (!inside(resolve10(dirname6(src), target2), sourceDir)) {
32326
32354
  linksOutside.push(path);
32327
32355
  return false;
32328
32356
  }
@@ -32338,14 +32366,14 @@ async function copyWorkingTree(source, checkout) {
32338
32366
  const root = await realpath3(checkout);
32339
32367
  const strays = await keptOnly(
32340
32368
  keptLinks,
32341
- async ({ path, text: text2 }) => {
32369
+ async ({ path, text: text3 }) => {
32342
32370
  try {
32343
- return inside(await realpath3(join25(checkout, path)), root);
32371
+ return inside(await realpath3(join26(checkout, path)), root);
32344
32372
  } catch (error51) {
32345
- return error51.code === "ENOENT" && climbsOnlyFirst(text2);
32373
+ return error51.code === "ENOENT" && climbsOnlyFirst(text3);
32346
32374
  }
32347
32375
  },
32348
- ({ path }) => unlink(join25(checkout, path))
32376
+ ({ path }) => unlink(join26(checkout, path))
32349
32377
  );
32350
32378
  linksElsewhere.push(...strays.map(({ path }) => path));
32351
32379
  const committed = await committedEnvFiles(sourceDir);
@@ -32359,13 +32387,13 @@ async function copyWorkingTree(source, checkout) {
32359
32387
  outsideProject.push(path);
32360
32388
  continue;
32361
32389
  }
32362
- const target2 = join25(checkout, path);
32363
- if (!inside(await realAncestor(dirname5(target2)), root)) {
32390
+ const target2 = join26(checkout, path);
32391
+ if (!inside(await realAncestor(dirname6(target2)), root)) {
32364
32392
  outsideProject.push(path);
32365
32393
  continue;
32366
32394
  }
32367
32395
  try {
32368
- await mkdir3(dirname5(target2), { recursive: true });
32396
+ await mkdir3(dirname6(target2), { recursive: true });
32369
32397
  } catch {
32370
32398
  outsideProject.push(path);
32371
32399
  continue;
@@ -32374,7 +32402,7 @@ async function copyWorkingTree(source, checkout) {
32374
32402
  const content = await git(sourceDir, ["show", `HEAD:./${path}`]);
32375
32403
  if (isLink) {
32376
32404
  const linkTarget = content.toString("utf8");
32377
- const pointsAt = resolve10(dirname5(target2), linkTarget);
32405
+ const pointsAt = resolve10(dirname6(target2), linkTarget);
32378
32406
  if (isAbsolute4(linkTarget) || !inside(pointsAt, checkout)) {
32379
32407
  outsideProject.push(path);
32380
32408
  continue;
@@ -32384,16 +32412,16 @@ async function copyWorkingTree(source, checkout) {
32384
32412
  continue;
32385
32413
  }
32386
32414
  await writeFile7(target2, content, { flag: "wx" });
32387
- const local = await readLocal(join25(sourceDir, path));
32415
+ const local = await readLocal(join26(sourceDir, path));
32388
32416
  if (!local || !sameText(local, content)) committedVersion.push(path);
32389
32417
  }
32390
32418
  const envStrays = await keptOnly(
32391
32419
  envLinks,
32392
32420
  async (path) => {
32393
- const real = await realpath3(join25(checkout, path)).catch(() => null);
32421
+ const real = await realpath3(join26(checkout, path)).catch(() => null);
32394
32422
  return real !== null && inside(real, root);
32395
32423
  },
32396
- (path) => unlink(join25(checkout, path))
32424
+ (path) => unlink(join26(checkout, path))
32397
32425
  );
32398
32426
  outsideProject.push(...envStrays);
32399
32427
  const inCommit = new Set(
@@ -32413,9 +32441,1776 @@ async function copyWorkingTree(source, checkout) {
32413
32441
  };
32414
32442
  }
32415
32443
 
32444
+ // src/functions/deploy.ts
32445
+ import { relative as relative11, resolve as resolve13, sep as sep10 } from "path";
32446
+
32447
+ // ../../packages/functions-bundler/src/errors.ts
32448
+ var FunctionBundleError = class extends Error {
32449
+ code;
32450
+ constructor(code, message, options) {
32451
+ super(message, options);
32452
+ this.name = "FunctionBundleError";
32453
+ this.code = code;
32454
+ }
32455
+ };
32456
+ var NAME_RULE = "names are 1\u201364 characters of lowercase letters, digits, - and _, starting with a letter";
32457
+ var JSR_REGISTRY = '"@jsr:registry=https://npm.jsr.io"';
32458
+ var bytes = (n) => n.toLocaleString("en-US");
32459
+ var SHELL_SAFE = /^[A-Za-z0-9@/._^=+:-]+$/;
32460
+ var shellArg = (spec) => SHELL_SAFE.test(spec) ? spec : `'${spec.replaceAll("'", "'\\''")}'`;
32461
+ var BUNDLE_MESSAGES = {
32462
+ noDir: (dir) => `There is no ${dir} folder here. Create a function with naro functions new <name>.`,
32463
+ supabaseFound: "Found supabase/functions. Deploy it with --dir supabase/functions.",
32464
+ noFunctions: (dir) => `No functions in ${dir}. Create one with naro functions new <name>.`,
32465
+ badName: (name) => `Function folder ${name} is not a valid function name: ${NAME_RULE}.`,
32466
+ noFolder: (name, dir) => `Function ${name} has no folder: ${dir}/${name} does not exist.`,
32467
+ jsonInvalid: (name) => `function.json of ${name} is not valid JSON.`,
32468
+ jsonKeys: (name, keys) => `function.json of ${name} has keys Naro does not read: ${keys.join(", ")}. It takes verifyJwt and entrypoint.`,
32469
+ jsonVerifyJwt: (name) => `verifyJwt in function.json of ${name} must be true or false.`,
32470
+ jsonEntrypoint: (name) => `entrypoint in function.json of ${name} must be a relative path inside the function folder.`,
32471
+ noEntry: (name, dir) => `Function ${name} has no entry file. Add ${dir}/${name}/index.ts (or set "entrypoint" in function.json).`,
32472
+ entryMissing: (name, entrypoint) => `Function ${name} has no ${entrypoint}, the entrypoint its function.json names.`,
32473
+ supabaseVerifyJwt: (dir) => `\u26A0 supabase/config.toml's verify_jwt is not read. Set "verifyJwt": false in ${dir}/<name>/function.json, or deploy with --no-verify-jwt.`,
32474
+ importMapMissing: (file2) => `--import-map ${file2} does not exist.`,
32475
+ importMapInvalid: (file2) => `${file2} is not valid JSON.`,
32476
+ importMapShape: (file2) => `The imports of ${file2} must map names to text.`,
32477
+ importMapPrefix: (file2, key, value) => `The imports of ${file2} map ${JSON.stringify(key)} to ${JSON.stringify(value)}: a key ending in / needs a value ending in / too.`,
32478
+ npmMissing: (spec, install, dir) => `npm:${spec} is not installed. Run npm install ${shellArg(install)} in ${dir}.`,
32479
+ jsrMissing: (spec, install) => `jsr:${spec} is not installed. Add ${JSR_REGISTRY} to .npmrc, then run npm install ${shellArg(install)}.`,
32480
+ missingMany: (specs, installs, jsr) => jsr ? `Missing packages: ${specs.join(", ")}. Add ${JSR_REGISTRY} to .npmrc, then install them with: npm install ${installs.map(shellArg).join(" ")}` : `Missing packages: ${specs.join(", ")}. Install them with: npm install ${installs.map(shellArg).join(" ")}`,
32481
+ noPackageName: (specifier, example) => `${specifier} names no package. Write it like ${example}.`,
32482
+ jsrNoScope: (spec) => `jsr:${spec} needs a scope, like jsr:@scope/${spec}.`,
32483
+ urlNpm: (url2, target2) => `URL imports are not supported: ${url2}. Use ${target2} instead.`,
32484
+ urlStd: (url2, module) => `URL imports are not supported: ${url2}. Use jsr:@std/${module} instead.`,
32485
+ urlOther: (url2) => `URL imports are not supported: ${url2}. Install the package from npm and import it by name.`,
32486
+ outOfRange: (pkg, version3, range, file2) => `\u26A0 ${pkg} is installed at ${version3}, outside the range ${range} that ${file2} asks for.`,
32487
+ wasm: (file2) => `WebAssembly modules are not supported in functions yet: ${file2}.`,
32488
+ naroJsMissing: 'Cannot find "naro-js/functions". Install naro-js 0.7.0 or later: npm install naro-js@latest.',
32489
+ tooLarge: (name, size, inputs) => `Function ${name} bundles to ${bytes(size)} bytes; the limit is 67,108,864 (64 MiB). The biggest inputs: ${inputs}.`,
32490
+ // Rounded up: a size over the limit never reads as the limit (10.0 MB).
32491
+ tooLargeCompressed: (name, size) => `Function ${name} is ${(Math.ceil(size / 1048576 * 10) / 10).toFixed(1)} MB after compression; Cloudflare accepts 10 MB.`,
32492
+ otherBundle: (name, text3, location2) => `Function ${name} did not bundle: ${text3}${location2 ? ` (${location2})` : ""}`,
32493
+ noHandler: (name) => `Function ${name} did not register a handler. Call Deno.serve(handler) or export default { fetch }.`,
32494
+ failedToStart: (name, line) => `Function ${name} failed to start: ${line}`,
32495
+ esbuildMissing: (name, cause) => `Function ${name} did not bundle: esbuild could not be loaded (${cause}). Reinstall naro-cli.`,
32496
+ miniflareMissing: (name, cause) => `Function ${name} could not be checked: miniflare could not be loaded (${cause}). Reinstall naro-cli, or skip the check with --skip-check (skipCheck: true in naro-mcp).`,
32497
+ bootTimeout: (name, ms) => `Function ${name} did not start within ${String(ms / 1e3)} seconds.`
32498
+ };
32499
+
32500
+ // ../../packages/functions-bundler/src/discover.ts
32501
+ import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
32502
+ import { join as join27, relative as relative7, resolve as resolve11, sep as sep6 } from "path";
32503
+
32504
+ // ../../packages/functions-bundler/src/limits.ts
32505
+ var FUNCTION_BUNDLE_MAX_BYTES = 67108864;
32506
+ var FUNCTION_COMPRESSED_BUNDLE_MAX_BYTES = 10485760;
32507
+ var ENTRY_FILES = [
32508
+ "index.ts",
32509
+ "index.js",
32510
+ "index.mjs",
32511
+ "index.tsx",
32512
+ "index.jsx"
32513
+ ];
32514
+
32515
+ // ../../packages/functions-bundler/src/discover.ts
32516
+ var SEGMENT2 = /^[A-Za-z0-9._@+-]+$/;
32517
+ function isEntrypoint(value) {
32518
+ if (value.length < 1 || value.length > 200) return false;
32519
+ return value.split("/").every(
32520
+ (segment) => segment !== "." && segment !== ".." && SEGMENT2.test(segment)
32521
+ );
32522
+ }
32523
+ function functionsFolder(options) {
32524
+ const root = resolve11(options.cwd, options.root ?? ".");
32525
+ const explicit = options.dir !== void 0;
32526
+ const dir = explicit ? resolve11(options.cwd, options.dir) : join27(root, "naro", "functions");
32527
+ const label2 = relative7(options.cwd, dir).split(sep6).join("/") || ".";
32528
+ return { dir, label: label2, root, explicit };
32529
+ }
32530
+ function listFunctionNames(folder) {
32531
+ let entries;
32532
+ try {
32533
+ entries = readdirSync3(folder.dir, { withFileTypes: true });
32534
+ } catch {
32535
+ if (!folder.explicit && existsSync7(join27(folder.root, "supabase", "functions")))
32536
+ throw new FunctionBundleError(
32537
+ "VALIDATION_FAILED",
32538
+ BUNDLE_MESSAGES.supabaseFound
32539
+ );
32540
+ throw new FunctionBundleError(
32541
+ "VALIDATION_FAILED",
32542
+ BUNDLE_MESSAGES.noDir(folder.label)
32543
+ );
32544
+ }
32545
+ const names = entries.filter(
32546
+ (entry) => entry.isDirectory() && !entry.name.startsWith("_") && !entry.name.startsWith(".") && entry.name !== "node_modules"
32547
+ ).map((entry) => entry.name).sort();
32548
+ if (names.length === 0)
32549
+ throw new FunctionBundleError(
32550
+ "VALIDATION_FAILED",
32551
+ BUNDLE_MESSAGES.noFunctions(folder.label)
32552
+ );
32553
+ return names;
32554
+ }
32555
+ function readFunctionJson(dir, name) {
32556
+ const file2 = join27(dir, "function.json");
32557
+ if (!existsSync7(file2)) return { verifyJwt: void 0, entrypoint: void 0 };
32558
+ let parsed;
32559
+ try {
32560
+ parsed = JSON.parse(readFileSync7(file2, "utf8"));
32561
+ } catch {
32562
+ throw new FunctionBundleError(
32563
+ "VALIDATION_FAILED",
32564
+ BUNDLE_MESSAGES.jsonInvalid(name)
32565
+ );
32566
+ }
32567
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
32568
+ throw new FunctionBundleError(
32569
+ "VALIDATION_FAILED",
32570
+ BUNDLE_MESSAGES.jsonInvalid(name)
32571
+ );
32572
+ const record3 = parsed;
32573
+ const unknown2 = Object.keys(record3).filter(
32574
+ (key) => key !== "verifyJwt" && key !== "entrypoint"
32575
+ );
32576
+ if (unknown2.length > 0)
32577
+ throw new FunctionBundleError(
32578
+ "VALIDATION_FAILED",
32579
+ BUNDLE_MESSAGES.jsonKeys(name, unknown2)
32580
+ );
32581
+ const { verifyJwt, entrypoint } = record3;
32582
+ if (verifyJwt !== void 0 && typeof verifyJwt !== "boolean")
32583
+ throw new FunctionBundleError(
32584
+ "VALIDATION_FAILED",
32585
+ BUNDLE_MESSAGES.jsonVerifyJwt(name)
32586
+ );
32587
+ if (entrypoint !== void 0 && (typeof entrypoint !== "string" || !isEntrypoint(entrypoint)))
32588
+ throw new FunctionBundleError(
32589
+ "VALIDATION_FAILED",
32590
+ BUNDLE_MESSAGES.jsonEntrypoint(name)
32591
+ );
32592
+ return { verifyJwt, entrypoint };
32593
+ }
32594
+ function readFunctionSource(folder, name) {
32595
+ if (!isFunctionName(name))
32596
+ throw new FunctionBundleError(
32597
+ "VALIDATION_FAILED",
32598
+ BUNDLE_MESSAGES.badName(name)
32599
+ );
32600
+ const dir = join27(folder.dir, name);
32601
+ if (!statSync2(dir, { throwIfNoEntry: false })?.isDirectory())
32602
+ throw new FunctionBundleError(
32603
+ "VALIDATION_FAILED",
32604
+ BUNDLE_MESSAGES.noFolder(name, folder.label)
32605
+ );
32606
+ const config2 = readFunctionJson(dir, name);
32607
+ let entrypoint;
32608
+ if (config2.entrypoint !== void 0) {
32609
+ if (!existsSync7(join27(dir, ...config2.entrypoint.split("/"))))
32610
+ throw new FunctionBundleError(
32611
+ "FUNCTION_BUNDLE_FAILED",
32612
+ BUNDLE_MESSAGES.entryMissing(name, config2.entrypoint)
32613
+ );
32614
+ entrypoint = config2.entrypoint;
32615
+ } else {
32616
+ const found = ENTRY_FILES.find((file2) => existsSync7(join27(dir, file2)));
32617
+ if (found === void 0)
32618
+ throw new FunctionBundleError(
32619
+ "FUNCTION_BUNDLE_FAILED",
32620
+ BUNDLE_MESSAGES.noEntry(name, folder.label)
32621
+ );
32622
+ entrypoint = found;
32623
+ }
32624
+ return {
32625
+ name,
32626
+ dir,
32627
+ entry: join27(dir, ...entrypoint.split("/")),
32628
+ entrypoint,
32629
+ verifyJwt: config2.verifyJwt
32630
+ };
32631
+ }
32632
+ function configTomlWarning(folder) {
32633
+ if (!folder.dir.endsWith(join27("supabase", "functions"))) return null;
32634
+ const file2 = join27(folder.dir, "..", "config.toml");
32635
+ if (!existsSync7(file2)) return null;
32636
+ return /^\s*verify_jwt\s*=/m.test(readFileSync7(file2, "utf8")) ? BUNDLE_MESSAGES.supabaseVerifyJwt(folder.label) : null;
32637
+ }
32638
+
32639
+ // ../../packages/functions-bundler/src/jsonc.ts
32640
+ function closesNext(text3, from) {
32641
+ let i = from;
32642
+ while (i < text3.length && /\s/.test(text3[i] ?? "")) i += 1;
32643
+ return text3[i] === "}" || text3[i] === "]";
32644
+ }
32645
+ function parseJsonc2(text3) {
32646
+ const uncommented = stripComments2(text3);
32647
+ let out = "";
32648
+ let inString = false;
32649
+ for (let i = 0; i < uncommented.length; i += 1) {
32650
+ const char = uncommented[i] ?? "";
32651
+ if (inString) {
32652
+ out += char;
32653
+ if (char === "\\") {
32654
+ out += uncommented[i + 1] ?? "";
32655
+ i += 1;
32656
+ } else if (char === '"') inString = false;
32657
+ continue;
32658
+ }
32659
+ if (char === '"') inString = true;
32660
+ if (char === "," && closesNext(uncommented, i + 1)) continue;
32661
+ out += char;
32662
+ }
32663
+ return JSON.parse(out);
32664
+ }
32665
+ function stripComments2(text3) {
32666
+ let out = "";
32667
+ let i = 0;
32668
+ let inString = false;
32669
+ while (i < text3.length) {
32670
+ const char = text3[i] ?? "";
32671
+ const next = text3[i + 1] ?? "";
32672
+ if (inString) {
32673
+ out += char;
32674
+ if (char === "\\") {
32675
+ out += next;
32676
+ i += 2;
32677
+ continue;
32678
+ }
32679
+ if (char === '"') inString = false;
32680
+ i += 1;
32681
+ continue;
32682
+ }
32683
+ if (char === '"') {
32684
+ inString = true;
32685
+ out += char;
32686
+ i += 1;
32687
+ continue;
32688
+ }
32689
+ if (char === "/" && next === "/") {
32690
+ while (i < text3.length && text3[i] !== "\n") i += 1;
32691
+ continue;
32692
+ }
32693
+ if (char === "/" && next === "*") {
32694
+ const end = text3.indexOf("*/", i + 2);
32695
+ i = end === -1 ? text3.length : end + 2;
32696
+ out += " ";
32697
+ continue;
32698
+ }
32699
+ out += char;
32700
+ i += 1;
32701
+ }
32702
+ return out;
32703
+ }
32704
+
32705
+ // ../../packages/functions-bundler/src/node-compat.ts
32706
+ import { createRequire as createRequire2 } from "module";
32707
+ import { dirname as dirname7, resolve as resolvePath } from "path";
32708
+ import { fileURLToPath as fileURLToPath2 } from "url";
32709
+ var require2 = createRequire2(import.meta.url);
32710
+ var MODULE_DIR = dirname7(fileURLToPath2(import.meta.url));
32711
+ var REQUIRED_NODE_BUILT_IN_NAMESPACE = "node-built-in-modules";
32712
+ var REQUIRED_UNENV_ALIAS_NAMESPACE = "required-unenv-alias";
32713
+ var SKIPPED_ALIASES = /* @__PURE__ */ new Set(["debug"]);
32714
+ async function nodeCompatEnvironment(options) {
32715
+ const { defineEnv } = await import("unenv");
32716
+ const { getCloudflarePreset } = await import("@cloudflare/unenv-preset");
32717
+ return defineEnv({
32718
+ presets: [
32719
+ getCloudflarePreset({
32720
+ compatibilityDate: options.compatibilityDate,
32721
+ compatibilityFlags: [...options.compatibilityFlags]
32722
+ })
32723
+ ],
32724
+ npmShims: true
32725
+ }).env;
32726
+ }
32727
+ function nodeCompatPlugin(options) {
32728
+ return {
32729
+ name: "hybrid-nodejs_compat",
32730
+ async setup(build) {
32731
+ const { nonPrefixedNodeModules } = await import("@cloudflare/unenv-preset");
32732
+ const { alias, inject, external, polyfill } = await nodeCompatEnvironment(options);
32733
+ const nodeJsModuleRegexp = new RegExp(
32734
+ `^(${nonPrefixedNodeModules.join("|")}|node:.+)$`
32735
+ );
32736
+ handleRequireCallsToNodeJSBuiltins(build, nodeJsModuleRegexp);
32737
+ handleUnenvAliasedPackages(build, alias, external);
32738
+ handleNodeJSGlobals(build, inject, polyfill, options.virtualBase);
32739
+ }
32740
+ };
32741
+ }
32742
+ function handleRequireCallsToNodeJSBuiltins(build, nodeJsModuleRegexp) {
32743
+ build.onResolve({ filter: nodeJsModuleRegexp }, (args) => {
32744
+ if (args.kind === "require-call")
32745
+ return { path: args.path, namespace: REQUIRED_NODE_BUILT_IN_NAMESPACE };
32746
+ return void 0;
32747
+ });
32748
+ build.onLoad(
32749
+ { filter: /.*/, namespace: REQUIRED_NODE_BUILT_IN_NAMESPACE },
32750
+ ({ path }) => ({
32751
+ contents: `import libDefault from '${path}';
32752
+ module.exports = libDefault;`,
32753
+ loader: "js"
32754
+ })
32755
+ );
32756
+ }
32757
+ function handleUnenvAliasedPackages(build, alias, external) {
32758
+ const aliasAbsolute = {};
32759
+ for (const [module, unresolvedAlias] of Object.entries(alias)) {
32760
+ if (SKIPPED_ALIASES.has(module)) continue;
32761
+ try {
32762
+ aliasAbsolute[module] = require2.resolve(unresolvedAlias);
32763
+ } catch {
32764
+ }
32765
+ }
32766
+ const UNENV_ALIAS_RE = new RegExp(
32767
+ `^(${Object.keys(aliasAbsolute).join("|")})$`
32768
+ );
32769
+ build.onResolve({ filter: UNENV_ALIAS_RE }, (args) => {
32770
+ const unresolvedAlias = alias[args.path] ?? "";
32771
+ if (args.kind === "require-call" && (unresolvedAlias.startsWith("unenv/npm/") || unresolvedAlias.startsWith("unenv/mock/")))
32772
+ return { path: args.path, namespace: REQUIRED_UNENV_ALIAS_NAMESPACE };
32773
+ return {
32774
+ path: aliasAbsolute[args.path] ?? args.path,
32775
+ external: external.includes(unresolvedAlias)
32776
+ };
32777
+ });
32778
+ build.onLoad(
32779
+ { filter: /.*/, namespace: REQUIRED_UNENV_ALIAS_NAMESPACE },
32780
+ ({ path }) => ({
32781
+ contents: `import * as esm from '${path}';
32782
+ module.exports = Object.entries(esm)
32783
+ .filter(([k,]) => k !== 'default')
32784
+ .reduce((cjs, [k, value]) =>
32785
+ Object.defineProperty(cjs, k, { value, enumerable: true }),
32786
+ "default" in esm ? esm.default : {}
32787
+ );`,
32788
+ loader: "js"
32789
+ })
32790
+ );
32791
+ }
32792
+ function handleNodeJSGlobals(build, inject, polyfill, virtualBase) {
32793
+ const UNENV_VIRTUAL_MODULE_RE = /_virtual_unenv_global_polyfill-(.+)$/;
32794
+ const prefix = resolvePath(virtualBase, "_virtual_unenv_global_polyfill-");
32795
+ const injectsByModule = /* @__PURE__ */ new Map();
32796
+ const virtualModulePathToSpecifier = /* @__PURE__ */ new Map();
32797
+ for (const [injectedName, moduleSpecifier] of Object.entries(inject)) {
32798
+ const [module, exportName, importName] = Array.isArray(moduleSpecifier) ? [
32799
+ moduleSpecifier[0] ?? "",
32800
+ moduleSpecifier[1] ?? "",
32801
+ moduleSpecifier[1] ?? ""
32802
+ ] : [moduleSpecifier, "default", "defaultExport"];
32803
+ if (!injectsByModule.has(module)) {
32804
+ injectsByModule.set(module, []);
32805
+ virtualModulePathToSpecifier.set(
32806
+ prefix + module.replaceAll("/", "-"),
32807
+ module
32808
+ );
32809
+ }
32810
+ injectsByModule.get(module)?.push({ injectedName, exportName, importName });
32811
+ }
32812
+ build.initialOptions.inject = [
32813
+ ...build.initialOptions.inject ?? [],
32814
+ ...virtualModulePathToSpecifier.keys(),
32815
+ ...polyfill.map((module) => require2.resolve(module))
32816
+ ];
32817
+ build.onResolve({ filter: UNENV_VIRTUAL_MODULE_RE }, ({ path }) => ({
32818
+ path
32819
+ }));
32820
+ build.onLoad({ filter: UNENV_VIRTUAL_MODULE_RE }, ({ path }) => {
32821
+ const module = virtualModulePathToSpecifier.get(path);
32822
+ const injects = module === void 0 ? void 0 : injectsByModule.get(module);
32823
+ if (module === void 0 || injects === void 0)
32824
+ throw new Error(`Expected ${path} to be mapped to a module specifier`);
32825
+ const imports = injects.map(
32826
+ ({ exportName, importName }) => importName === exportName ? exportName : `${exportName} as ${importName}`
32827
+ );
32828
+ return {
32829
+ resolveDir: MODULE_DIR,
32830
+ contents: `import { ${imports.join(", ")} } from "${module}";
32831
+ ${injects.map(
32832
+ ({ injectedName, importName }) => `globalThis.${injectedName} = ${importName};`
32833
+ ).join("\n")}`
32834
+ };
32835
+ });
32836
+ }
32837
+
32838
+ // ../../packages/functions-bundler/src/deno-imports.ts
32839
+ import { existsSync as existsSync9, readFileSync as readFileSync9, realpathSync as realpathSync2 } from "fs";
32840
+ import { dirname as dirname9, isAbsolute as isAbsolute5, join as join29, relative as relative8, sep as sep8 } from "path";
32841
+
32842
+ // ../../packages/functions-bundler/src/import-map.ts
32843
+ import { existsSync as existsSync8, readFileSync as readFileSync8, realpathSync } from "fs";
32844
+ import { basename as basename4, dirname as dirname8, join as join28, resolve as resolve12, sep as sep7 } from "path";
32845
+ import { fileURLToPath as fileURLToPath3 } from "url";
32846
+
32847
+ // ../../packages/functions-bundler/src/printable.ts
32848
+ var UNPRINTABLE = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu;
32849
+ function printable(text3) {
32850
+ return text3.replace(UNPRINTABLE, "?");
32851
+ }
32852
+ function causeLine(error51) {
32853
+ const text3 = error51 instanceof Error ? error51.message : String(error51);
32854
+ return printable(
32855
+ text3.split("\n").map((line) => line.trim()).find((line) => line.length > 0) ?? "unknown error"
32856
+ );
32857
+ }
32858
+
32859
+ // ../../packages/functions-bundler/src/import-map.ts
32860
+ var FILES = ["deno.json", "deno.jsonc", "import_map.json"];
32861
+ var DENO_CONFIGS = /* @__PURE__ */ new Set(["deno.json", "deno.jsonc"]);
32862
+ function expandBareKeys(imports) {
32863
+ const out = {};
32864
+ for (const [key, value] of Object.entries(imports)) {
32865
+ out[key] = value;
32866
+ if (key.endsWith("/") || Object.hasOwn(imports, `${key}/`)) continue;
32867
+ if (value.endsWith("/")) continue;
32868
+ const scheme = value.startsWith("jsr:") ? "jsr:" : value.startsWith("npm:") ? "npm:" : null;
32869
+ if (scheme === null) continue;
32870
+ const rest = value.slice(scheme.length).replace(/^\//, "");
32871
+ out[`${key}/`] = `${scheme}/${rest}/`;
32872
+ }
32873
+ return out;
32874
+ }
32875
+ function load(file2, label2) {
32876
+ let parsed;
32877
+ try {
32878
+ parsed = parseJsonc2(readFileSync8(file2, "utf8"));
32879
+ } catch {
32880
+ throw new FunctionBundleError(
32881
+ "VALIDATION_FAILED",
32882
+ BUNDLE_MESSAGES.importMapInvalid(label2)
32883
+ );
32884
+ }
32885
+ if (typeof parsed !== "object" || parsed === null) return null;
32886
+ const imports = parsed.imports;
32887
+ if (imports === void 0) return null;
32888
+ if (typeof imports !== "object" || imports === null || Array.isArray(imports) || Object.values(imports).some((target2) => typeof target2 !== "string"))
32889
+ throw new FunctionBundleError(
32890
+ "VALIDATION_FAILED",
32891
+ BUNDLE_MESSAGES.importMapShape(label2)
32892
+ );
32893
+ const written = imports;
32894
+ for (const [key, value] of Object.entries(written))
32895
+ if (key.endsWith("/") && !value.endsWith("/"))
32896
+ throw new FunctionBundleError(
32897
+ "VALIDATION_FAILED",
32898
+ printable(BUNDLE_MESSAGES.importMapPrefix(label2, key, value))
32899
+ );
32900
+ return {
32901
+ imports: DENO_CONFIGS.has(basename4(file2)) ? expandBareKeys(written) : written,
32902
+ base: dirname8(file2),
32903
+ label: label2
32904
+ };
32905
+ }
32906
+ function readImportMapFile(file2, label2) {
32907
+ if (!existsSync8(file2))
32908
+ throw new FunctionBundleError(
32909
+ "VALIDATION_FAILED",
32910
+ BUNDLE_MESSAGES.importMapMissing(label2)
32911
+ );
32912
+ return load(file2, label2);
32913
+ }
32914
+ function readImportMap(functionDir, fallback, labelOf) {
32915
+ for (const name of FILES) {
32916
+ const file2 = join28(functionDir, name);
32917
+ if (!existsSync8(file2)) continue;
32918
+ const map2 = load(file2, labelOf(file2));
32919
+ if (map2 !== null) return map2;
32920
+ }
32921
+ if (fallback === void 0 || fallback === null) return null;
32922
+ return typeof fallback === "string" ? readImportMapFile(fallback, labelOf(fallback)) : fallback;
32923
+ }
32924
+ function realPath(path) {
32925
+ try {
32926
+ return realpathSync.native(path);
32927
+ } catch {
32928
+ return path;
32929
+ }
32930
+ }
32931
+ var isPathLike = (text3) => text3.startsWith("./") || text3.startsWith("../") || text3.startsWith("/");
32932
+ function filePath(text3) {
32933
+ if (!text3.startsWith("file:")) return null;
32934
+ try {
32935
+ return fileURLToPath3(text3);
32936
+ } catch {
32937
+ return null;
32938
+ }
32939
+ }
32940
+ function realKey(path, trailing) {
32941
+ const real = realPath(path);
32942
+ return trailing && !real.endsWith(sep7) ? `${real}${sep7}` : real;
32943
+ }
32944
+ var normalized = /* @__PURE__ */ new WeakMap();
32945
+ function keysOf(map2) {
32946
+ const cached2 = normalized.get(map2);
32947
+ if (cached2 !== void 0) return cached2;
32948
+ const base2 = realPath(map2.base);
32949
+ const keys = /* @__PURE__ */ new Map();
32950
+ for (const [key, target2] of Object.entries(map2.imports)) {
32951
+ const trailing = key.endsWith("/");
32952
+ const file2 = filePath(key);
32953
+ const name = file2 !== null ? realKey(file2, trailing) : isPathLike(key) ? realKey(resolve12(base2, key), trailing) : key;
32954
+ if (!keys.has(name)) keys.set(name, target2);
32955
+ }
32956
+ normalized.set(map2, keys);
32957
+ return keys;
32958
+ }
32959
+ function mapSpecifier(map2, specifier, importerDir) {
32960
+ let lookup = specifier;
32961
+ const trailing = specifier.endsWith("/");
32962
+ const file2 = filePath(specifier);
32963
+ if (file2 !== null) lookup = realKey(file2, trailing);
32964
+ else if (specifier.startsWith("/"))
32965
+ lookup = realKey(resolve12(specifier), trailing);
32966
+ else if (isPathLike(specifier)) {
32967
+ if (importerDir === void 0) return null;
32968
+ lookup = realKey(resolve12(importerDir, specifier), trailing);
32969
+ }
32970
+ const keys = keysOf(map2);
32971
+ let target2 = keys.get(lookup);
32972
+ if (target2 === void 0) {
32973
+ let prefix;
32974
+ for (const key of keys.keys())
32975
+ if ((key.endsWith("/") || key.endsWith(sep7)) && lookup.startsWith(key) && (prefix === void 0 || key.length > prefix.length))
32976
+ prefix = key;
32977
+ if (prefix === void 0) return null;
32978
+ target2 = `${keys.get(prefix) ?? ""}${lookup.slice(prefix.length)}`;
32979
+ }
32980
+ if (target2.startsWith("./") || target2.startsWith("../"))
32981
+ return resolve12(map2.base, target2);
32982
+ return filePath(target2) ?? target2;
32983
+ }
32984
+
32985
+ // ../../packages/functions-bundler/src/range.ts
32986
+ function parse3(text3) {
32987
+ const match = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(text3.trim());
32988
+ if (!match) return null;
32989
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
32990
+ }
32991
+ function partial2(text3) {
32992
+ if (!/^\d+(\.\d+){0,2}$/.test(text3)) return null;
32993
+ return text3.split(".").map(Number);
32994
+ }
32995
+ function compare2(a, b) {
32996
+ for (let i = 0; i < 3; i += 1) {
32997
+ const diff = (a[i] ?? 0) - (b[i] ?? 0);
32998
+ if (diff !== 0) return diff;
32999
+ }
33000
+ return 0;
33001
+ }
33002
+ var filled = (parts) => [
33003
+ parts[0] ?? 0,
33004
+ parts[1] ?? 0,
33005
+ parts[2] ?? 0
33006
+ ];
33007
+ function inRange(versionText, rangeText) {
33008
+ const version3 = parse3(versionText);
33009
+ if (version3 === null) return null;
33010
+ const range = rangeText.trim();
33011
+ if (range === "" || range === "*" || range === "latest") return true;
33012
+ const operator = /^(\^|~|>=)?(.*)$/.exec(range);
33013
+ const op = operator?.[1] ?? "";
33014
+ const parts = partial2(operator?.[2] ?? "");
33015
+ if (parts === null) return null;
33016
+ const floor = filled(parts);
33017
+ if (op === ">=") return compare2(version3, floor) >= 0;
33018
+ if (op === "") return parts.every((part, i) => version3[i] === part);
33019
+ if (compare2(version3, floor) < 0) return false;
33020
+ if (op === "~")
33021
+ return version3[0] === floor[0] && (parts.length < 2 || version3[1] === floor[1]);
33022
+ if (floor[0] !== 0 || parts.length === 1) return version3[0] === floor[0];
33023
+ if (floor[1] !== 0 || parts.length === 2)
33024
+ return version3[0] === 0 && version3[1] === floor[1];
33025
+ return version3[0] === 0 && version3[1] === 0 && version3[2] === floor[2];
33026
+ }
33027
+
33028
+ // ../../packages/functions-bundler/src/deno-imports.ts
33029
+ var MISSING_NAMESPACE = "naro-missing-package";
33030
+ var MAPPED = "naroMapped";
33031
+ function parseNpm(text3) {
33032
+ const scoped = text3.startsWith("@");
33033
+ const slash = text3.indexOf("/", scoped ? text3.indexOf("/") + 1 : 0);
33034
+ const head = slash === -1 ? text3 : text3.slice(0, slash);
33035
+ const sub = slash === -1 ? "" : text3.slice(slash);
33036
+ const at = head.indexOf("@", scoped ? 1 : 0);
33037
+ return at === -1 ? { pkg: head, range: void 0, sub } : { pkg: head.slice(0, at), range: head.slice(at + 1) || void 0, sub };
33038
+ }
33039
+ var afterScheme = (specifier) => specifier.slice(4).replace(/^\//, "");
33040
+ var isPackageName = (pkg) => pkg.startsWith("@") ? /^@[^/]+\/[^/]+$/.test(pkg) : /^[^/]+$/.test(pkg);
33041
+ var refuse2 = (text3) => ({ errors: [{ text: printable(text3) }] });
33042
+ var installOf = (pkg, range) => range ? `${pkg}@${range}` : pkg;
33043
+ function realPath2(path) {
33044
+ try {
33045
+ return realpathSync2.native(path);
33046
+ } catch {
33047
+ return path;
33048
+ }
33049
+ }
33050
+ var fromRoot = (projectRoot, path) => relative8(projectRoot, path).split(sep8).join("/");
33051
+ function isInside(path, projectRoot) {
33052
+ const rel = relative8(projectRoot, path);
33053
+ return rel === "" || rel !== ".." && !rel.startsWith(`..${sep8}`) && !isAbsolute5(rel);
33054
+ }
33055
+ function packageDir(from, projectRoot) {
33056
+ let current = from;
33057
+ while (isInside(current, projectRoot)) {
33058
+ const inNodeModules = fromRoot(projectRoot, current).split("/").includes("node_modules");
33059
+ if (!inNodeModules && existsSync9(join29(current, "package.json")))
33060
+ return fromRoot(projectRoot, current) || ".";
33061
+ const up = dirname9(current);
33062
+ if (up === current) break;
33063
+ current = up;
33064
+ }
33065
+ return ".";
33066
+ }
33067
+ function isInstalled(from, pkg) {
33068
+ if (pkg === "") return false;
33069
+ let current = from;
33070
+ for (; ; ) {
33071
+ if (existsSync9(join29(current, "node_modules", pkg))) return true;
33072
+ const up = dirname9(current);
33073
+ if (up === current) return false;
33074
+ current = up;
33075
+ }
33076
+ }
33077
+ var NODE_MODULES = /[\\/]node_modules[\\/]/;
33078
+ function installedVersion(resolved, pkg) {
33079
+ let current = dirname9(resolved);
33080
+ for (; ; ) {
33081
+ const file2 = join29(current, "package.json");
33082
+ if (existsSync9(file2)) {
33083
+ try {
33084
+ const manifest2 = JSON.parse(readFileSync9(file2, "utf8"));
33085
+ if (manifest2.name === pkg && typeof manifest2.version === "string")
33086
+ return manifest2.version;
33087
+ } catch {
33088
+ }
33089
+ }
33090
+ const up = dirname9(current);
33091
+ if (up === current) return null;
33092
+ current = up;
33093
+ }
33094
+ }
33095
+ var byCodePoint = (a, b) => a < b ? -1 : a > b ? 1 : 0;
33096
+ function missingPackagesMessage(unsorted) {
33097
+ return printable(installSentence(unsorted));
33098
+ }
33099
+ function installSentence(unsorted) {
33100
+ const missing = [...unsorted].sort(
33101
+ (a, b) => byCodePoint(`${a.kind}:${a.spec}`, `${b.kind}:${b.spec}`)
33102
+ );
33103
+ const [only] = missing;
33104
+ if (missing.length === 1 && only !== void 0)
33105
+ return only.kind === "npm" ? BUNDLE_MESSAGES.npmMissing(only.spec, only.install, only.dir) : BUNDLE_MESSAGES.jsrMissing(only.spec, only.install);
33106
+ return BUNDLE_MESSAGES.missingMany(
33107
+ missing.map((item) => `${item.kind}:${item.spec}`),
33108
+ // npm:zod@3 and npm:zod@3/x need one zod@3; zod@3 and zod@4 stay two.
33109
+ [...new Set(missing.map((item) => item.install))].sort(byCodePoint),
33110
+ missing.some((item) => item.kind === "jsr")
33111
+ );
33112
+ }
33113
+ var ESM_SH_NOT_NPM = /* @__PURE__ */ new Set(["stable", "gh", "jsr", "pr"]);
33114
+ var URL_IMPORT = /^https?:\/\//;
33115
+ var WASM = /\.wasm(\?.*)?$/;
33116
+ function urlRefusal(url2) {
33117
+ let parsed;
33118
+ try {
33119
+ parsed = new URL(url2);
33120
+ } catch {
33121
+ return BUNDLE_MESSAGES.urlOther(url2);
33122
+ }
33123
+ if (parsed.hostname === "esm.sh") {
33124
+ const path = parsed.pathname.replace(/^\/v\d+(?=\/)/, "");
33125
+ const first = path.split("/")[1] ?? "";
33126
+ if (ESM_SH_NOT_NPM.has(first) || first.startsWith("*"))
33127
+ return BUNDLE_MESSAGES.urlOther(url2);
33128
+ const match = /^\/((?:@[^/@]+\/)?[^/@]+)(?:@([^/?]+))?/.exec(path);
33129
+ if (match?.[1])
33130
+ return BUNDLE_MESSAGES.urlNpm(
33131
+ url2,
33132
+ `npm:${installOf(match[1], match[2])}`
33133
+ );
33134
+ }
33135
+ if (parsed.hostname === "deno.land") {
33136
+ const match = /^\/std(?:@[^/]+)?\/([^/]+)/.exec(parsed.pathname);
33137
+ if (match?.[1]) return BUNDLE_MESSAGES.urlStd(url2, match[1]);
33138
+ }
33139
+ return BUNDLE_MESSAGES.urlOther(url2);
33140
+ }
33141
+ function denoImportsPlugin(options) {
33142
+ const { importMap, state } = options;
33143
+ const projectRoot = realPath2(options.projectRoot);
33144
+ const seenMissing = /* @__PURE__ */ new Set();
33145
+ return {
33146
+ name: "naro-deno-imports",
33147
+ setup(build) {
33148
+ build.onStart(() => {
33149
+ state.missing.length = 0;
33150
+ state.warnings.length = 0;
33151
+ seenMissing.clear();
33152
+ });
33153
+ const rewritten = async (kind, written, spec, target2, args) => {
33154
+ const result = await build.resolve(target2, {
33155
+ kind: args.kind,
33156
+ resolveDir: args.resolveDir,
33157
+ importer: args.importer,
33158
+ pluginData: { [MAPPED]: true }
33159
+ });
33160
+ const pkgName = kind === "npm" ? spec.pkg : target2.split("/").slice(0, 2).join("/");
33161
+ if (result.errors.length > 0) {
33162
+ if (isInstalled(args.resolveDir, pkgName))
33163
+ return { errors: result.errors };
33164
+ if (!seenMissing.has(`${kind}:${written}`)) {
33165
+ seenMissing.add(`${kind}:${written}`);
33166
+ state.missing.push({
33167
+ kind,
33168
+ spec: written,
33169
+ install: installOf(pkgName, spec.range),
33170
+ dir: packageDir(args.resolveDir, projectRoot)
33171
+ });
33172
+ }
33173
+ return { path: `${kind}:${written}`, namespace: MISSING_NAMESPACE };
33174
+ }
33175
+ if (spec.range) {
33176
+ const version3 = installedVersion(result.path, pkgName);
33177
+ if (version3 !== null && inRange(version3, spec.range) === false) {
33178
+ const warning = printable(
33179
+ BUNDLE_MESSAGES.outOfRange(
33180
+ pkgName,
33181
+ version3,
33182
+ spec.range,
33183
+ fromRoot(projectRoot, args.importer)
33184
+ )
33185
+ );
33186
+ if (!state.warnings.includes(warning)) state.warnings.push(warning);
33187
+ }
33188
+ }
33189
+ return {
33190
+ path: result.path,
33191
+ external: result.external,
33192
+ namespace: result.namespace,
33193
+ sideEffects: result.sideEffects
33194
+ };
33195
+ };
33196
+ build.onResolve({ filter: /.*/, namespace: "file" }, async (args) => {
33197
+ if (importMap === null || args.kind === "entry-point") return void 0;
33198
+ if (NODE_MODULES.test(args.importer)) return void 0;
33199
+ if (args.pluginData?.[MAPPED])
33200
+ return void 0;
33201
+ const mapped = mapSpecifier(importMap, args.path, args.resolveDir);
33202
+ if (mapped === null) return void 0;
33203
+ if (WASM.test(mapped)) return refuse2(BUNDLE_MESSAGES.wasm(args.path));
33204
+ if (URL_IMPORT.test(mapped)) return refuse2(urlRefusal(mapped));
33205
+ const result = await build.resolve(mapped, {
33206
+ kind: args.kind,
33207
+ resolveDir: args.resolveDir,
33208
+ importer: args.importer,
33209
+ pluginData: { [MAPPED]: true }
33210
+ });
33211
+ if (result.errors.length > 0) return { errors: result.errors };
33212
+ return {
33213
+ path: result.path,
33214
+ external: result.external,
33215
+ namespace: result.namespace,
33216
+ sideEffects: result.sideEffects
33217
+ };
33218
+ });
33219
+ build.onResolve({ filter: /^npm:/ }, async (args) => {
33220
+ const written = afterScheme(args.path);
33221
+ const spec = parseNpm(written);
33222
+ if (!isPackageName(spec.pkg))
33223
+ return refuse2(BUNDLE_MESSAGES.noPackageName(args.path, "npm:zod@3"));
33224
+ return rewritten("npm", written, spec, `${spec.pkg}${spec.sub}`, args);
33225
+ });
33226
+ build.onResolve({ filter: /^jsr:/ }, async (args) => {
33227
+ const written = afterScheme(args.path);
33228
+ const spec = parseNpm(written);
33229
+ if (spec.pkg !== "" && !spec.pkg.startsWith("@"))
33230
+ return refuse2(BUNDLE_MESSAGES.jsrNoScope(written));
33231
+ if (!isPackageName(spec.pkg))
33232
+ return refuse2(
33233
+ BUNDLE_MESSAGES.noPackageName(args.path, "jsr:@std/http@1")
33234
+ );
33235
+ const [scope, name] = spec.pkg.slice(1).split("/");
33236
+ return rewritten(
33237
+ "jsr",
33238
+ written,
33239
+ spec,
33240
+ `@jsr/${scope ?? ""}__${name ?? ""}${spec.sub}`,
33241
+ args
33242
+ );
33243
+ });
33244
+ build.onResolve(
33245
+ { filter: URL_IMPORT },
33246
+ (args) => refuse2(urlRefusal(args.path))
33247
+ );
33248
+ build.onResolve(
33249
+ { filter: WASM },
33250
+ (args) => refuse2(BUNDLE_MESSAGES.wasm(args.path))
33251
+ );
33252
+ build.onLoad({ filter: /.*/, namespace: MISSING_NAMESPACE }, () => ({
33253
+ contents: "module.exports = {};",
33254
+ loader: "js"
33255
+ }));
33256
+ build.onEnd(
33257
+ () => state.missing.length === 0 ? void 0 : { errors: [{ text: missingPackagesMessage(state.missing) }] }
33258
+ );
33259
+ }
33260
+ };
33261
+ }
33262
+
33263
+ // ../../packages/functions-bundler/src/bundle.ts
33264
+ import { createHash as createHash4 } from "crypto";
33265
+ import { join as join30, relative as relative9, sep as sep9 } from "path";
33266
+ import { gzipSync } from "zlib";
33267
+
33268
+ // ../../packages/functions-runtime/dist/index.js
33269
+ var NARO_SHIM_MODULE = "naro-shim.js";
33270
+ var NARO_USER_MODULE = "user.js";
33271
+ var NARO_BOOT_MODULE = "naro-boot.js";
33272
+ var NARO_ENTRY_SOURCE = '// src/naro-entry.ts\nimport "./naro-shim.js";\nimport * as user from "./user.js";\n\n// src/context.ts\nvar CONTEXT_HEADER = "x-naro-context";\nvar MAX_CONTEXT_LENGTH = 4096;\nvar BASE64URL = /^[A-Za-z0-9_-]+$/;\nvar TRACE_ID_RE = /^[A-Za-z0-9-]{1,64}$/;\nvar MAX_HOP = 1e3;\nvar ROLES = /* @__PURE__ */ new Set([\n "anon",\n "authenticated",\n "service"\n]);\nfunction fieldsOf(value) {\n if (typeof value !== "object" || value === null || Array.isArray(value))\n return null;\n return value;\n}\nfunction own(fields, key) {\n return Object.hasOwn(fields, key) ? fields[key] : void 0;\n}\nfunction nonEmptyText(value) {\n return typeof value === "string" && value !== "";\n}\nvar MAX_USER_ID_LENGTH = 256;\nfunction headerSafeId(value) {\n if (!nonEmptyText(value) || value.length > MAX_USER_ID_LENGTH) return false;\n if (value.trim() !== value) return false;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 32 || code >= 127 && code <= 159) return false;\n if (code >= 55296 && code <= 57343) {\n const next = value.charCodeAt(index + 1);\n if (code >= 56320 || !(next >= 56320 && next <= 57343)) return false;\n index += 1;\n }\n }\n return true;\n}\nfunction userOf(value) {\n const fields = fieldsOf(value);\n if (fields === null) return null;\n const id = own(fields, "id");\n const email = own(fields, "email");\n const emailVerified = own(fields, "emailVerified");\n if (!headerSafeId(id)) return null;\n if (email !== null && typeof email !== "string") return null;\n if (typeof emailVerified !== "boolean") return null;\n return { id, email, emailVerified };\n}\nfunction contextOf(value, projectId, name) {\n const fields = fieldsOf(value);\n if (fields === null) return null;\n if (own(fields, "v") !== 1) return null;\n if (own(fields, "projectId") !== projectId) return null;\n if (own(fields, "function") !== name) return null;\n const traceId = own(fields, "traceId");\n if (typeof traceId !== "string" || !TRACE_ID_RE.test(traceId)) return null;\n const hop = own(fields, "hop");\n if (typeof hop !== "number" || !Number.isInteger(hop) || hop < 0 || hop > MAX_HOP)\n return null;\n const role = own(fields, "role");\n if (role !== null && !ROLES.has(role)) return null;\n const sentUser = own(fields, "user");\n let user2 = null;\n if (role === "authenticated") {\n user2 = userOf(sentUser);\n if (user2 === null) return null;\n } else if (sentUser !== null) return null;\n return {\n v: 1,\n projectId,\n function: name,\n role,\n user: user2,\n traceId,\n hop\n };\n}\nfunction bytesOf(value) {\n if (!BASE64URL.test(value) || value.length % 4 === 1) return null;\n const base64 = value.replace(/-/g, "+").replace(/_/g, "/");\n let binary;\n try {\n binary = atob(base64 + "=".repeat((4 - base64.length % 4) % 4));\n } catch {\n return null;\n }\n const again = btoa(binary).replace(/\\+/g, "-").replace(/\\//g, "_").replace(/=+$/, "");\n if (again !== value) return null;\n return Uint8Array.from(binary, (char) => char.charCodeAt(0));\n}\nfunction decodeContext(value, bindings) {\n const projectId = bindings.NARO_PROJECT_ID;\n const name = bindings.NARO_FUNCTION_NAME;\n if (!nonEmptyText(projectId) || !nonEmptyText(name)) return null;\n if (typeof value !== "string" || value.length > MAX_CONTEXT_LENGTH)\n return null;\n const bytes = bytesOf(value);\n if (bytes === null) return null;\n let parsed;\n try {\n parsed = JSON.parse(\n new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes)\n );\n } catch {\n return null;\n }\n return contextOf(parsed, projectId, name);\n}\n\n// src/rejections.ts\nfunction loggedRejection(promise, name) {\n return Promise.resolve(promise).then(\n () => void 0,\n (error) => {\n console.error(`naro functions: ${name} waitUntil rejected`, error);\n }\n );\n}\n\n// src/respond.ts\nvar FUNCTION_EXPOSE_HEADERS = [\n "x-relay-error",\n "x-naro-trace-id",\n "retry-after",\n "x-retry-after"\n];\nvar WRAPPER_ERRORS = {\n FUNCTION_ERROR: "The function threw an error. See `naro functions logs {name}`.",\n FUNCTION_NO_HANDLER: "The function has no handler. Call Deno.serve(handler) or export default { fetch }.",\n FUNCTION_MISROUTED: "This function was reached without the Naro gateway."\n};\nfunction appendExposeHeaders(value) {\n const listed = (value ?? "").split(",").map((part) => part.trim()).filter((part) => part !== "");\n const seen = new Set(listed.map((part) => part.toLowerCase()));\n for (const name of FUNCTION_EXPOSE_HEADERS)\n if (!seen.has(name)) listed.push(name);\n return listed.join(", ");\n}\nfunction wrapperError(code, name, traceId) {\n const headers = new Headers({\n "access-control-allow-origin": "*",\n "access-control-expose-headers": appendExposeHeaders(null),\n "cache-control": "no-store"\n });\n if (traceId !== null) headers.set("x-naro-trace-id", traceId);\n return Response.json(\n {\n data: null,\n error: {\n code,\n // A function, not a string: `$&` in a name stays as it is.\n message: WRAPPER_ERRORS[code].replace("{name}", () => name)\n }\n },\n { status: 500, headers }\n );\n}\nfunction withFunctionHeaders(response, traceId) {\n if (response.status === 101) return response;\n const out = new Response(response.body, response);\n const headers = out.headers;\n headers.delete("x-relay-error");\n if (!headers.has("access-control-allow-origin"))\n headers.set("access-control-allow-origin", "*");\n headers.set(\n "access-control-expose-headers",\n appendExposeHeaders(headers.get("access-control-expose-headers"))\n );\n headers.set("x-naro-trace-id", traceId);\n return out;\n}\n\n// src/runtime-state.ts\nvar RUNTIME_KEY = /* @__PURE__ */ Symbol.for("naro.functions.runtime");\nvar CONTEXT_KEY = /* @__PURE__ */ Symbol.for("naro.functions.context");\nvar SHIM_FIRST = "The Naro functions shim must be imported before the wrapper.";\nfunction globals() {\n return globalThis;\n}\nfunction runtimeState() {\n const state2 = globals()[RUNTIME_KEY];\n if (state2 === void 0) throw new Error(SHIM_FIRST);\n return state2;\n}\nfunction callContexts() {\n const contexts2 = globals()[CONTEXT_KEY];\n if (contexts2 === void 0) throw new Error(SHIM_FIRST);\n return contexts2;\n}\n\n// src/naro-entry.ts\nvar state = runtimeState();\nvar contexts = callContexts();\nasync function serveWithInfo(registered, request) {\n let complete;\n const info = {\n remoteAddr: {\n transport: "tcp",\n hostname: request.headers.get("cf-connecting-ip") ?? "0.0.0.0",\n port: 0\n },\n completed: new Promise((resolve) => {\n complete = resolve;\n })\n };\n try {\n return await registered(request, info);\n } finally {\n complete();\n }\n}\nfunction chooseHandler() {\n const registered = state.handler;\n if (registered !== null)\n return {\n handler: async (request) => serveWithInfo(registered, request),\n onError: state.onError\n };\n const exported = user.default;\n if (typeof exported === "object" && exported !== null) {\n const fetchHandler = exported.fetch;\n if (typeof fetchHandler === "function")\n return {\n handler: async (request, env, ctx) => fetchHandler.call(exported, request, env, ctx),\n onError: null\n };\n }\n if (typeof exported === "function") {\n const prototype = exported.prototype;\n if (typeof prototype === "object" && prototype !== null && typeof prototype.fetch === "function")\n return {\n handler: async (request, env, ctx) => new exported(ctx, env).fetch(request),\n onError: null\n };\n return {\n handler: async (request, env, ctx) => exported(request, env, ctx),\n onError: null\n };\n }\n return null;\n}\nfunction callerRequest(request, context) {\n const headers = new Headers();\n for (const [name, value] of request.headers)\n if (!name.startsWith("x-naro-")) headers.append(name, value);\n if (context.role !== null) headers.set("x-naro-role", context.role);\n if (context.user !== null) headers.set("x-naro-user-id", context.user.id);\n headers.set("x-naro-trace-id", context.traceId);\n return new Request(request, { headers });\n}\nfunction logWaitUntilRejections(ctx, name) {\n const waitUntil = ctx.waitUntil.bind(ctx);\n try {\n Object.defineProperty(ctx, "waitUntil", {\n configurable: true,\n writable: true,\n value: (promise) => waitUntil(loggedRejection(promise, name))\n });\n } catch {\n }\n}\nfunction textOf(value) {\n return typeof value === "string" ? value : "";\n}\nfunction responseOf(value, what) {\n if (value instanceof Response) return value;\n throw new TypeError(`${what} did not return a Response.`);\n}\nasync function answerOf(chosen, name, request, env, ctx) {\n try {\n return responseOf(await chosen.handler(request, env, ctx), "The handler");\n } catch (error) {\n if (chosen.onError === null) {\n console.error(`naro functions: ${name} threw`, error);\n return null;\n }\n try {\n return responseOf(await chosen.onError(error), "onError");\n } catch (failed) {\n console.error(`naro functions: ${name} threw`, error, failed);\n return null;\n }\n }\n}\nasync function answerCall(request, env, ctx, seen) {\n const name = textOf(env.NARO_FUNCTION_NAME);\n const context = decodeContext(request.headers.get(CONTEXT_HEADER), env);\n if (context === null) return wrapperError("FUNCTION_MISROUTED", name, null);\n let forwarded;\n try {\n forwarded = callerRequest(request, context);\n } catch (error) {\n console.error(`naro functions: ${name} misrouted`, error);\n return wrapperError("FUNCTION_MISROUTED", name, null);\n }\n seen.traceId = context.traceId;\n const call = {\n role: context.role,\n user: context.user,\n traceId: context.traceId\n };\n contexts.set(forwarded, call);\n const chosen = chooseHandler();\n if (chosen === null)\n return wrapperError("FUNCTION_NO_HANDLER", name, context.traceId);\n logWaitUntilRejections(ctx, name);\n const answer = await state.requests.run(\n { ctx, hop: context.hop, traceId: context.traceId, call },\n () => answerOf(chosen, name, forwarded, env, ctx)\n );\n if (answer === null)\n return wrapperError("FUNCTION_ERROR", name, context.traceId);\n try {\n return withFunctionHeaders(answer, context.traceId);\n } catch (error) {\n console.error(\n `naro functions: ${name} answered with a response that cannot be sent`,\n error\n );\n return wrapperError("FUNCTION_ERROR", name, context.traceId);\n }\n}\nvar naro_entry_default = {\n async fetch(request, env, ctx) {\n const seen = { traceId: null };\n let answer;\n try {\n answer = await answerCall(request, env, ctx, seen);\n } catch (error) {\n return state.lastResort(error, seen.traceId);\n }\n if (state.isResponse(answer)) return answer;\n return state.lastResort(\n new TypeError("The wrapper\'s answer is not a Response."),\n seen.traceId\n );\n }\n};\nexport {\n naro_entry_default as default\n};\n';
33273
+ var NARO_SHIM_SOURCE = '// src/naro-shim.ts\nimport { AsyncLocalStorage } from "node:async_hooks";\nimport { env } from "cloudflare:workers";\n\n// src/hosts.ts\nfunction bareHost(host) {\n return host.toLowerCase().replace(/\\.+$/, "");\n}\nfunction isNaroHost(hostname, rootDomain2, naroUrl2) {\n const host = bareHost(hostname);\n if (host === "") return false;\n const root = rootDomain2.toLowerCase().replace(/^\\.+|\\.+$/g, "");\n if (root !== "" && host.endsWith(`.${root}`)) return true;\n if (naroUrl2 === "") return false;\n try {\n return bareHost(new URL(naroUrl2).hostname) === host;\n } catch {\n return false;\n }\n}\n\n// src/redact.ts\nvar MIN_REDACTED_LENGTH = 8;\nvar REDACTED = "[redacted]";\nfunction isSecretBinding(name) {\n return name === "NARO_SERVICE_KEY" || !name.startsWith("NARO_") && name !== "DB";\n}\nfunction secretValues(bindings2) {\n const values = /* @__PURE__ */ new Set();\n for (const [name, value] of Object.entries(bindings2)) {\n if (typeof value !== "string" || value.length < MIN_REDACTED_LENGTH)\n continue;\n if (!isSecretBinding(name)) continue;\n values.add(value);\n values.add(JSON.stringify(value).slice(1, -1));\n }\n return [...values].toSorted(\n (left, right) => right.length - left.length || (left < right ? -1 : left > right ? 1 : 0)\n );\n}\nfunction redactText(text, secrets2) {\n const spans = [];\n for (const secret of secrets2) {\n if (secret === "") continue;\n let last;\n for (let at = text.indexOf(secret); at !== -1; at = text.indexOf(secret, at + 1)) {\n if (last !== void 0 && at <= last[1]) last[1] = at + secret.length;\n else spans.push(last = [at, at + secret.length]);\n }\n }\n if (spans.length === 0) return text;\n const ordered = spans.toSorted((left, right) => left[0] - right[0]);\n let out = "";\n let kept = 0;\n let [start, end] = ordered[0];\n for (const [nextStart, nextEnd] of ordered) {\n if (nextStart <= end) {\n end = Math.max(end, nextEnd);\n continue;\n }\n out += text.slice(kept, start) + REDACTED;\n kept = end;\n start = nextStart;\n end = nextEnd;\n }\n return out + text.slice(kept, start) + REDACTED + text.slice(end);\n}\nfunction stringOf(value) {\n try {\n return String(value);\n } catch {\n return void 0;\n }\n}\nfunction withHead(stack, head) {\n if (stack === head || stack.startsWith(`${head}\n`)) return stack;\n const frames = stack.indexOf("\\n at ");\n return frames === -1 ? `${head}\n${stack}` : `${head}${stack.slice(frames)}`;\n}\nfunction redactError(error, secrets2) {\n const stack = typeof error.stack === "string" ? error.stack : `${error.name}: ${error.message}`;\n const head = stringOf(error);\n let json;\n try {\n json = JSON.stringify(error);\n } catch {\n json = void 0;\n }\n const cleanStack = redactText(stack, secrets2);\n const cleanHead = head === void 0 ? void 0 : redactText(head, secrets2);\n const cleanJson = json === void 0 ? void 0 : redactText(json, secrets2);\n if (cleanStack === stack && head !== void 0 && cleanHead === head && json !== void 0 && cleanJson === json)\n return error;\n const text = cleanHead === void 0 ? cleanStack : withHead(cleanStack, cleanHead);\n return cleanJson === void 0 || cleanJson === "{}" ? text : `${text}\n${cleanJson}`;\n}\nfunction isPlain(value) {\n if (Array.isArray(value)) return true;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\nfunction redactArg(arg, secrets2) {\n if (typeof arg === "string") return redactText(arg, secrets2);\n if (arg === null || typeof arg !== "object" && typeof arg !== "function")\n return arg;\n try {\n if (arg instanceof Error) return redactError(arg, secrets2);\n let json;\n try {\n json = JSON.stringify(arg);\n } catch {\n return redactText(String(arg), secrets2);\n }\n if (json !== void 0) {\n const clean2 = redactText(json, secrets2);\n if (clean2 !== json) return clean2;\n }\n if (isPlain(arg)) return arg;\n const text = stringOf(arg);\n if (text === void 0) return arg;\n const clean = redactText(text, secrets2);\n return clean === text ? arg : clean;\n } catch {\n return REDACTED;\n }\n}\nfunction redactArgs(args, secrets2) {\n if (secrets2.length === 0) return [...args];\n return args.map((arg) => redactArg(arg, secrets2));\n}\n\n// src/rejections.ts\nfunction loggedRejection(promise, name) {\n return Promise.resolve(promise).then(\n () => void 0,\n (error) => {\n console.error(`naro functions: ${name} waitUntil rejected`, error);\n }\n );\n}\n\n// src/respond.ts\nvar FUNCTION_EXPOSE_HEADERS = [\n "x-relay-error",\n "x-naro-trace-id",\n "retry-after",\n "x-retry-after"\n];\nvar WRAPPER_ERRORS = {\n FUNCTION_ERROR: "The function threw an error. See `naro functions logs {name}`.",\n FUNCTION_NO_HANDLER: "The function has no handler. Call Deno.serve(handler) or export default { fetch }.",\n FUNCTION_MISROUTED: "This function was reached without the Naro gateway."\n};\nfunction appendExposeHeaders(value) {\n const listed = (value ?? "").split(",").map((part) => part.trim()).filter((part) => part !== "");\n const seen = new Set(listed.map((part) => part.toLowerCase()));\n for (const name of FUNCTION_EXPOSE_HEADERS)\n if (!seen.has(name)) listed.push(name);\n return listed.join(", ");\n}\n\n// src/runtime-state.ts\nvar RUNTIME_KEY = /* @__PURE__ */ Symbol.for("naro.functions.runtime");\nvar CONTEXT_KEY = /* @__PURE__ */ Symbol.for("naro.functions.context");\n\n// src/naro-shim.ts\nvar bindings = env;\nvar globals = globalThis;\nvar functionName = typeof bindings.NARO_FUNCTION_NAME === "string" ? bindings.NARO_FUNCTION_NAME : "";\nvar secrets = secretValues(bindings);\nfor (const level of ["log", "info", "warn", "error", "debug"]) {\n const original = console[level].bind(console);\n console[level] = (...args) => {\n original(...redactArgs(args, secrets));\n };\n}\nvar logError = console.error;\nvar NativeResponse = Response;\nvar bareRecord = Object.create;\nvar failedBody = JSON.stringify({\n data: null,\n error: {\n code: "FUNCTION_ERROR",\n message: WRAPPER_ERRORS.FUNCTION_ERROR.replace(\n "{name}",\n () => functionName\n )\n }\n});\nvar exposedHeaders = appendExposeHeaders(null);\nfunction lastResort(error, traceId) {\n try {\n logError(`naro functions: ${functionName} threw`, error);\n } catch {\n }\n const headers = bareRecord(null);\n headers["content-type"] = "application/json";\n headers["access-control-allow-origin"] = "*";\n headers["access-control-expose-headers"] = exposedHeaders;\n headers["cache-control"] = "no-store";\n if (traceId !== null) headers["x-naro-trace-id"] = traceId;\n const init = bareRecord(null);\n init.status = 500;\n init.headers = headers;\n return new NativeResponse(failedBody, init);\n}\nvar reflectApply = Reflect.apply;\nvar responseStatus = Object.getOwnPropertyDescriptor(\n NativeResponse.prototype,\n "status"\n)?.get;\nfunction isResponse(value) {\n if (typeof value !== "object" || value === null) return false;\n try {\n if (responseStatus === void 0) return value instanceof NativeResponse;\n reflectApply(responseStatus, value, []);\n return true;\n } catch {\n return false;\n }\n}\nvar state = {\n handler: null,\n onError: null,\n requests: new AsyncLocalStorage(),\n lastResort,\n isResponse\n};\nglobals[RUNTIME_KEY] = state;\nglobals[CONTEXT_KEY] = /* @__PURE__ */ new WeakMap();\nvar rootDomain = typeof bindings.NARO_ROOT_DOMAIN === "string" ? bindings.NARO_ROOT_DOMAIN : "";\nvar naroUrl = typeof bindings.NARO_URL === "string" ? bindings.NARO_URL : "";\nvar originalFetch = globalThis.fetch.bind(globalThis);\nasync function naroFetch(input, init) {\n const store = state.requests.getStore();\n if (store === void 0) return originalFetch(input, init);\n let host;\n try {\n host = new URL(input instanceof Request ? input.url : String(input)).hostname;\n } catch {\n return originalFetch(input, init);\n }\n if (!isNaroHost(host, rootDomain, naroUrl)) return originalFetch(input, init);\n const request = new Request(input, init);\n const headers = new Headers(request.headers);\n headers.set("x-naro-fn-hop", String(store.hop + 1));\n headers.set("x-naro-trace-id", store.traceId);\n return originalFetch(new Request(request, { headers }));\n}\nglobalThis.fetch = naroFetch;\nvar addListener = EventTarget.prototype.addEventListener;\nvar removeListener = EventTarget.prototype.removeEventListener;\nvar standIns = /* @__PURE__ */ new WeakMap();\nfunction standInFor(socket, listener, store) {\n let listeners = standIns.get(socket);\n if (listeners === void 0)\n standIns.set(socket, listeners = /* @__PURE__ */ new WeakMap());\n let standIn = listeners.get(listener);\n if (standIn === void 0) {\n standIn = function(event) {\n state.requests.run(\n store,\n () => typeof listener === "function" ? Reflect.apply(listener, this, [event]) : listener.handleEvent(event)\n );\n };\n listeners.set(listener, standIn);\n }\n return standIn;\n}\nObject.defineProperties(WebSocket.prototype, {\n addEventListener: {\n configurable: true,\n writable: true,\n value(type, listener, ...rest) {\n const store = state.requests.getStore();\n const runs = store !== void 0 && listener !== null && (typeof listener === "function" || typeof listener === "object");\n return Reflect.apply(addListener, this, [\n type,\n runs ? standInFor(this, listener, store) : listener,\n ...rest\n ]);\n }\n },\n removeEventListener: {\n configurable: true,\n writable: true,\n value(type, listener, ...rest) {\n const standIn = typeof listener === "function" || typeof listener === "object" && listener !== null ? standIns.get(this)?.get(listener) : void 0;\n return Reflect.apply(removeListener, this, [\n type,\n standIn ?? listener,\n ...rest\n ]);\n }\n }\n});\nvar ON_EVENTS = ["onopen", "onmessage", "onclose", "onerror"];\nvar onHandlers = /* @__PURE__ */ new WeakMap();\nfunction nativeAccessor(target, name) {\n for (let at = target; at !== null; at = Object.getPrototypeOf(at)) {\n const descriptor = Object.getOwnPropertyDescriptor(at, name);\n if (descriptor === void 0) continue;\n return descriptor.get !== void 0 && descriptor.set !== void 0 ? { get: descriptor.get, set: descriptor.set } : void 0;\n }\n return void 0;\n}\nfor (const name of ON_EVENTS) {\n const native = nativeAccessor(WebSocket.prototype, name);\n Object.defineProperty(WebSocket.prototype, name, {\n configurable: true,\n enumerable: true,\n get() {\n const set = onHandlers.get(this)?.get(name);\n if (set === void 0)\n return native === void 0 ? void 0 : Reflect.apply(native.get, this, []);\n return state.requests.getStore() === void 0 ? set.standIn : set.handler;\n },\n set(handler) {\n const store = state.requests.getStore();\n const standIn = store !== void 0 && typeof handler === "function" ? standInFor(this, handler, store) : handler;\n let handlers = onHandlers.get(this);\n if (handlers === void 0) onHandlers.set(this, handlers = /* @__PURE__ */ new Map());\n handlers.set(name, { handler, standIn });\n if (native !== void 0) Reflect.apply(native.set, this, [standIn]);\n }\n });\n}\nfunction serve(first, second) {\n const options = typeof first === "function" ? {} : first ?? {};\n const handler = typeof first === "function" ? first : second ?? options.handler;\n if (typeof handler !== "function")\n throw new TypeError("Deno.serve needs a handler.");\n state.handler = handler;\n state.onError = typeof options.onError === "function" ? options.onError : null;\n return {\n finished: new Promise(() => {\n }),\n shutdown: () => Promise.resolve()\n };\n}\nfunction textBindings() {\n const out = {};\n for (const [name, value] of Object.entries(bindings))\n if (typeof value === "string") out[name] = value;\n return out;\n}\nvar build = Object.freeze({\n os: "linux",\n arch: "x86_64",\n target: "x86_64-unknown-linux-gnu",\n vendor: "unknown",\n env: "gnu"\n});\nvar version = Object.freeze({\n deno: "2.1.4",\n v8: "13.0.245.12",\n typescript: "5.6.2"\n});\nvar DENO_ERROR_NAMES = [\n "NotFound",\n "PermissionDenied",\n "ConnectionRefused",\n "ConnectionReset",\n "ConnectionAborted",\n "NotConnected",\n "AddrInUse",\n "AddrNotAvailable",\n "BrokenPipe",\n "AlreadyExists",\n "InvalidData",\n "TimedOut",\n "Interrupted",\n "WriteZero",\n "WouldBlock",\n "UnexpectedEof",\n "BadResource",\n "Http",\n "Busy",\n "NotSupported",\n "FilesystemLoop",\n "IsADirectory",\n "NetworkUnreachable",\n "NotADirectory",\n "NotCapable"\n];\nfunction denoError(name) {\n const made = { [name]: class extends Error {\n } }[name];\n Object.defineProperty(made.prototype, "name", {\n configurable: true,\n writable: true,\n value: name\n });\n return made;\n}\nvar errors = Object.freeze(\n Object.fromEntries(DENO_ERROR_NAMES.map((name) => [name, denoError(name)]))\n);\nvar deno = {\n serve,\n env: {\n get: (name) => {\n const value = bindings[name];\n return typeof value === "string" ? value : void 0;\n },\n has: (name) => typeof bindings[name] === "string",\n toObject: () => textBindings(),\n set: () => {\n throw new Error("Deno.env.set is not available on Naro Functions.");\n },\n delete: () => {\n throw new Error("Deno.env.delete is not available on Naro Functions.");\n }\n },\n build,\n version,\n errors\n};\nvar PROBES = /* @__PURE__ */ new Set(["then", "toJSON"]);\nglobals.Deno = new Proxy(deno, {\n get(target, property) {\n if (typeof property === "symbol" || PROBES.has(property)) return void 0;\n if (Object.hasOwn(target, property)) return target[property];\n return () => {\n throw new Error(`Deno.${property} is not available on Naro Functions.`);\n };\n }\n});\nglobals.EdgeRuntime = {\n waitUntil(promise) {\n const logged = loggedRejection(promise, functionName);\n state.requests.getStore()?.ctx.waitUntil(logged);\n return promise;\n }\n};\naddEventListener("unhandledrejection", (event) => {\n event.preventDefault();\n console.error(\n `naro functions: ${functionName} unhandled rejection`,\n event.reason\n );\n});\n';
33274
+ var NARO_BOOT_SOURCE = '// src/naro-boot.ts\nimport "./naro-shim.js";\nimport * as user from "./user.js";\n\n// src/runtime-state.ts\nvar RUNTIME_KEY = /* @__PURE__ */ Symbol.for("naro.functions.runtime");\nvar SHIM_FIRST = "The Naro functions shim must be imported before the wrapper.";\nfunction globals() {\n return globalThis;\n}\nfunction runtimeState() {\n const state2 = globals()[RUNTIME_KEY];\n if (state2 === void 0) throw new Error(SHIM_FIRST);\n return state2;\n}\n\n// src/naro-boot.ts\nvar BOOT_PATH = "/__naro/boot";\nvar state = runtimeState();\nfunction hasHandler(exported) {\n if (state.handler !== null) return true;\n if (typeof exported === "function") return true;\n return typeof exported === "object" && exported !== null && typeof exported.fetch === "function";\n}\nvar naro_boot_default = {\n fetch(request) {\n if (new URL(request.url).pathname !== BOOT_PATH)\n return new Response("Not found", { status: 404 });\n return Response.json({ handler: hasHandler(user.default) });\n }\n};\nexport {\n naro_boot_default as default\n};\n';
33275
+ var FUNCTIONS_COMPATIBILITY_DATE = "2026-08-19";
33276
+ var FUNCTIONS_COMPATIBILITY_FLAGS = Object.freeze(["nodejs_compat", "global_fetch_strictly_public"]);
33277
+
33278
+ // ../../packages/functions-bundler/src/bundle.ts
33279
+ var NARO_JS_FUNCTIONS = /Could not resolve "naro-js\/functions"/;
33280
+ var runtimeGzip;
33281
+ function runtimeCompressedBytes() {
33282
+ runtimeGzip ??= gzipSync(NARO_ENTRY_SOURCE).byteLength + gzipSync(NARO_SHIM_SOURCE).byteLength;
33283
+ return runtimeGzip;
33284
+ }
33285
+ function relativeLabel(root, file2) {
33286
+ return relative9(root, file2).split(sep9).join("/");
33287
+ }
33288
+ function location(message) {
33289
+ return message.location ? `${message.location.file}:${String(message.location.line)}` : null;
33290
+ }
33291
+ function failure(name, error51, state) {
33292
+ if (error51 instanceof FunctionBundleError) return error51;
33293
+ if (state.missing.length > 0)
33294
+ return new FunctionBundleError(
33295
+ "FUNCTION_BUNDLE_FAILED",
33296
+ missingPackagesMessage(state.missing)
33297
+ );
33298
+ const errors = error51.errors ?? [];
33299
+ if (errors.length === 0)
33300
+ return new FunctionBundleError(
33301
+ "FUNCTION_BUNDLE_FAILED",
33302
+ BUNDLE_MESSAGES.otherBundle(
33303
+ name,
33304
+ error51 instanceof Error ? error51.message : String(error51),
33305
+ null
33306
+ )
33307
+ );
33308
+ const lines = errors.map((message) => {
33309
+ if (NARO_JS_FUNCTIONS.test(message.text))
33310
+ return BUNDLE_MESSAGES.naroJsMissing;
33311
+ if (message.pluginName === "naro-deno-imports") return message.text;
33312
+ return BUNDLE_MESSAGES.otherBundle(name, message.text, location(message));
33313
+ });
33314
+ return new FunctionBundleError(
33315
+ "FUNCTION_BUNDLE_FAILED",
33316
+ [...new Set(lines)].sort().join("\n")
33317
+ );
33318
+ }
33319
+ async function bundleFunction(source, folder, options = {}) {
33320
+ let build;
33321
+ try {
33322
+ ({ build } = await import("esbuild"));
33323
+ } catch (error51) {
33324
+ throw new FunctionBundleError(
33325
+ "FUNCTION_BUNDLE_FAILED",
33326
+ BUNDLE_MESSAGES.esbuildMissing(source.name, causeLine(error51)),
33327
+ { cause: error51 }
33328
+ );
33329
+ }
33330
+ const importMap = readImportMap(
33331
+ source.dir,
33332
+ options.importMap !== void 0 ? options.importMap : options.importMapFile,
33333
+ (file2) => relativeLabel(folder.root, file2)
33334
+ );
33335
+ const state = { missing: [], warnings: [] };
33336
+ let result;
33337
+ try {
33338
+ result = await build({
33339
+ absWorkingDir: folder.root,
33340
+ entryPoints: [source.entry],
33341
+ outfile: join30(source.dir, NARO_USER_MODULE),
33342
+ bundle: true,
33343
+ write: false,
33344
+ format: "esm",
33345
+ platform: "neutral",
33346
+ target: "es2024",
33347
+ conditions: ["workerd", "worker", "browser"],
33348
+ mainFields: ["browser", "module", "main"],
33349
+ external: ["cloudflare:*"],
33350
+ metafile: true,
33351
+ legalComments: "none",
33352
+ logLevel: "silent",
33353
+ plugins: [
33354
+ denoImportsPlugin({ importMap, state, projectRoot: folder.root }),
33355
+ nodeCompatPlugin({
33356
+ compatibilityDate: FUNCTIONS_COMPATIBILITY_DATE,
33357
+ compatibilityFlags: FUNCTIONS_COMPATIBILITY_FLAGS,
33358
+ virtualBase: folder.root
33359
+ })
33360
+ ]
33361
+ });
33362
+ } catch (error51) {
33363
+ throw failure(source.name, error51, state);
33364
+ }
33365
+ if (state.missing.length > 0)
33366
+ throw new FunctionBundleError(
33367
+ "FUNCTION_BUNDLE_FAILED",
33368
+ missingPackagesMessage(state.missing)
33369
+ );
33370
+ const [output] = result.outputFiles;
33371
+ if (output === void 0 || result.outputFiles.length !== 1)
33372
+ throw new FunctionBundleError(
33373
+ "FUNCTION_BUNDLE_FAILED",
33374
+ BUNDLE_MESSAGES.otherBundle(
33375
+ source.name,
33376
+ "esbuild did not produce exactly one file",
33377
+ null
33378
+ )
33379
+ );
33380
+ const bytes2 = output.contents.byteLength;
33381
+ if (bytes2 > (options.maxBytes ?? FUNCTION_BUNDLE_MAX_BYTES)) {
33382
+ const inputs = Object.values(result.metafile.outputs)[0]?.inputs ?? {};
33383
+ const biggest = Object.entries(inputs).sort(([, a], [, b]) => b.bytesInOutput - a.bytesInOutput).slice(0, 5).map(
33384
+ ([path, input]) => `${path} (${input.bytesInOutput.toLocaleString("en-US")} bytes)`
33385
+ ).join(", ");
33386
+ throw new FunctionBundleError(
33387
+ "FUNCTION_BUNDLE_FAILED",
33388
+ BUNDLE_MESSAGES.tooLarge(source.name, bytes2, biggest)
33389
+ );
33390
+ }
33391
+ const compressedBytes = gzipSync(output.contents).byteLength + runtimeCompressedBytes();
33392
+ if (compressedBytes > (options.maxCompressedBytes ?? FUNCTION_COMPRESSED_BUNDLE_MAX_BYTES))
33393
+ throw new FunctionBundleError(
33394
+ "FUNCTION_BUNDLE_FAILED",
33395
+ BUNDLE_MESSAGES.tooLargeCompressed(source.name, compressedBytes)
33396
+ );
33397
+ return {
33398
+ name: source.name,
33399
+ code: output.text,
33400
+ contents: output.contents,
33401
+ bytes: bytes2,
33402
+ compressedBytes,
33403
+ sha256: createHash4("sha256").update(output.contents).digest("hex"),
33404
+ warnings: [...state.warnings]
33405
+ };
33406
+ }
33407
+
33408
+ // ../../packages/functions-bundler/src/boot.ts
33409
+ var BOOT_PATH = "/__naro/boot";
33410
+ var BOOT_TIMEOUT_MS = 3e4;
33411
+ var BOOT_SECRET_PLACEHOLDER = "naro-boot-check-placeholder";
33412
+ var text2 = (value) => ({ type: "text", value });
33413
+ function bindings(name, secretNames) {
33414
+ return {
33415
+ // First, so a name that is also a fixed binding never replaces it.
33416
+ ...Object.fromEntries(
33417
+ secretNames.map((secret) => [secret, text2(BOOT_SECRET_PLACEHOLDER)])
33418
+ ),
33419
+ NARO_PROJECT_ID: text2("00000000-0000-4000-8000-000000000000"),
33420
+ NARO_FUNCTION_NAME: text2(name),
33421
+ NARO_ROOT_DOMAIN: text2("naro.sh"),
33422
+ NARO_URL: text2("https://boot-check.naro.sh"),
33423
+ NARO_ANON_KEY: text2("naro_pk_boot_check"),
33424
+ NARO_SERVICE_KEY: text2("naro_sk_boot_check"),
33425
+ DB: { type: "d1", id: "boot-check" }
33426
+ };
33427
+ }
33428
+ var WORKERD_SERVICE_HEAD = /^service core:user:naro-boot: /;
33429
+ function bootErrorLine(logs, error51) {
33430
+ const logged = logs.find((line2) => line2.includes("Uncaught")) ?? logs.find((line2) => line2.includes("Error"));
33431
+ const raw = logged ?? (error51 instanceof Error ? error51.message : String(error51));
33432
+ const line = raw.split("\n").map((part) => part.trim()).find((part) => part.length > 0) ?? "unknown error";
33433
+ return printable(line.replace(WORKERD_SERVICE_HEAD, ""));
33434
+ }
33435
+ async function bootCheck(name, code, options = {}) {
33436
+ const timeoutMs = options.timeoutMs ?? BOOT_TIMEOUT_MS;
33437
+ let Miniflare;
33438
+ try {
33439
+ ({ Miniflare } = await import("miniflare"));
33440
+ } catch (error51) {
33441
+ throw new FunctionBundleError(
33442
+ "FUNCTION_BOOT_FAILED",
33443
+ BUNDLE_MESSAGES.miniflareMissing(name, causeLine(error51)),
33444
+ { cause: error51 }
33445
+ );
33446
+ }
33447
+ const logs = [];
33448
+ let mf;
33449
+ let timer;
33450
+ try {
33451
+ mf = new Miniflare({
33452
+ handleStructuredLogs: (log2) => logs.push(log2.message),
33453
+ workers: [
33454
+ {
33455
+ config: {
33456
+ // No `type`: the Miniflare wrangler pins (5.20261006) refuses
33457
+ // the key the functions-runtime tests' older one still takes.
33458
+ name: "naro-boot",
33459
+ compatibilityDate: FUNCTIONS_COMPATIBILITY_DATE,
33460
+ compatibilityFlags: [...FUNCTIONS_COMPATIBILITY_FLAGS],
33461
+ manifest: {
33462
+ mainModule: NARO_BOOT_MODULE,
33463
+ modules: {
33464
+ [NARO_BOOT_MODULE]: { type: "esm", contents: NARO_BOOT_SOURCE },
33465
+ [NARO_SHIM_MODULE]: { type: "esm", contents: NARO_SHIM_SOURCE },
33466
+ [NARO_USER_MODULE]: { type: "esm", contents: code }
33467
+ }
33468
+ },
33469
+ env: bindings(name, options.secretNames ?? [])
33470
+ }
33471
+ }
33472
+ ]
33473
+ });
33474
+ const started = mf;
33475
+ const answer = async () => {
33476
+ await started.ready;
33477
+ const worker = await started.getWorker("naro-boot");
33478
+ const response2 = await worker.fetch(`http://boot.local${BOOT_PATH}`);
33479
+ const body2 = await response2.json().catch(() => null);
33480
+ return { response: response2, body: body2 };
33481
+ };
33482
+ const timedOut = new Promise((_, reject) => {
33483
+ timer = setTimeout(() => {
33484
+ reject(
33485
+ new FunctionBundleError(
33486
+ "FUNCTION_BOOT_FAILED",
33487
+ BUNDLE_MESSAGES.bootTimeout(name, timeoutMs)
33488
+ )
33489
+ );
33490
+ }, timeoutMs);
33491
+ });
33492
+ const { response, body } = await Promise.race([answer(), timedOut]);
33493
+ if (response.status !== 200 || body === null)
33494
+ throw new Error(
33495
+ logs[0] ?? `the boot request answered ${String(response.status)}`
33496
+ );
33497
+ if (body.handler !== true)
33498
+ throw new FunctionBundleError(
33499
+ "FUNCTION_BOOT_FAILED",
33500
+ BUNDLE_MESSAGES.noHandler(name)
33501
+ );
33502
+ } catch (error51) {
33503
+ if (error51 instanceof FunctionBundleError) throw error51;
33504
+ throw new FunctionBundleError(
33505
+ "FUNCTION_BOOT_FAILED",
33506
+ BUNDLE_MESSAGES.failedToStart(name, bootErrorLine(logs, error51))
33507
+ );
33508
+ } finally {
33509
+ clearTimeout(timer);
33510
+ await mf?.dispose().catch(() => void 0);
33511
+ }
33512
+ }
33513
+
33514
+ // src/commands/migration.ts
33515
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
33516
+ import { join as join31, relative as relative10 } from "path";
33517
+
33518
+ // src/data-environment.ts
33519
+ var DATA_ENV_MESSAGES = {
33520
+ name: "--env must be production or an environment name.",
33521
+ preview: "--env preview has no data of its own: preview deployments use production's. Drop --env, or name an environment.",
33522
+ projectWide: (command) => `--env is not an option of ${command}: turning the backend on or off applies to every environment.`
33523
+ };
33524
+ function dataEnvironment(flags) {
33525
+ const value = flags.env;
33526
+ if (value === void 0 || value === "production") return null;
33527
+ if (value === "preview")
33528
+ throw new NaroError("VALIDATION_FAILED", DATA_ENV_MESSAGES.preview);
33529
+ if (environmentSlugProblem(value) !== null)
33530
+ throw new NaroError("VALIDATION_FAILED", DATA_ENV_MESSAGES.name);
33531
+ return value;
33532
+ }
33533
+ async function dataClient(context) {
33534
+ return (await context.client()).inEnvironment(dataEnvironment(context.flags));
33535
+ }
33536
+ function databaseName(environment) {
33537
+ return environment === null ? "the project database" : `the ${environment} environment's database`;
33538
+ }
33539
+ function enableBackendCommand(environment) {
33540
+ return environment === null ? "naro backend enable" : `naro environments provision ${environment}`;
33541
+ }
33542
+ function envFlag(environment) {
33543
+ return environment === null ? "" : ` --env ${environment}`;
33544
+ }
33545
+ function forEnvironment(text3, environment) {
33546
+ return environmentGuidance(text3, environment);
33547
+ }
33548
+
33549
+ // src/prompt.ts
33550
+ import { createInterface as createInterface2 } from "readline";
33551
+ import { Writable } from "stream";
33552
+ function confirmHint(defaultYes) {
33553
+ return defaultYes ? "(Y/n)" : "(y/N)";
33554
+ }
33555
+ function readConfirmAnswer(answer, defaultYes) {
33556
+ const normalized2 = answer.trim().toLowerCase();
33557
+ if (normalized2 === "") return defaultYes;
33558
+ if (normalized2 === "y" || normalized2 === "yes") return true;
33559
+ if (!defaultYes) return false;
33560
+ if (normalized2 === "n" || normalized2 === "no") return false;
33561
+ return null;
33562
+ }
33563
+ function isInteractive() {
33564
+ return process.stdin.isTTY === true && process.stdout.isTTY === true;
33565
+ }
33566
+ async function readStdin() {
33567
+ let data = "";
33568
+ for await (const chunk of process.stdin) data += String(chunk);
33569
+ return data.replace(/\r?\n$/, "");
33570
+ }
33571
+ var TtyPrompter = class {
33572
+ async ask(question) {
33573
+ const rl = createInterface2({
33574
+ input: process.stdin,
33575
+ output: process.stdout
33576
+ });
33577
+ try {
33578
+ return await new Promise(
33579
+ (resolve15) => rl.question(question, resolve15)
33580
+ );
33581
+ } finally {
33582
+ rl.close();
33583
+ }
33584
+ }
33585
+ async askHidden(question) {
33586
+ let muted = false;
33587
+ const output = new Writable({
33588
+ write(chunk, _enc, done) {
33589
+ if (!muted) process.stdout.write(chunk);
33590
+ done();
33591
+ }
33592
+ });
33593
+ const rl = createInterface2({
33594
+ input: process.stdin,
33595
+ output,
33596
+ terminal: true
33597
+ });
33598
+ try {
33599
+ const answer = new Promise(
33600
+ (resolve15) => rl.question(question, resolve15)
33601
+ );
33602
+ muted = true;
33603
+ const value = await answer;
33604
+ process.stdout.write("\n");
33605
+ return value;
33606
+ } finally {
33607
+ rl.close();
33608
+ }
33609
+ }
33610
+ async confirm(question, options = {}) {
33611
+ const defaultYes = options.defaultYes ?? false;
33612
+ for (; ; ) {
33613
+ const read = readConfirmAnswer(
33614
+ await this.ask(`${question} ${confirmHint(defaultYes)} `),
33615
+ defaultYes
33616
+ );
33617
+ if (read !== null) return read;
33618
+ }
33619
+ }
33620
+ async select(question, options) {
33621
+ process.stdout.write(`${question}
33622
+ `);
33623
+ options.forEach((option, index) => {
33624
+ process.stdout.write(` ${String(index + 1)}. ${option}
33625
+ `);
33626
+ });
33627
+ for (; ; ) {
33628
+ const answer = Number.parseInt(
33629
+ (await this.ask(`Choose 1-${String(options.length)}: `)).trim(),
33630
+ 10
33631
+ );
33632
+ if (Number.isInteger(answer) && answer >= 1 && answer <= options.length)
33633
+ return answer - 1;
33634
+ }
33635
+ }
33636
+ };
33637
+ var NonInteractivePrompter = class {
33638
+ constructor(assumeYes) {
33639
+ this.assumeYes = assumeYes;
33640
+ }
33641
+ refuse(question) {
33642
+ throw new NaroError(
33643
+ "VALIDATION_FAILED",
33644
+ `Interactive input required (${question.trim()}). Pass the value via flags/stdin or run without --json in a terminal.`
33645
+ );
33646
+ }
33647
+ async ask(question) {
33648
+ this.refuse(question);
33649
+ }
33650
+ async askHidden(question) {
33651
+ this.refuse(question);
33652
+ }
33653
+ async confirm() {
33654
+ return this.assumeYes;
33655
+ }
33656
+ async select(question) {
33657
+ this.refuse(question);
33658
+ }
33659
+ };
33660
+ function createPrompter(options) {
33661
+ if (options.yes || options.json || !isInteractive())
33662
+ return new NonInteractivePrompter(options.yes);
33663
+ return new TtyPrompter();
33664
+ }
33665
+
33666
+ // src/commands/confirm.ts
33667
+ function cannotAsk(context) {
33668
+ return context.flags.json || !isInteractive();
33669
+ }
33670
+ async function confirmOrAbort(context, question) {
33671
+ if (context.flags.yes) return;
33672
+ if (cannotAsk(context)) {
33673
+ throw new NaroError(
33674
+ "CONFIRMATION_REQUIRED",
33675
+ `${question} Re-run with --yes to confirm.`
33676
+ );
33677
+ }
33678
+ const confirmed = await context.prompter.confirm(question);
33679
+ if (!confirmed) throw new NaroError("CANCELED", "Canceled.");
33680
+ }
33681
+
33682
+ // src/commands/migration.ts
33683
+ var processStdin = {
33684
+ stdinIsTty: () => process.stdin.isTTY === true,
33685
+ readStdin
33686
+ };
33687
+ function migrationsDir(context) {
33688
+ return resolveMigrationsDir({
33689
+ baseDir: context.cwd,
33690
+ rootDirectory: context.flags.root,
33691
+ dir: context.flags.dir
33692
+ });
33693
+ }
33694
+ function relativeToCwd(context, path) {
33695
+ const rel = relative10(context.cwd, path);
33696
+ return rel === "" ? "." : rel;
33697
+ }
33698
+ async function appliedMigrations(client, projectId) {
33699
+ try {
33700
+ return await client.db.migrations(projectId);
33701
+ } catch (error51) {
33702
+ if (isNaroError(error51) && error51.code === "DATABASE_NOT_READY") return [];
33703
+ throw error51;
33704
+ }
33705
+ }
33706
+ var UNPRINTABLE2 = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu;
33707
+ function printable2(text3) {
33708
+ return text3.replace(UNPRINTABLE2, "?");
33709
+ }
33710
+ function isPrintable(text3) {
33711
+ return printable2(text3) === text3;
33712
+ }
33713
+ var UNSHOWN_WARNING_LINE = "(a line of this warning has characters the terminal cannot show; run with --json to see it exactly)";
33714
+ function warningLines(message) {
33715
+ return message.split("\n").map(
33716
+ (line, index) => index === 0 ? `\u26A0 ${printable2(line)}` : ` ${isPrintable(line) ? line : UNSHOWN_WARNING_LINE}`
33717
+ );
33718
+ }
33719
+ function policyProblems(dir, names) {
33720
+ return names.flatMap((name) => {
33721
+ const split2 = splitStatements(readFileSync10(join31(dir, name), "utf8"));
33722
+ if (!split2.ok) return [];
33723
+ const planned = planPolicyMigration(
33724
+ split2.statements.map((statement2) => statement2.text)
33725
+ );
33726
+ return planned.ok ? [] : [{ migration: name, message: planned.message }];
33727
+ });
33728
+ }
33729
+ function warningLine(warning) {
33730
+ if (warning === "out-of-order")
33731
+ return " \u26A0 older than an applied migration \u2014 db push will still apply it";
33732
+ if (warning === "ledger-name-missing-extension")
33733
+ return " \u26A0 recorded without .sql in the ledger";
33734
+ return null;
33735
+ }
33736
+ async function runMigrationNew(context, deps = processStdin) {
33737
+ const [name] = context.positionalOrThrow(
33738
+ 1,
33739
+ "Usage: naro migration new <name>"
33740
+ );
33741
+ const dir = migrationsDir(context);
33742
+ const fileName = nextMigrationFileName(
33743
+ listMigrationFiles(dir),
33744
+ name
33745
+ );
33746
+ mkdirSync3(dir, { recursive: true });
33747
+ const piped = !deps.stdinIsTty() ? await deps.readStdin() : "";
33748
+ const fromStdin = piped.length > 0;
33749
+ const body = fromStdin ? piped.endsWith("\n") ? piped : `${piped}
33750
+ ` : `-- Migration: ${fileName}
33751
+ `;
33752
+ const path = join31(dir, fileName);
33753
+ writeFileSync3(path, body, { flag: "wx" });
33754
+ const relPath = relativeToCwd(context, path);
33755
+ context.output.result({ file: fileName, path: relPath, fromStdin }, [
33756
+ `\u2705 Created ${relPath}`
33757
+ ]);
33758
+ }
33759
+ async function runMigrationList(context) {
33760
+ const client = await dataClient(context);
33761
+ const projectId = await context.resolveProjectId();
33762
+ const dir = migrationsDir(context);
33763
+ const local = listMigrationFiles(dir);
33764
+ const ledger = await appliedMigrations(client, projectId);
33765
+ const migrations = compareMigrations(local, ledger);
33766
+ const relDir = relativeToCwd(context, dir);
33767
+ const lines = migrations.length === 0 ? ["No migrations yet. Create one with `naro migration new <name>`."] : [
33768
+ `Migrations in ${relDir} (${String(migrations.length)}):`,
33769
+ ...migrations.flatMap((row) => {
33770
+ const line = ` ${row.status.padEnd(12)}${printable2(row.name)}${row.appliedAt ? ` ${printable2(row.appliedAt)}` : ""}`;
33771
+ const warning = warningLine(row.warning);
33772
+ return warning ? [line, warning] : [line];
33773
+ })
33774
+ ];
33775
+ context.output.result({ projectId, dir: relDir, migrations }, lines);
33776
+ }
33777
+ async function applyMigrationFiles(context, client, projectId, dir, names) {
33778
+ const applied = [];
33779
+ const warnings = [];
33780
+ for (const name of names) {
33781
+ const sql = readFileSync10(join31(dir, name), "utf8");
33782
+ let answer;
33783
+ try {
33784
+ answer = await client.db.applyMigration(projectId, { name, sql });
33785
+ } catch (error51) {
33786
+ if (!isNaroError(error51)) throw error51;
33787
+ for (const message of serverWarnings(error51.details))
33788
+ for (const line of warningLines(message)) context.output.warn(line);
33789
+ const shown = context.output.json ? name : printable2(name);
33790
+ throw new NaroError(error51.code, `${shown}: ${error51.message}`, {
33791
+ ...error51.status === void 0 ? {} : { status: error51.status },
33792
+ details: {
33793
+ ...error51.details,
33794
+ migration: name,
33795
+ applied,
33796
+ appliedWarnings: warnings
33797
+ },
33798
+ cause: error51
33799
+ });
33800
+ }
33801
+ context.output.log(`\u2713 ${printable2(name)}`);
33802
+ applied.push(name);
33803
+ for (const message of answer.warnings) {
33804
+ warnings.push({ migration: name, message });
33805
+ for (const line of warningLines(message)) context.output.warn(line);
33806
+ }
33807
+ }
33808
+ return { applied, warnings };
33809
+ }
33810
+ function serverWarnings(details) {
33811
+ const warnings = details?.warnings;
33812
+ return Array.isArray(warnings) ? warnings.filter(
33813
+ (warning) => typeof warning === "string"
33814
+ ) : [];
33815
+ }
33816
+ var MIGRATION_NAME_RE = /^[A-Za-z0-9_.-]{1,200}\.sql$/;
33817
+ var LEDGER_DDL = "CREATE TABLE IF NOT EXISTS d1_migrations (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE, applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)";
33818
+ var LEDGER_INSERT = "INSERT INTO d1_migrations (name) SELECT ? WHERE NOT EXISTS (SELECT 1 FROM d1_migrations WHERE name = ?)";
33819
+ var LEDGER_DELETE = "DELETE FROM d1_migrations WHERE name IN (?, ?)";
33820
+ function withoutSuffix(key) {
33821
+ return key.slice(0, -".sql".length);
33822
+ }
33823
+ async function runMigrationRepair(context) {
33824
+ const [name] = context.positionalOrThrow(
33825
+ 1,
33826
+ "Usage: naro migration repair <name> --status applied|reverted"
33827
+ );
33828
+ const key = name;
33829
+ if (!MIGRATION_NAME_RE.test(key))
33830
+ throw new NaroError(
33831
+ "VALIDATION_FAILED",
33832
+ "name must end with .sql and contain only letters, digits, _ . -"
33833
+ );
33834
+ const status = context.flags.status;
33835
+ if (status !== "applied" && status !== "reverted")
33836
+ throw new NaroError(
33837
+ "VALIDATION_FAILED",
33838
+ "Pass --status applied or --status reverted."
33839
+ );
33840
+ const client = await dataClient(context);
33841
+ const projectId = await context.resolveProjectId();
33842
+ const ledger = await appliedMigrations(client, projectId);
33843
+ const recorded = ledger.some(
33844
+ (row) => row.name === key || row.name === withoutSuffix(key)
33845
+ );
33846
+ const nothingToDo = status === "applied" ? `${key} was already applied; nothing to do.` : `${key} was not in the ledger; nothing to do.`;
33847
+ if (status === "applied" ? recorded : !recorded) {
33848
+ context.output.warn(nothingToDo);
33849
+ context.output.result({ name: key, status, changed: false });
33850
+ return;
33851
+ }
33852
+ await confirmOrAbort(
33853
+ context,
33854
+ status === "applied" ? `Mark ${key} as applied in ${databaseName(dataEnvironment(context.flags))}'s ledger? Its SQL is not run.` : `Remove ${key} from ${databaseName(dataEnvironment(context.flags))}'s ledger? Its SQL is not rolled back.`
33855
+ );
33856
+ if (status === "applied" && ledger.length === 0)
33857
+ await client.db.query(projectId, { sql: LEDGER_DDL });
33858
+ const answer = await client.db.query(projectId, {
33859
+ sql: status === "applied" ? LEDGER_INSERT : LEDGER_DELETE,
33860
+ params: status === "applied" ? [key, key] : [key, withoutSuffix(key)]
33861
+ });
33862
+ const changed = (answer.statements[0]?.meta.changes ?? 0) > 0;
33863
+ if (!changed) {
33864
+ context.output.warn(nothingToDo);
33865
+ context.output.result({ name: key, status, changed: false });
33866
+ return;
33867
+ }
33868
+ context.output.result({ name: key, status, changed: true }, [
33869
+ status === "applied" ? `\u2713 Marked ${key} as applied.` : `\u2713 Removed ${key} from the ledger.`
33870
+ ]);
33871
+ }
33872
+ async function runMigrationUp(context) {
33873
+ const client = await dataClient(context);
33874
+ const projectId = await context.resolveProjectId();
33875
+ const dir = migrationsDir(context);
33876
+ const local = listMigrationFiles(dir);
33877
+ const ledger = await appliedMigrations(client, projectId);
33878
+ const pending = compareMigrations(local, ledger).filter((row) => row.status === "pending").map((row) => row.name);
33879
+ if (pending.length === 0) {
33880
+ context.output.result({ projectId, applied: [], pending: [] }, [
33881
+ "No pending migrations."
33882
+ ]);
33883
+ return;
33884
+ }
33885
+ if (context.flags.dryRun) {
33886
+ const problems2 = policyProblems(dir, pending);
33887
+ context.output.result({ projectId, dryRun: true, pending, problems: problems2 }, [
33888
+ `Pending migrations (${String(pending.length)}):`,
33889
+ ...pending.map((name) => ` ${printable2(name)}`),
33890
+ ...problems2.map(
33891
+ (problem) => `${printable2(problem.migration)}: ${printable2(problem.message)}`
33892
+ )
33893
+ ]);
33894
+ if (problems2.length > 0) process.exitCode = 1;
33895
+ return;
33896
+ }
33897
+ context.output.log(`Pending migrations (${String(pending.length)}):`);
33898
+ for (const name of pending) context.output.log(` ${printable2(name)}`);
33899
+ await confirmOrAbort(
33900
+ context,
33901
+ `Apply ${String(pending.length)} migration(s) to ${databaseName(dataEnvironment(context.flags))}? Each file is applied all-or-nothing; a failure stops the run.`
33902
+ );
33903
+ const { applied, warnings } = await applyMigrationFiles(
33904
+ context,
33905
+ client,
33906
+ projectId,
33907
+ dir,
33908
+ pending
33909
+ );
33910
+ context.output.result({ projectId, applied, pending: [], warnings }, [
33911
+ `\u2705 Applied ${String(applied.length)} migration(s).`
33912
+ ]);
33913
+ }
33914
+
33915
+ // src/functions/retry.ts
33916
+ var FUNCTION_RETRIES = 3;
33917
+ var FUNCTION_BUSY_WAIT_MS = 5e3;
33918
+ var FUNCTION_RATE_LIMIT_DEFAULT_SECONDS = 60;
33919
+ var FUNCTION_RATE_LIMIT_MAX_SECONDS = 300;
33920
+ function defaultSleep(ms) {
33921
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
33922
+ }
33923
+ function retryAfterSeconds(error51) {
33924
+ const value = error51.details?.retryAfter;
33925
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(Math.ceil(value), FUNCTION_RATE_LIMIT_MAX_SECONDS) : FUNCTION_RATE_LIMIT_DEFAULT_SECONDS;
33926
+ }
33927
+ async function withFunctionRetries(op, name, io) {
33928
+ const rateRetries = io.rateLimitRetries ?? FUNCTION_RETRIES;
33929
+ const busyRetries = io.busyRetries ?? FUNCTION_RETRIES;
33930
+ let rate = 0;
33931
+ let busy = 0;
33932
+ for (; ; ) {
33933
+ try {
33934
+ return await op();
33935
+ } catch (error51) {
33936
+ if (!isNaroError(error51)) throw error51;
33937
+ if (error51.code === "FUNCTIONS_RATE_LIMITED" && rate < rateRetries) {
33938
+ rate += 1;
33939
+ const seconds = retryAfterSeconds(error51);
33940
+ io.log(
33941
+ `\u23F3 Cloudflare is rate limiting function uploads; trying ${name} again in ${String(seconds)} seconds (${String(rate)}/${String(rateRetries)}).`
33942
+ );
33943
+ await io.sleep(seconds * 1e3);
33944
+ continue;
33945
+ }
33946
+ if (error51.code === "FUNCTION_BUSY" && busy < busyRetries) {
33947
+ busy += 1;
33948
+ io.log(
33949
+ `\u23F3 ${name} is being changed right now; trying again in ${String(FUNCTION_BUSY_WAIT_MS / 1e3)} seconds (${String(busy)}/${String(busyRetries)}).`
33950
+ );
33951
+ await io.sleep(FUNCTION_BUSY_WAIT_MS);
33952
+ continue;
33953
+ }
33954
+ throw error51;
33955
+ }
33956
+ }
33957
+ }
33958
+
33959
+ // src/functions/deploy.ts
33960
+ var PER_FUNCTION_CODES = /* @__PURE__ */ new Set([
33961
+ "VALIDATION_FAILED",
33962
+ "FUNCTION_BUNDLE_FAILED",
33963
+ "FUNCTION_BOOT_FAILED",
33964
+ "FUNCTION_UPLOAD_FAILED",
33965
+ "BUNDLE_TOO_LARGE",
33966
+ "BUNDLE_MISSING",
33967
+ "BUNDLE_MISMATCH",
33968
+ "FUNCTION_LIMIT",
33969
+ "FUNCTION_BUSY",
33970
+ "FUNCTION_NOT_FOUND",
33971
+ "VERSION_NOT_FOUND",
33972
+ "VERSION_NOT_DEPLOYABLE",
33973
+ "FUNCTION_DEPLOY_FAILED",
33974
+ "FUNCTION_DEPLOY_INCOMPLETE",
33975
+ "FUNCTIONS_RATE_LIMITED"
33976
+ ]);
33977
+ function assertFunctionsNode(version3 = process.versions.node) {
33978
+ const major = Number(version3.split(".")[0]);
33979
+ if (!(major >= 22))
33980
+ throw new NaroError(
33981
+ "NODE_VERSION_UNSUPPORTED",
33982
+ `naro functions needs Node.js 22 or later (found ${version3}).`
33983
+ );
33984
+ }
33985
+ function asNaroError(error51) {
33986
+ return error51 instanceof FunctionBundleError ? new NaroError(error51.code, error51.message) : error51;
33987
+ }
33988
+ var UPLOAD_TIMEOUT_DEFAULT_MS = 15 * 6e4;
33989
+ var UPLOAD_TIMEOUT_MIN_MS = 6e4;
33990
+ var UPLOAD_TIMEOUT_SLACK_MS = 3e4;
33991
+ function uploadTimeoutMs(upload, now = Date.now()) {
33992
+ const expires = typeof upload.expiresAt === "string" ? Date.parse(upload.expiresAt) : NaN;
33993
+ if (Number.isNaN(expires)) return UPLOAD_TIMEOUT_DEFAULT_MS;
33994
+ return Math.max(expires - now, UPLOAD_TIMEOUT_MIN_MS) + UPLOAD_TIMEOUT_SLACK_MS;
33995
+ }
33996
+ var SECRETS_LIST_TIMEOUT_MS = 45e3;
33997
+ var FUNCTION_CALL_TIMEOUT_MS = 12e4;
33998
+ var deadlineReached = (name, deadlineMs) => `Deploying ${name} reached the ${String(deadlineMs / 1e3)}-second limit before it went live; the live version did not change. Try again.`;
33999
+ function budgetOf(options) {
34000
+ const { deadlineMs } = options;
34001
+ if (deadlineMs === void 0) return null;
34002
+ const now = options.now ?? Date.now;
34003
+ const end = now() + deadlineMs;
34004
+ return {
34005
+ left(name, cap) {
34006
+ const left = end - now();
34007
+ if (left <= 0)
34008
+ throw new NaroError("TIMEOUT", deadlineReached(name, deadlineMs));
34009
+ return Math.min(cap, left);
34010
+ }
34011
+ };
34012
+ }
34013
+ var bootSeconds = (ms) => Math.max(1e3, Math.floor(ms / 1e3) * 1e3);
34014
+ async function putBundle(doFetch, name, upload, contents, timeoutMs) {
34015
+ const headers = Object.fromEntries(
34016
+ Object.entries(upload.headers).filter(
34017
+ ([header]) => header.toLowerCase() !== "content-length"
34018
+ )
34019
+ );
34020
+ const again = `Run naro functions deploy ${name} again.`;
34021
+ const signal = AbortSignal.timeout(timeoutMs);
34022
+ let response;
34023
+ try {
34024
+ response = await doFetch(upload.url, {
34025
+ method: upload.method,
34026
+ headers,
34027
+ body: contents,
34028
+ signal
34029
+ });
34030
+ } catch (cause) {
34031
+ const timedOut = signal.aborted || cause instanceof Error && cause.name === "TimeoutError";
34032
+ throw new NaroError(
34033
+ "FUNCTION_UPLOAD_FAILED",
34034
+ `Uploading the bundle of ${name} failed (${timedOut ? "timed out" : "network error"}). ${again}`,
34035
+ { cause }
34036
+ );
34037
+ }
34038
+ if (!response.ok)
34039
+ throw new NaroError(
34040
+ "FUNCTION_UPLOAD_FAILED",
34041
+ `Uploading the bundle of ${name} failed (${String(response.status)}). ${again}`,
34042
+ { status: response.status }
34043
+ );
34044
+ }
34045
+ async function projectSecretNames(client, projectId, timeoutMs) {
34046
+ try {
34047
+ const secrets = timeoutMs === void 0 ? await client.functions.secrets(projectId) : await client.functions.secrets(projectId, { timeoutMs });
34048
+ return secrets.map((secret) => secret.name);
34049
+ } catch {
34050
+ return [];
34051
+ }
34052
+ }
34053
+ async function deployOne(options, folder, name, importMap, secretNames, io, budget) {
34054
+ const steps = options.steps ?? { bundle: bundleFunction, boot: bootCheck };
34055
+ const { client, projectId } = options;
34056
+ const call = () => budget ? { timeoutMs: budget.left(name, FUNCTION_CALL_TIMEOUT_MS) } : null;
34057
+ io.log(`\u23F3 Deploying ${name}\u2026`);
34058
+ try {
34059
+ const source = readFunctionSource(folder, name);
34060
+ const bundle = await steps.bundle(source, folder, { importMap });
34061
+ for (const warning of bundle.warnings) io.log(warning);
34062
+ if (!options.skipCheck)
34063
+ await steps.boot(
34064
+ name,
34065
+ bundle.code,
34066
+ budget ? {
34067
+ secretNames,
34068
+ timeoutMs: bootSeconds(budget.left(name, BOOT_TIMEOUT_MS))
34069
+ } : { secretNames }
34070
+ );
34071
+ const verifyJwt = options.verifyJwt ?? source.verifyJwt ?? true;
34072
+ const request2 = {
34073
+ size: bundle.bytes,
34074
+ sha256: bundle.sha256,
34075
+ verifyJwt,
34076
+ entrypoint: source.entrypoint,
34077
+ ...options.cliVersion ? { cliVersion: options.cliVersion } : {}
34078
+ };
34079
+ const created = await withFunctionRetries(
34080
+ () => {
34081
+ const limit = call();
34082
+ return limit ? client.functions.createVersion(projectId, name, request2, limit) : client.functions.createVersion(projectId, name, request2);
34083
+ },
34084
+ name,
34085
+ io
34086
+ );
34087
+ const urlLife = uploadTimeoutMs(created.upload);
34088
+ await putBundle(
34089
+ options.fetch ?? fetch,
34090
+ name,
34091
+ created.upload,
34092
+ bundle.contents,
34093
+ budget ? budget.left(name, urlLife) : urlLife
34094
+ );
34095
+ const live = await withFunctionRetries(
34096
+ () => {
34097
+ const limit = call();
34098
+ return limit ? client.functions.deploy(projectId, name, created.version.id, limit) : client.functions.deploy(projectId, name, created.version.id);
34099
+ },
34100
+ name,
34101
+ io
34102
+ );
34103
+ io.log(
34104
+ `\u2705 Deployed ${name} (v${String(live.version ?? created.version.number)}) \u2014 ${live.url}`
34105
+ );
34106
+ return {
34107
+ name,
34108
+ version: live.version,
34109
+ url: live.url,
34110
+ verifyJwt: live.verifyJwt
34111
+ };
34112
+ } catch (error51) {
34113
+ throw asNaroError(error51);
34114
+ }
34115
+ }
34116
+ function readFlagImportMap(options, folder) {
34117
+ if (options.importMap === void 0) return void 0;
34118
+ const file2 = resolve13(options.cwd, options.importMap);
34119
+ try {
34120
+ return readImportMapFile(
34121
+ file2,
34122
+ relative11(folder.root, file2).split(sep10).join("/")
34123
+ );
34124
+ } catch (error51) {
34125
+ throw asNaroError(error51);
34126
+ }
34127
+ }
34128
+ function withProgress(error51, deployed, failures) {
34129
+ return new NaroError(error51.code, error51.message, {
34130
+ ...error51.status === void 0 ? {} : { status: error51.status },
34131
+ details: { ...error51.details, deployed, failures },
34132
+ cause: error51
34133
+ });
34134
+ }
34135
+ async function deployFunctions(options) {
34136
+ assertFunctionsNode(options.nodeVersion);
34137
+ const budget = budgetOf(options);
34138
+ const io = {
34139
+ sleep: options.sleep ?? defaultSleep,
34140
+ log: options.log ?? (() => {
34141
+ }),
34142
+ rateLimitRetries: options.rateLimitRetries,
34143
+ busyRetries: options.busyRetries
34144
+ };
34145
+ const folder = functionsFolder({
34146
+ cwd: options.cwd,
34147
+ root: options.root,
34148
+ dir: options.dir
34149
+ });
34150
+ let names;
34151
+ try {
34152
+ names = options.names && options.names.length > 0 ? [...new Set(options.names)] : listFunctionNames(folder);
34153
+ } catch (error51) {
34154
+ throw asNaroError(error51);
34155
+ }
34156
+ const importMap = readFlagImportMap(options, folder);
34157
+ const warning = configTomlWarning(folder);
34158
+ if (warning !== null) io.log(warning);
34159
+ const [only] = names;
34160
+ const secretNames = options.skipCheck ? [] : await projectSecretNames(
34161
+ options.client,
34162
+ options.projectId,
34163
+ budget?.left(only ?? "", SECRETS_LIST_TIMEOUT_MS)
34164
+ );
34165
+ if (names.length === 1 && only !== void 0)
34166
+ return {
34167
+ deployed: [
34168
+ await deployOne(
34169
+ options,
34170
+ folder,
34171
+ only,
34172
+ importMap,
34173
+ secretNames,
34174
+ io,
34175
+ budget
34176
+ )
34177
+ ]
34178
+ };
34179
+ const deployed = [];
34180
+ const failures = [];
34181
+ for (const name of names) {
34182
+ try {
34183
+ deployed.push(
34184
+ await deployOne(
34185
+ options,
34186
+ folder,
34187
+ name,
34188
+ importMap,
34189
+ secretNames,
34190
+ io,
34191
+ budget
34192
+ )
34193
+ );
34194
+ } catch (error51) {
34195
+ if (!isNaroError(error51)) throw error51;
34196
+ if (!PER_FUNCTION_CODES.has(error51.code))
34197
+ throw withProgress(error51, deployed, failures);
34198
+ failures.push({ name, code: error51.code, message: error51.message });
34199
+ io.log(`\u2717 ${name}: ${printable2(error51.message)}`);
34200
+ }
34201
+ }
34202
+ if (failures.length > 0)
34203
+ throw new NaroError(
34204
+ "FUNCTIONS_DEPLOY_PARTIAL",
34205
+ `Deployed ${String(deployed.length)} of ${String(names.length)} functions. Failed: ${failures.map((failure2) => `${failure2.name} (${failure2.code})`).join(", ")}.`,
34206
+ { details: { deployed, failures } }
34207
+ );
34208
+ return { deployed };
34209
+ }
34210
+
32416
34211
  // src/deploy.ts
32417
- function parseDotenv2(text2) {
32418
- return parseDotenv(text2);
34212
+ function parseDotenv2(text3) {
34213
+ return parseDotenv(text3);
32419
34214
  }
32420
34215
  function readProjectEnv2(dir) {
32421
34216
  return readProjectEnv(dir);
@@ -32438,7 +34233,7 @@ function eventsObserver(cp3, deploymentId, token, fetchImpl = fetch, logIngestUr
32438
34233
  } catch (error51) {
32439
34234
  lastError = error51;
32440
34235
  await new Promise(
32441
- (resolve12) => setTimeout(resolve12, 500 * (attempt + 1))
34236
+ (resolve15) => setTimeout(resolve15, 500 * (attempt + 1))
32442
34237
  );
32443
34238
  }
32444
34239
  }
@@ -32514,19 +34309,19 @@ function slugify2(value) {
32514
34309
  async function projectName(sourceDir) {
32515
34310
  try {
32516
34311
  const pkg = JSON.parse(
32517
- await readFile15(join26(sourceDir, "package.json"), "utf8")
34312
+ await readFile15(join32(sourceDir, "package.json"), "utf8")
32518
34313
  );
32519
34314
  if (pkg.name) return pkg.name;
32520
34315
  } catch {
32521
34316
  }
32522
- return basename4(sourceDir);
34317
+ return basename5(sourceDir);
32523
34318
  }
32524
34319
  function resolveBin(name) {
32525
- let dir = dirname6(fileURLToPath(import.meta.url));
34320
+ let dir = dirname10(fileURLToPath4(import.meta.url));
32526
34321
  for (; ; ) {
32527
- const candidate = join26(dir, "node_modules", ".bin", name);
32528
- if (existsSync7(candidate)) return candidate;
32529
- const parent = dirname6(dir);
34322
+ const candidate = join32(dir, "node_modules", ".bin", name);
34323
+ if (existsSync10(candidate)) return candidate;
34324
+ const parent = dirname10(dir);
32530
34325
  if (parent === dir) return name;
32531
34326
  dir = parent;
32532
34327
  }
@@ -32591,7 +34386,7 @@ function workingTreeNotices(copy) {
32591
34386
  }
32592
34387
  function localDependencies(sourceDir, say = () => void 0) {
32593
34388
  return {
32594
- createWorkspace: () => mkdtemp2(join26(tmpdir2(), "naro-build-")),
34389
+ createWorkspace: () => mkdtemp2(join32(tmpdir2(), "naro-build-")),
32595
34390
  removeWorkspace: (path) => rm5(path, { recursive: true, force: true }),
32596
34391
  async runCommand(spec, observer) {
32597
34392
  if (spec.command === "git" && spec.args[0] === "clone") {
@@ -32641,7 +34436,7 @@ async function deployDirectory(sourceDir, options, log2) {
32641
34436
  "Pass production: true for production; preview is the default."
32642
34437
  );
32643
34438
  const surface = production ? "production" : environment ?? "preview";
32644
- const appRoot = options.rootDirectory ? resolve11(sourceDir, options.rootDirectory) : sourceDir;
34439
+ const appRoot = options.rootDirectory ? resolve14(sourceDir, options.rootDirectory) : sourceDir;
32645
34440
  const framework = detectFramework2(appRoot);
32646
34441
  if (!framework.deployable && !options.force) {
32647
34442
  throw new NaroError(
@@ -32661,6 +34456,7 @@ async function deployDirectory(sourceDir, options, log2) {
32661
34456
  const client = new NaroClient({
32662
34457
  baseUrl: cpUrl,
32663
34458
  getAccessToken: () => auth.getAccessToken(),
34459
+ clientName: `naro-cli/${version2()}`,
32664
34460
  ...options.fetch ? { fetch: options.fetch } : {}
32665
34461
  });
32666
34462
  if (environment !== void 0 && options.projectId)
@@ -32844,12 +34640,10 @@ function deploymentUrl(detail, ctx, production) {
32844
34640
  }
32845
34641
 
32846
34642
  export {
32847
- environmentGuidance,
34643
+ isFunctionName,
32848
34644
  parseGitHubRemote,
32849
34645
  schemaMigrationTitle,
32850
34646
  projectPath,
32851
- splitStatements,
32852
- environmentSlugProblem,
32853
34647
  ANALYTICS_FILTER_KEYS,
32854
34648
  NaroError,
32855
34649
  promoteTargetUnsupported,
@@ -32907,7 +34701,6 @@ export {
32907
34701
  parsePolicyStatement,
32908
34702
  splitPolicyStatements,
32909
34703
  STORAGE_SUBQUERIES_SQL,
32910
- planPolicyMigration,
32911
34704
  unreadablePolicyComment,
32912
34705
  parseRedirectEntry,
32913
34706
  formatRedirectEntry,
@@ -32919,10 +34712,8 @@ export {
32919
34712
  ensureGitignoreHasNaro,
32920
34713
  countLintedTables,
32921
34714
  lintSchema,
32922
- resolveMigrationsDir,
32923
34715
  listMigrationFiles,
32924
34716
  nextMigrationFileName,
32925
- compareMigrations,
32926
34717
  pendingMigrationNames,
32927
34718
  migrationsPendingError,
32928
34719
  migrationNameMismatch,
@@ -32941,6 +34732,40 @@ export {
32941
34732
  promptForMissingEnv,
32942
34733
  pullEnv,
32943
34734
  detectGitInfo,
34735
+ version2 as version,
34736
+ BUNDLE_MESSAGES,
34737
+ functionsFolder,
34738
+ parseJsonc2 as parseJsonc,
34739
+ DATA_ENV_MESSAGES,
34740
+ dataEnvironment,
34741
+ dataClient,
34742
+ databaseName,
34743
+ enableBackendCommand,
34744
+ envFlag,
34745
+ forEnvironment,
34746
+ isInteractive,
34747
+ readStdin,
34748
+ createPrompter,
34749
+ cannotAsk,
34750
+ confirmOrAbort,
34751
+ migrationsDir,
34752
+ relativeToCwd,
34753
+ appliedMigrations,
34754
+ printable2 as printable,
34755
+ isPrintable,
34756
+ UNSHOWN_WARNING_LINE,
34757
+ warningLines,
34758
+ policyProblems,
34759
+ runMigrationNew,
34760
+ runMigrationList,
34761
+ applyMigrationFiles,
34762
+ runMigrationRepair,
34763
+ runMigrationUp,
34764
+ defaultSleep,
34765
+ retryAfterSeconds,
34766
+ withFunctionRetries,
34767
+ assertFunctionsNode,
34768
+ deployFunctions,
32944
34769
  parseDotenv2 as parseDotenv,
32945
34770
  readProjectEnv2 as readProjectEnv,
32946
34771
  eventsObserver,