@xylex-group/athena 3.1.0 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +17 -1
  2. package/dist/admin.cjs +55 -1
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.d.cts +32 -8
  5. package/dist/admin.d.ts +32 -8
  6. package/dist/admin.js +54 -2
  7. package/dist/admin.js.map +1 -1
  8. package/dist/athena-auth-url-C1FbVmN6.d.cts +200 -0
  9. package/dist/athena-auth-url-C1FbVmN6.d.ts +200 -0
  10. package/dist/{athena-request-headers-C7Jy-c_D.d.ts → athena-request-headers-BnFN2mbd.d.cts} +49 -201
  11. package/dist/{athena-request-headers-DujFFyMU.d.cts → athena-request-headers-Dwdkq2WR.d.ts} +49 -201
  12. package/dist/billing.cjs +1 -1
  13. package/dist/billing.cjs.map +1 -1
  14. package/dist/billing.js +1 -1
  15. package/dist/billing.js.map +1 -1
  16. package/dist/browser.cjs +3735 -248
  17. package/dist/browser.cjs.map +1 -1
  18. package/dist/browser.d.cts +11 -10
  19. package/dist/browser.d.ts +11 -10
  20. package/dist/browser.js +3726 -249
  21. package/dist/browser.js.map +1 -1
  22. package/dist/cli/index.cjs +3232 -190
  23. package/dist/cli/index.cjs.map +1 -1
  24. package/dist/cli/index.d.cts +4 -4
  25. package/dist/cli/index.d.ts +4 -4
  26. package/dist/cli/index.js +3232 -190
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/cloudflare.cjs +12914 -0
  29. package/dist/cloudflare.cjs.map +1 -0
  30. package/dist/cloudflare.d.cts +368 -0
  31. package/dist/cloudflare.d.ts +368 -0
  32. package/dist/cloudflare.js +12885 -0
  33. package/dist/cloudflare.js.map +1 -0
  34. package/dist/cookies.cjs +4 -3
  35. package/dist/cookies.cjs.map +1 -1
  36. package/dist/cookies.js +4 -3
  37. package/dist/cookies.js.map +1 -1
  38. package/dist/env.cjs +130 -0
  39. package/dist/env.cjs.map +1 -0
  40. package/dist/env.d.cts +70 -0
  41. package/dist/env.d.ts +70 -0
  42. package/dist/env.js +122 -0
  43. package/dist/env.js.map +1 -0
  44. package/dist/index.cjs +3749 -241
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.cts +11 -10
  47. package/dist/index.d.ts +11 -10
  48. package/dist/index.js +3739 -242
  49. package/dist/index.js.map +1 -1
  50. package/dist/{model-form-BhWWsA-7.d.cts → model-form-D0ykVVOs.d.cts} +26 -4
  51. package/dist/{model-form-BbdzJ9Uh.d.ts → model-form-U8NVtfSA.d.ts} +26 -4
  52. package/dist/{module-xFd7_Igv.d.cts → module-CMWlJ1z3.d.cts} +5 -5
  53. package/dist/{module-DKkJKOuJ.d.ts → module-CZ-wPcf2.d.ts} +5 -5
  54. package/dist/next/client.cjs +3212 -196
  55. package/dist/next/client.cjs.map +1 -1
  56. package/dist/next/client.d.cts +6 -5
  57. package/dist/next/client.d.ts +6 -5
  58. package/dist/next/client.js +3212 -196
  59. package/dist/next/client.js.map +1 -1
  60. package/dist/next/server.cjs +4461 -781
  61. package/dist/next/server.cjs.map +1 -1
  62. package/dist/next/server.d.cts +139 -13
  63. package/dist/next/server.d.ts +139 -13
  64. package/dist/next/server.js +4451 -782
  65. package/dist/next/server.js.map +1 -1
  66. package/dist/{pipeline-DuKzYGia.d.cts → pipeline-BCpb4BX1.d.cts} +1 -1
  67. package/dist/{pipeline-wer2G9xW.d.ts → pipeline-CgmXwMeX.d.ts} +1 -1
  68. package/dist/{proxy-request-headers-m4D2Tduy.d.ts → proxy-request-headers-CttlcuRb.d.ts} +1 -1
  69. package/dist/{proxy-request-headers-DGxdoyA0.d.cts → proxy-request-headers-pIBSn1Fw.d.cts} +1 -1
  70. package/dist/react.cjs +290 -31
  71. package/dist/react.cjs.map +1 -1
  72. package/dist/react.d.cts +62 -12
  73. package/dist/react.d.ts +62 -12
  74. package/dist/react.js +290 -32
  75. package/dist/react.js.map +1 -1
  76. package/dist/schema-handlers-CvWqF-dW.d.ts +138 -0
  77. package/dist/schema-handlers-Dr8h9Jg-.d.cts +138 -0
  78. package/dist/social-providers.cjs +1 -1
  79. package/dist/social-providers.cjs.map +1 -1
  80. package/dist/social-providers.d.cts +1 -1
  81. package/dist/social-providers.d.ts +1 -1
  82. package/dist/social-providers.js +1 -1
  83. package/dist/social-providers.js.map +1 -1
  84. package/dist/{types-Bltx6iL6.d.ts → types-B2RZPivM.d.cts} +8 -1
  85. package/dist/{types-Bltx6iL6.d.cts → types-B2RZPivM.d.ts} +8 -1
  86. package/dist/{types-1ztXDgPa.d.cts → types-BKklrX4J.d.ts} +14 -2
  87. package/dist/{types-AOY-GLu8.d.cts → types-BVKpQmfY.d.cts} +11 -0
  88. package/dist/{types-AOY-GLu8.d.ts → types-BVKpQmfY.d.ts} +11 -0
  89. package/dist/{types-CgCv5o6R.d.cts → types-D5dj1v5Z.d.cts} +1 -1
  90. package/dist/{types-CccOiXPo.d.ts → types-DqBFwfhn.d.cts} +14 -2
  91. package/dist/{types-B75PdABb.d.ts → types-S-bTMPiM.d.ts} +1 -1
  92. package/dist/utils.cjs +30 -0
  93. package/dist/utils.cjs.map +1 -1
  94. package/dist/utils.d.cts +4 -3
  95. package/dist/utils.d.ts +4 -3
  96. package/dist/utils.js +30 -1
  97. package/dist/utils.js.map +1 -1
  98. package/dist/{v3-client-CWfZHcKL.d.cts → v3-client-DP-qg82X.d.cts} +323 -5
  99. package/dist/{v3-client-DZp2NEhK.d.ts → v3-client-OAai_JNs.d.ts} +323 -5
  100. package/package.json +25 -4
package/dist/cli/index.js CHANGED
@@ -585,6 +585,13 @@ var GATEWAY_API_KEY_ENV_KEYS = [
585
585
  "ATHENA_GATEWAY_API_KEY",
586
586
  "ATHENA_GENERATOR_API_KEY"
587
587
  ];
588
+ var GATEWAY_CLIENT_ENV_KEYS = [
589
+ "ATHENA_CLIENT",
590
+ "ATHENA_GATEWAY_CLIENT",
591
+ "ATHENA_GENERATOR_CLIENT",
592
+ "NEXT_PUBLIC_ATHENA_CLIENT",
593
+ "NEXT_PUBLIC_ATHENA_GATEWAY_CLIENT"
594
+ ];
588
595
  var GENERATOR_SCHEMA_ENV_KEYS = ["ATHENA_GENERATOR_SCHEMAS"];
589
596
  var OUTPUT_FORMAT_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_FORMAT"];
590
597
  var OUTPUT_PRESET_ENV_KEYS = ["ATHENA_GENERATOR_OUTPUT_PRESET"];
@@ -885,11 +892,13 @@ function normalizeProviderConfig(provider) {
885
892
  GATEWAY_API_KEY_ENV_KEYS
886
893
  );
887
894
  const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS) ?? "postgres";
895
+ const client = normalizeOptionalString(provider.client, GATEWAY_CLIENT_ENV_KEYS);
888
896
  return {
889
897
  ...provider,
890
898
  gatewayUrl,
891
899
  apiKey,
892
900
  database,
901
+ ...client ? { client } : {},
893
902
  schemas: normalizeSchemaSelection(provider.schemas)
894
903
  };
895
904
  }
@@ -1080,6 +1089,7 @@ function buildEnvironmentProviderConfig() {
1080
1089
  const apiKey = resolveFallbackValue(GATEWAY_API_KEY_ENV_KEYS);
1081
1090
  if (gatewayUrl && apiKey) {
1082
1091
  const backend = resolveOptionalOneOf(GATEWAY_BACKEND_ENV_KEYS, BACKEND_TYPE_VALUES);
1092
+ const client = resolveFallbackValue(GATEWAY_CLIENT_ENV_KEYS);
1083
1093
  return {
1084
1094
  kind: "postgres",
1085
1095
  mode: "gateway",
@@ -1087,7 +1097,8 @@ function buildEnvironmentProviderConfig() {
1087
1097
  apiKey,
1088
1098
  database: normalizeOptionalString(void 0, POSTGRES_DATABASE_ENV_KEYS),
1089
1099
  schemas: normalizeSchemaSelection(resolveFallbackValue(GENERATOR_SCHEMA_ENV_KEYS)),
1090
- backend
1100
+ backend,
1101
+ ...client ? { client } : {}
1091
1102
  };
1092
1103
  }
1093
1104
  return void 0;
@@ -2358,6 +2369,8 @@ function buildUpdateDebugSql(payload) {
2358
2369
  sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
2359
2370
  }
2360
2371
  const pagination = resolvePagination({
2372
+ limit: payload.limit,
2373
+ offset: payload.offset,
2361
2374
  currentPage: payload.current_page,
2362
2375
  pageSize: payload.page_size
2363
2376
  });
@@ -2380,6 +2393,8 @@ function buildDeleteDebugSql(payload) {
2380
2393
  sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
2381
2394
  }
2382
2395
  const pagination = resolvePagination({
2396
+ limit: payload.limit,
2397
+ offset: payload.offset,
2383
2398
  currentPage: payload.current_page,
2384
2399
  pageSize: payload.page_size
2385
2400
  });
@@ -2523,7 +2538,7 @@ function buildAthenaGatewayUrl(baseUrl, path) {
2523
2538
 
2524
2539
  // package.json
2525
2540
  var package_default = {
2526
- version: "3.1.0"
2541
+ version: "3.5.1"
2527
2542
  };
2528
2543
 
2529
2544
  // src/sdk-version.ts
@@ -4590,6 +4605,14 @@ function createAuthModule(config = {}, runtimeOptions = {}) {
4590
4605
  changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
4591
4606
  deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
4592
4607
  changePassword: (input, options) => postGeneric("/change-password", input, options),
4608
+ // Better Auth UI flat method aliases (also nested under session/account/social/user).
4609
+ listSessions: (input, options) => getGeneric("/list-sessions", input, options),
4610
+ revokeSession: sessionRevokeBinding,
4611
+ revokeOtherSessions,
4612
+ listAccounts: (input, options) => getGeneric("/list-accounts", input, options),
4613
+ unlinkAccount: (input, options) => postGeneric("/unlink-account", input, options),
4614
+ linkSocial: (input, options) => postGeneric("/link-social", input, options),
4615
+ updateUser: (input, options) => postGeneric("/update-user", input, options),
4593
4616
  user: {
4594
4617
  update: (input, options) => postGeneric("/update-user", input, options),
4595
4618
  delete: (input, options) => postGeneric("/delete-user", input, options),
@@ -5695,9 +5718,9 @@ function readHeadersField(value) {
5695
5718
  const headers = value.headers;
5696
5719
  if (!isRecord8(headers)) return {};
5697
5720
  const result = {};
5698
- for (const [key, headerValue2] of Object.entries(headers)) {
5699
- if (typeof headerValue2 === "string") {
5700
- result[key] = headerValue2;
5721
+ for (const [key, headerValue3] of Object.entries(headers)) {
5722
+ if (typeof headerValue3 === "string") {
5723
+ result[key] = headerValue3;
5701
5724
  }
5702
5725
  }
5703
5726
  return result;
@@ -9322,6 +9345,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, beha
9322
9345
  strip_nulls: mergedOptions?.stripNulls ?? true
9323
9346
  };
9324
9347
  if (executionState.order) payload.sort_by = executionState.order;
9348
+ if (executionState.limit !== void 0) payload.limit = executionState.limit;
9349
+ if (executionState.offset !== void 0) payload.offset = executionState.offset;
9325
9350
  if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
9326
9351
  if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
9327
9352
  if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
@@ -9376,6 +9401,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, beha
9376
9401
  conditions: filters
9377
9402
  };
9378
9403
  if (executionState.order) payload.sort_by = executionState.order;
9404
+ if (executionState.limit !== void 0) payload.limit = executionState.limit;
9405
+ if (executionState.offset !== void 0) payload.offset = executionState.offset;
9379
9406
  if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
9380
9407
  if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
9381
9408
  if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
@@ -9427,7 +9454,11 @@ function createQueryBuilder(client, formatGatewayResult, behavior, tracer) {
9427
9454
  if (!normalizedQuery) {
9428
9455
  throw new Error("query requires a non-empty string");
9429
9456
  }
9430
- const payload = { query: normalizedQuery };
9457
+ const params = options?.params;
9458
+ const payload = {
9459
+ query: normalizedQuery,
9460
+ ...Array.isArray(params) ? { params } : {}
9461
+ };
9431
9462
  const callsite = captureTraceCallsite(tracer);
9432
9463
  return executeRead(
9433
9464
  behavior,
@@ -9476,7 +9507,7 @@ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
9476
9507
  }
9477
9508
  function createInternalClientCore(config) {
9478
9509
  const normalizedAuthConfig = normalizeAuthClientConfig(config.auth, config.authUrl);
9479
- const gatewayTransport = createAthenaGatewayClient({
9510
+ const gatewayTransport = config.gatewayTransport ?? createAthenaGatewayClient({
9480
9511
  baseUrl: config.baseUrl,
9481
9512
  apiKey: config.apiKey,
9482
9513
  client: config.client ?? void 0,
@@ -9631,170 +9662,2808 @@ function createInternalClientView(core, resolveContext) {
9631
9662
  };
9632
9663
  }
9633
9664
 
9634
- // src/billing/module.ts
9635
- var SDK_NAME5 = "xylex-group/athena-billing";
9636
- var SDK_HEADER_VALUE4 = buildSdkHeaderValue(SDK_NAME5);
9637
- var AthenaBillingError = class extends Error {
9638
- status;
9639
- endpoint;
9640
- method;
9641
- body;
9642
- constructor(input) {
9643
- super(input.message);
9644
- this.name = "AthenaBillingError";
9645
- this.status = input.status;
9646
- this.endpoint = input.endpoint;
9647
- this.method = input.method;
9648
- this.body = input.body;
9649
- }
9650
- };
9651
- function withPathParam2(path, name, value) {
9652
- return path.replace(`{${name}}`, encodeURIComponent(value));
9653
- }
9654
- function appendQuery3(path, query) {
9655
- if (!query) return path;
9656
- const params = new URLSearchParams();
9657
- for (const [key, value] of Object.entries(query)) {
9658
- if (value === void 0 || value === null) continue;
9659
- params.set(key, String(value));
9660
- }
9661
- const serialized = params.toString();
9662
- return serialized ? `${path}?${serialized}` : path;
9665
+ // src/cloudflare/types.ts
9666
+ var CLOUDFLARE_EDGE_BASE_URL = "https://athena.local/cloudflare-edge";
9667
+ var CLOUDFLARE_EDGE_API_KEY = "cloudflare-edge-local";
9668
+
9669
+ // src/cloudflare/capabilities.ts
9670
+ function createGatewayCapabilities(options) {
9671
+ const storageConfigured = options?.storageConfigured ?? true;
9672
+ return {
9673
+ mode: "gateway",
9674
+ db: {
9675
+ engine: options?.engine ?? "postgresql",
9676
+ local: false,
9677
+ layers: {
9678
+ query: true,
9679
+ flatCrud: true,
9680
+ findManyAst: true,
9681
+ rpc: true,
9682
+ relations: true
9683
+ }
9684
+ },
9685
+ storage: {
9686
+ local: false,
9687
+ objects: storageConfigured,
9688
+ catalogs: storageConfigured ? options?.storageCatalogs ?? true : false,
9689
+ backups: storageConfigured ? options?.storageBackups ?? true : false
9690
+ },
9691
+ auth: {
9692
+ remote: options?.authRemote ?? true
9693
+ }
9694
+ };
9663
9695
  }
9664
- function connectionQuery(input) {
9665
- const query = {
9666
- connectionId: input.connectionId
9696
+ function createCloudflareEdgeCapabilities(options) {
9697
+ const hasObjects = options.hasR2 || Boolean(options.hasRemoteStorage);
9698
+ return {
9699
+ mode: "cloudflare-edge",
9700
+ db: {
9701
+ engine: "cloudflare-d1",
9702
+ local: true,
9703
+ layers: {
9704
+ query: true,
9705
+ flatCrud: true,
9706
+ findManyAst: options.findManyAst ?? false,
9707
+ rpc: false,
9708
+ relations: false
9709
+ }
9710
+ },
9711
+ storage: {
9712
+ // Local objects only when an R2 binding is present.
9713
+ local: options.hasR2,
9714
+ // Remote hybrid root can still expose storage.objects via the HTTP API.
9715
+ objects: hasObjects,
9716
+ catalogs: false,
9717
+ backups: false
9718
+ },
9719
+ auth: {
9720
+ remote: options.authRemote
9721
+ }
9667
9722
  };
9668
- if (input.clientName) query.clientName = input.clientName;
9669
- if ("cursor" in input && input.cursor) query.cursor = input.cursor;
9670
- if ("source" in input && input.source) query.source = input.source;
9671
- if ("limit" in input && input.limit !== void 0) query.limit = String(input.limit);
9672
- if ("offset" in input && input.offset !== void 0) query.offset = String(input.offset);
9673
- return query;
9674
9723
  }
9675
- function parseEnvelopeData(body) {
9676
- if (body && typeof body === "object" && "data" in body) {
9677
- return body.data;
9724
+
9725
+ // src/cloudflare/d1/runner.ts
9726
+ function resultColumns(rows) {
9727
+ const first = rows.find((value) => value && typeof value === "object" && !Array.isArray(value));
9728
+ if (!first) return [];
9729
+ return Object.keys(first);
9730
+ }
9731
+ function isIdentChar(ch) {
9732
+ if (!ch) return false;
9733
+ return /[A-Za-z0-9_]/.test(ch);
9734
+ }
9735
+ function scanSqlKeywordsOutsideLiterals(sql, onKeyword) {
9736
+ let inSingle = false;
9737
+ let inDouble = false;
9738
+ let inBacktick = false;
9739
+ let inBracket = false;
9740
+ let inLineComment = false;
9741
+ let inBlockComment = false;
9742
+ for (let i = 0; i < sql.length; i += 1) {
9743
+ const ch = sql[i];
9744
+ const next = sql[i + 1];
9745
+ if (inLineComment) {
9746
+ if (ch === "\n" || ch === "\r") inLineComment = false;
9747
+ continue;
9748
+ }
9749
+ if (inBlockComment) {
9750
+ if (ch === "*" && next === "/") {
9751
+ i += 1;
9752
+ inBlockComment = false;
9753
+ }
9754
+ continue;
9755
+ }
9756
+ if (inSingle) {
9757
+ if (ch === "'" && next === "'") {
9758
+ i += 1;
9759
+ continue;
9760
+ }
9761
+ if (ch === "'") inSingle = false;
9762
+ continue;
9763
+ }
9764
+ if (inDouble) {
9765
+ if (ch === '"' && next === '"') {
9766
+ i += 1;
9767
+ continue;
9768
+ }
9769
+ if (ch === '"') inDouble = false;
9770
+ continue;
9771
+ }
9772
+ if (inBacktick) {
9773
+ if (ch === "`" && next === "`") {
9774
+ i += 1;
9775
+ continue;
9776
+ }
9777
+ if (ch === "`") inBacktick = false;
9778
+ continue;
9779
+ }
9780
+ if (inBracket) {
9781
+ if (ch === "]") inBracket = false;
9782
+ continue;
9783
+ }
9784
+ if (ch === "-" && next === "-") {
9785
+ inLineComment = true;
9786
+ i += 1;
9787
+ continue;
9788
+ }
9789
+ if (ch === "/" && next === "*") {
9790
+ inBlockComment = true;
9791
+ i += 1;
9792
+ continue;
9793
+ }
9794
+ if (ch === "'") {
9795
+ inSingle = true;
9796
+ continue;
9797
+ }
9798
+ if (ch === '"') {
9799
+ inDouble = true;
9800
+ continue;
9801
+ }
9802
+ if (ch === "`") {
9803
+ inBacktick = true;
9804
+ continue;
9805
+ }
9806
+ if (ch === "[") {
9807
+ inBracket = true;
9808
+ continue;
9809
+ }
9810
+ if (!isIdentChar(ch) || isIdentChar(sql[i - 1])) {
9811
+ continue;
9812
+ }
9813
+ let end = i + 1;
9814
+ while (end < sql.length && isIdentChar(sql[end])) {
9815
+ end += 1;
9816
+ }
9817
+ const keyword = sql.slice(i, end);
9818
+ if (onKeyword(keyword, i)) {
9819
+ return;
9820
+ }
9821
+ i = end - 1;
9678
9822
  }
9679
- return body;
9680
9823
  }
9681
- function createBillingModule(config) {
9682
- const baseUrl = normalizeAthenaGatewayBaseUrl(config.baseUrl, {
9683
- label: "Athena billing base URL"
9824
+ function sqlContainsKeywordOutsideLiterals(sql, keyword) {
9825
+ const target = keyword.toUpperCase();
9826
+ let found = false;
9827
+ scanSqlKeywordsOutsideLiterals(sql, (token) => {
9828
+ if (token.toUpperCase() === target) {
9829
+ found = true;
9830
+ return true;
9831
+ }
9832
+ return false;
9684
9833
  });
9685
- const fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);
9686
- async function call(method, path, body, options, responseType = "json") {
9687
- const headers = buildAthenaRequestHeaders({
9688
- profile: "gateway",
9689
- sdkHeaderValue: SDK_HEADER_VALUE4,
9690
- apiKey: options?.apiKey ?? config.apiKey,
9691
- client: config.client,
9692
- configHeaders: {
9693
- ...config.headers ?? {}
9694
- },
9695
- callHeaders: options?.headers,
9696
- contentType: "application/json"
9697
- });
9698
- let requestBody;
9699
- if (body !== void 0 && body !== null) {
9700
- if (typeof body === "string" || body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof FormData || body instanceof URLSearchParams) {
9701
- requestBody = body;
9702
- } else {
9703
- requestBody = JSON.stringify(body);
9704
- if (!hasHeaderIgnoreCase(headers, "Content-Type")) {
9705
- headers["Content-Type"] = "application/json";
9706
- }
9834
+ return found;
9835
+ }
9836
+ function sqlFirstKeywordOutsideLiterals(sql) {
9837
+ let first = null;
9838
+ scanSqlKeywordsOutsideLiterals(sql, (token) => {
9839
+ first = token;
9840
+ return true;
9841
+ });
9842
+ return first;
9843
+ }
9844
+ var ROW_PRODUCING_LEAD_KEYWORDS = /* @__PURE__ */ new Set(["SELECT", "PRAGMA", "EXPLAIN", "VALUES"]);
9845
+ var MUTATION_LEAD_KEYWORDS = /* @__PURE__ */ new Set(["INSERT", "UPDATE", "DELETE", "REPLACE"]);
9846
+ var WITH_TERMINAL_KEYWORDS = /* @__PURE__ */ new Set([
9847
+ "SELECT",
9848
+ "INSERT",
9849
+ "UPDATE",
9850
+ "DELETE",
9851
+ "REPLACE",
9852
+ "VALUES",
9853
+ "PRAGMA",
9854
+ "EXPLAIN"
9855
+ ]);
9856
+ function sqlTerminalKeywordAfterWith(sql) {
9857
+ let inSingle = false;
9858
+ let inDouble = false;
9859
+ let inBacktick = false;
9860
+ let inBracket = false;
9861
+ let inLineComment = false;
9862
+ let inBlockComment = false;
9863
+ let depth = 0;
9864
+ let sawWith = false;
9865
+ for (let i = 0; i < sql.length; i += 1) {
9866
+ const ch = sql[i];
9867
+ const next = sql[i + 1];
9868
+ if (inLineComment) {
9869
+ if (ch === "\n" || ch === "\r") inLineComment = false;
9870
+ continue;
9871
+ }
9872
+ if (inBlockComment) {
9873
+ if (ch === "*" && next === "/") {
9874
+ i += 1;
9875
+ inBlockComment = false;
9707
9876
  }
9877
+ continue;
9708
9878
  }
9709
- const targetUrl = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
9710
- const response = await fetchImpl(targetUrl, {
9711
- method,
9712
- headers,
9713
- body: requestBody,
9714
- signal: options?.signal
9715
- });
9716
- if (responseType === "text") {
9717
- const text = await response.text();
9718
- if (!response.ok) {
9719
- throw new AthenaBillingError({
9720
- message: `Billing request failed (${response.status})`,
9721
- status: response.status,
9722
- endpoint: path,
9723
- method,
9724
- body: text
9725
- });
9879
+ if (inSingle) {
9880
+ if (ch === "'" && next === "'") {
9881
+ i += 1;
9882
+ continue;
9726
9883
  }
9727
- return text;
9884
+ if (ch === "'") inSingle = false;
9885
+ continue;
9728
9886
  }
9729
- const rawText = await response.text();
9730
- let parsed = rawText;
9731
- if (rawText) {
9732
- try {
9733
- parsed = JSON.parse(rawText);
9734
- } catch {
9735
- parsed = rawText;
9887
+ if (inDouble) {
9888
+ if (ch === '"' && next === '"') {
9889
+ i += 1;
9890
+ continue;
9736
9891
  }
9737
- } else {
9738
- parsed = null;
9892
+ if (ch === '"') inDouble = false;
9893
+ continue;
9739
9894
  }
9740
- if (!response.ok) {
9741
- const message = parsed && typeof parsed === "object" && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `Billing request failed (${response.status})`;
9742
- throw new AthenaBillingError({
9743
- message,
9744
- status: response.status,
9745
- endpoint: path,
9746
- method,
9747
- body: parsed
9748
- });
9895
+ if (inBacktick) {
9896
+ if (ch === "`" && next === "`") {
9897
+ i += 1;
9898
+ continue;
9899
+ }
9900
+ if (ch === "`") inBacktick = false;
9901
+ continue;
9749
9902
  }
9750
- return parseEnvelopeData(parsed);
9903
+ if (inBracket) {
9904
+ if (ch === "]") inBracket = false;
9905
+ continue;
9906
+ }
9907
+ if (ch === "-" && next === "-") {
9908
+ inLineComment = true;
9909
+ i += 1;
9910
+ continue;
9911
+ }
9912
+ if (ch === "/" && next === "*") {
9913
+ inBlockComment = true;
9914
+ i += 1;
9915
+ continue;
9916
+ }
9917
+ if (ch === "'") {
9918
+ inSingle = true;
9919
+ continue;
9920
+ }
9921
+ if (ch === '"') {
9922
+ inDouble = true;
9923
+ continue;
9924
+ }
9925
+ if (ch === "`") {
9926
+ inBacktick = true;
9927
+ continue;
9928
+ }
9929
+ if (ch === "[") {
9930
+ inBracket = true;
9931
+ continue;
9932
+ }
9933
+ if (ch === "(") {
9934
+ depth += 1;
9935
+ continue;
9936
+ }
9937
+ if (ch === ")") {
9938
+ if (depth > 0) depth -= 1;
9939
+ continue;
9940
+ }
9941
+ if (depth !== 0 || !isIdentChar(ch) || isIdentChar(sql[i - 1])) {
9942
+ continue;
9943
+ }
9944
+ let end = i + 1;
9945
+ while (end < sql.length && isIdentChar(sql[end])) {
9946
+ end += 1;
9947
+ }
9948
+ const keyword = sql.slice(i, end);
9949
+ const upper = keyword.toUpperCase();
9950
+ if (!sawWith) {
9951
+ if (upper === "WITH") {
9952
+ sawWith = true;
9953
+ }
9954
+ i = end - 1;
9955
+ continue;
9956
+ }
9957
+ if (WITH_TERMINAL_KEYWORDS.has(upper)) {
9958
+ return keyword;
9959
+ }
9960
+ i = end - 1;
9751
9961
  }
9752
- return {
9753
- getCapabilities(input, options) {
9754
- return call(
9755
- "GET",
9756
- appendQuery3("/billing/v1/capabilities", connectionQuery(input)),
9757
- void 0,
9758
- options
9759
- );
9760
- },
9761
- createCheckout(body, options) {
9762
- return call("POST", "/billing/v1/checkouts", body, options);
9763
- },
9764
- listProducts(input, options) {
9765
- return call(
9766
- "GET",
9767
- appendQuery3("/billing/v1/products", connectionQuery(input)),
9768
- void 0,
9769
- options
9770
- );
9771
- },
9772
- listPrices(input, options) {
9773
- return call(
9774
- "GET",
9775
- appendQuery3("/billing/v1/prices", {
9776
- ...connectionQuery(input),
9777
- ...input.productId ? { productId: input.productId } : {}
9778
- }),
9779
- void 0,
9780
- options
9781
- );
9782
- },
9783
- listCustomers(input, options) {
9784
- return call(
9785
- "GET",
9786
- appendQuery3("/billing/v1/customers", connectionQuery(input)),
9787
- void 0,
9788
- options
9789
- );
9790
- },
9791
- createCustomer(input, options) {
9792
- return call(
9793
- "POST",
9794
- "/billing/v1/customers",
9795
- {
9796
- connectionId: input.connectionId,
9797
- clientName: input.clientName,
9962
+ return null;
9963
+ }
9964
+ function sqlLeadStatementKeyword(sql) {
9965
+ const first = sqlFirstKeywordOutsideLiterals(sql);
9966
+ if (!first) return null;
9967
+ if (first.toUpperCase() !== "WITH") return first;
9968
+ return sqlTerminalKeywordAfterWith(sql) ?? first;
9969
+ }
9970
+ function statementExpectsResultRows(sql) {
9971
+ const lead = sqlLeadStatementKeyword(sql);
9972
+ if (lead) {
9973
+ const upper = lead.toUpperCase();
9974
+ if (ROW_PRODUCING_LEAD_KEYWORDS.has(upper)) {
9975
+ return true;
9976
+ }
9977
+ if (MUTATION_LEAD_KEYWORDS.has(upper)) {
9978
+ return sqlContainsKeywordOutsideLiterals(sql, "RETURNING");
9979
+ }
9980
+ }
9981
+ return sqlContainsKeywordOutsideLiterals(sql, "RETURNING");
9982
+ }
9983
+ function collectRowsFromBatchResults(results) {
9984
+ const rows = [];
9985
+ for (const item of results) {
9986
+ if (Array.isArray(item.results) && item.results.length > 0) {
9987
+ rows.push(...item.results);
9988
+ }
9989
+ }
9990
+ return rows;
9991
+ }
9992
+ function sumBatchAffectedRows(results, statementCount) {
9993
+ let sum2 = 0;
9994
+ let sawChanges = false;
9995
+ for (const item of results) {
9996
+ const changes = item.meta?.changes;
9997
+ if (typeof changes === "number") {
9998
+ sum2 += changes;
9999
+ sawChanges = true;
10000
+ }
10001
+ }
10002
+ return sawChanges ? sum2 : statementCount;
10003
+ }
10004
+ function matchSqlKeywordAt(query, index, keyword) {
10005
+ const len = keyword.length;
10006
+ if (index + len > query.length) {
10007
+ return null;
10008
+ }
10009
+ const slice = query.slice(index, index + len);
10010
+ if (slice.toLowerCase() !== keyword.toLowerCase()) {
10011
+ return null;
10012
+ }
10013
+ const before = index === 0 ? "" : query[index - 1];
10014
+ const after = index + len >= query.length ? "" : query[index + len];
10015
+ const isIdent = (c) => /[A-Za-z0-9_]/.test(c);
10016
+ if (before && isIdent(before)) {
10017
+ return null;
10018
+ }
10019
+ if (after && isIdent(after)) {
10020
+ return null;
10021
+ }
10022
+ return len;
10023
+ }
10024
+ function splitSqlStatements(query) {
10025
+ const statements = [];
10026
+ let inSingle = false;
10027
+ let inDouble = false;
10028
+ let inBacktick = false;
10029
+ let inBracket = false;
10030
+ let inLineComment = false;
10031
+ let inBlockComment = false;
10032
+ let segmentStart = 0;
10033
+ let segmentHasContent = false;
10034
+ let awaitTriggerBegin = false;
10035
+ let triggerBodyDepth = 0;
10036
+ let caseDepth = 0;
10037
+ const flushSegment = (end) => {
10038
+ if (!segmentHasContent) {
10039
+ segmentStart = end + 1;
10040
+ return;
10041
+ }
10042
+ const sql = query.slice(segmentStart, end).trim();
10043
+ if (sql) {
10044
+ statements.push(sql);
10045
+ }
10046
+ segmentHasContent = false;
10047
+ segmentStart = end + 1;
10048
+ awaitTriggerBegin = false;
10049
+ triggerBodyDepth = 0;
10050
+ caseDepth = 0;
10051
+ };
10052
+ for (let i = 0; i < query.length; i += 1) {
10053
+ const ch = query[i];
10054
+ const next = query[i + 1];
10055
+ if (inLineComment) {
10056
+ if (ch === "\n" || ch === "\r") {
10057
+ inLineComment = false;
10058
+ }
10059
+ continue;
10060
+ }
10061
+ if (inBlockComment) {
10062
+ if (ch === "*" && next === "/") {
10063
+ inBlockComment = false;
10064
+ i += 1;
10065
+ }
10066
+ continue;
10067
+ }
10068
+ if (inSingle) {
10069
+ if (ch === "'" && next === "'") {
10070
+ i += 1;
10071
+ continue;
10072
+ }
10073
+ if (ch === "'") {
10074
+ inSingle = false;
10075
+ }
10076
+ continue;
10077
+ }
10078
+ if (inDouble) {
10079
+ if (ch === '"' && next === '"') {
10080
+ i += 1;
10081
+ continue;
10082
+ }
10083
+ if (ch === '"') {
10084
+ inDouble = false;
10085
+ }
10086
+ continue;
10087
+ }
10088
+ if (inBacktick) {
10089
+ if (ch === "`" && next === "`") {
10090
+ i += 1;
10091
+ continue;
10092
+ }
10093
+ if (ch === "`") {
10094
+ inBacktick = false;
10095
+ }
10096
+ continue;
10097
+ }
10098
+ if (inBracket) {
10099
+ if (ch === "]") {
10100
+ inBracket = false;
10101
+ }
10102
+ continue;
10103
+ }
10104
+ if (ch === "-" && next === "-") {
10105
+ inLineComment = true;
10106
+ i += 1;
10107
+ continue;
10108
+ }
10109
+ if (ch === "/" && next === "*") {
10110
+ inBlockComment = true;
10111
+ i += 1;
10112
+ continue;
10113
+ }
10114
+ if (ch === "'") {
10115
+ inSingle = true;
10116
+ segmentHasContent = true;
10117
+ continue;
10118
+ }
10119
+ if (ch === '"') {
10120
+ inDouble = true;
10121
+ segmentHasContent = true;
10122
+ continue;
10123
+ }
10124
+ if (ch === "`") {
10125
+ inBacktick = true;
10126
+ segmentHasContent = true;
10127
+ continue;
10128
+ }
10129
+ if (ch === "[") {
10130
+ inBracket = true;
10131
+ segmentHasContent = true;
10132
+ continue;
10133
+ }
10134
+ if (/[A-Za-z_]/.test(ch)) {
10135
+ const createLen = matchSqlKeywordAt(query, i, "CREATE");
10136
+ if (createLen != null) {
10137
+ let j2 = i + createLen;
10138
+ const skipWsAndComments = () => {
10139
+ while (j2 < query.length) {
10140
+ const c = query[j2];
10141
+ const n = query[j2 + 1];
10142
+ if (/\s/.test(c)) {
10143
+ j2 += 1;
10144
+ continue;
10145
+ }
10146
+ if (c === "-" && n === "-") {
10147
+ j2 += 2;
10148
+ while (j2 < query.length && query[j2] !== "\n" && query[j2] !== "\r") {
10149
+ j2 += 1;
10150
+ }
10151
+ continue;
10152
+ }
10153
+ if (c === "/" && n === "*") {
10154
+ j2 += 2;
10155
+ while (j2 < query.length) {
10156
+ if (query[j2] === "*" && query[j2 + 1] === "/") {
10157
+ j2 += 2;
10158
+ break;
10159
+ }
10160
+ j2 += 1;
10161
+ }
10162
+ continue;
10163
+ }
10164
+ break;
10165
+ }
10166
+ };
10167
+ skipWsAndComments();
10168
+ const tempLen = matchSqlKeywordAt(query, j2, "TEMPORARY") ?? matchSqlKeywordAt(query, j2, "TEMP");
10169
+ if (tempLen != null) {
10170
+ j2 += tempLen;
10171
+ skipWsAndComments();
10172
+ }
10173
+ const triggerLen = matchSqlKeywordAt(query, j2, "TRIGGER");
10174
+ if (triggerLen != null) {
10175
+ awaitTriggerBegin = true;
10176
+ segmentHasContent = true;
10177
+ i += createLen - 1;
10178
+ continue;
10179
+ }
10180
+ segmentHasContent = true;
10181
+ i += createLen - 1;
10182
+ continue;
10183
+ }
10184
+ const caseLen = matchSqlKeywordAt(query, i, "CASE");
10185
+ if (caseLen != null) {
10186
+ caseDepth += 1;
10187
+ segmentHasContent = true;
10188
+ i += caseLen - 1;
10189
+ continue;
10190
+ }
10191
+ const beginLen = matchSqlKeywordAt(query, i, "BEGIN");
10192
+ if (beginLen != null) {
10193
+ if (awaitTriggerBegin) {
10194
+ triggerBodyDepth += 1;
10195
+ awaitTriggerBegin = false;
10196
+ }
10197
+ segmentHasContent = true;
10198
+ i += beginLen - 1;
10199
+ continue;
10200
+ }
10201
+ const endLen = matchSqlKeywordAt(query, i, "END");
10202
+ if (endLen != null) {
10203
+ if (caseDepth > 0) {
10204
+ caseDepth -= 1;
10205
+ } else if (triggerBodyDepth > 0) {
10206
+ triggerBodyDepth -= 1;
10207
+ }
10208
+ segmentHasContent = true;
10209
+ i += endLen - 1;
10210
+ continue;
10211
+ }
10212
+ let j = i + 1;
10213
+ while (j < query.length && /[A-Za-z0-9_]/.test(query[j])) {
10214
+ j += 1;
10215
+ }
10216
+ segmentHasContent = true;
10217
+ i = j - 1;
10218
+ continue;
10219
+ }
10220
+ if (ch === ";") {
10221
+ if (triggerBodyDepth > 0 || caseDepth > 0) {
10222
+ segmentHasContent = true;
10223
+ continue;
10224
+ }
10225
+ flushSegment(i);
10226
+ continue;
10227
+ }
10228
+ if (!/\s/.test(ch)) {
10229
+ segmentHasContent = true;
10230
+ }
10231
+ }
10232
+ flushSegment(query.length);
10233
+ return statements;
10234
+ }
10235
+ function isMultiStatement(query) {
10236
+ return splitSqlStatements(query).length > 1;
10237
+ }
10238
+ function resolveSessionTarget(db, input) {
10239
+ const sessionValue = input.bookmark?.trim() || input.sessionMode?.trim();
10240
+ if (!sessionValue) {
10241
+ return { target: db, session: null };
10242
+ }
10243
+ if (typeof db.withSession !== "function") {
10244
+ throw new Error("D1 session mode/bookmark requested but withSession is not available");
10245
+ }
10246
+ const session = db.withSession(sessionValue);
10247
+ return { target: session, session };
10248
+ }
10249
+ function normalizeD1BindParams(params) {
10250
+ return params.map((value) => {
10251
+ if (typeof value === "boolean") {
10252
+ return value ? 1 : 0;
10253
+ }
10254
+ return value;
10255
+ });
10256
+ }
10257
+ async function executeD1Query(db, input) {
10258
+ const query = input.query?.trim();
10259
+ if (!query) {
10260
+ return { ok: false, error: "invalid_query", message: "query is required" };
10261
+ }
10262
+ const params = normalizeD1BindParams(Array.isArray(input.params) ? input.params : []);
10263
+ const { target, session } = resolveSessionTarget(db, input);
10264
+ if (isMultiStatement(query)) {
10265
+ if (params.length > 0) {
10266
+ return {
10267
+ ok: false,
10268
+ error: "invalid_query",
10269
+ message: "params are only supported for single prepared statements"
10270
+ };
10271
+ }
10272
+ const resolveBookmark = () => session?.getBookmark() ?? null;
10273
+ const parts = splitSqlStatements(query);
10274
+ if (typeof target.batch === "function") {
10275
+ const prepared = parts.map((part) => target.prepare(part));
10276
+ const results = await target.batch(prepared);
10277
+ const rows2 = collectRowsFromBatchResults(results);
10278
+ return {
10279
+ ok: true,
10280
+ rows: rows2,
10281
+ columns: resultColumns(rows2),
10282
+ // Prefer returned rows; otherwise sum mutation meta.changes (not statement count).
10283
+ count: rows2.length > 0 ? rows2.length : sumBatchAffectedRows(results, parts.length),
10284
+ bookmark: resolveBookmark(),
10285
+ meta: { statementCount: parts.length, results },
10286
+ statementCount: parts.length
10287
+ };
10288
+ }
10289
+ const canExec = typeof target.exec === "function" && !session;
10290
+ if (canExec) {
10291
+ const execResult = await target.exec(query);
10292
+ return {
10293
+ ok: true,
10294
+ rows: [],
10295
+ columns: [],
10296
+ durationMs: execResult.duration,
10297
+ count: execResult.count,
10298
+ bookmark: resolveBookmark(),
10299
+ meta: { statementCount: execResult.count },
10300
+ statementCount: execResult.count
10301
+ };
10302
+ }
10303
+ return {
10304
+ ok: false,
10305
+ error: "invalid_query",
10306
+ message: "multi-statement query requires D1 batch() or exec() support"
10307
+ };
10308
+ }
10309
+ let statement = target.prepare(query);
10310
+ if (params.length > 0) {
10311
+ statement = statement.bind(...params);
10312
+ }
10313
+ const expectsRows = statementExpectsResultRows(query);
10314
+ const result = expectsRows ? await statement.all() : await statement.run();
10315
+ if (result.success === false) {
10316
+ const errorField = result.error;
10317
+ const message = typeof errorField === "string" && errorField.trim() ? errorField : "D1 query failed";
10318
+ return {
10319
+ ok: false,
10320
+ error: "query_failed",
10321
+ message
10322
+ };
10323
+ }
10324
+ const rows = Array.isArray(result.results) ? result.results : [];
10325
+ const bookmark = session?.getBookmark() ?? null;
10326
+ const meta = result.meta ?? {};
10327
+ const changes = typeof meta.changes === "number" ? meta.changes : typeof result.meta?.changes === "number" ? result.meta.changes : void 0;
10328
+ return {
10329
+ ok: true,
10330
+ rows,
10331
+ columns: resultColumns(rows),
10332
+ durationMs: typeof result.meta?.duration === "number" ? result.meta.duration : void 0,
10333
+ count: expectsRows ? rows.length : changes ?? rows.length,
10334
+ bookmark,
10335
+ meta
10336
+ };
10337
+ }
10338
+ async function executeD1Batch(db, input) {
10339
+ const statements = Array.isArray(input.statements) ? input.statements : [];
10340
+ if (statements.length === 0) {
10341
+ return {
10342
+ ok: false,
10343
+ error: "invalid_batch",
10344
+ message: "statements must contain at least one item"
10345
+ };
10346
+ }
10347
+ const { target, session } = resolveSessionTarget(db, input);
10348
+ const prepared = statements.map((item) => {
10349
+ const query = item.query?.trim();
10350
+ if (!query) {
10351
+ throw new Error("statements[].query is required");
10352
+ }
10353
+ const params = normalizeD1BindParams(Array.isArray(item.params) ? item.params : []);
10354
+ let statement = target.prepare(query);
10355
+ if (params.length > 0) {
10356
+ statement = statement.bind(...params);
10357
+ }
10358
+ return statement;
10359
+ });
10360
+ const results = await target.batch(prepared);
10361
+ const bookmark = session?.getBookmark() ?? null;
10362
+ return {
10363
+ ok: true,
10364
+ results,
10365
+ bookmark
10366
+ };
10367
+ }
10368
+
10369
+ // src/cloudflare/d1/sql.ts
10370
+ function asSingle(sql, params) {
10371
+ return { sql, params };
10372
+ }
10373
+ function asBatch(statements) {
10374
+ if (statements.length === 0) {
10375
+ throw new D1SqlCompileError("empty_insert", "batch requires at least one statement");
10376
+ }
10377
+ return {
10378
+ sql: statements[0].sql,
10379
+ params: statements[0].params,
10380
+ statements
10381
+ };
10382
+ }
10383
+ function hasPaginationBounds(payload) {
10384
+ return payload.limit !== void 0 || payload.offset !== void 0 || payload.page_size !== void 0 || payload.current_page !== void 0;
10385
+ }
10386
+ function assertEffectiveMutationBounds(payload) {
10387
+ if (payload.current_page !== void 0 && payload.page_size === void 0 && payload.limit === void 0) {
10388
+ throw new D1SqlCompileError(
10389
+ "page_without_size",
10390
+ "current_page requires page_size (or limit) for bounded update/delete on D1 edge-local"
10391
+ );
10392
+ }
10393
+ const clause = limitOffsetClause(payload);
10394
+ if (!clause.trim()) {
10395
+ throw new D1SqlCompileError(
10396
+ "invalid_pagination_bounds",
10397
+ "Bounded update/delete requires limit, offset, and/or page_size on D1 edge-local"
10398
+ );
10399
+ }
10400
+ }
10401
+ var SQLITE_ROWID_ALIASES = /* @__PURE__ */ new Set(["rowid", "oid", "_rowid_"]);
10402
+ function referencedMutationColumns(payload) {
10403
+ const names = [];
10404
+ for (const condition of payload.conditions ?? []) {
10405
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
10406
+ if (column) names.push(column);
10407
+ }
10408
+ if (payload.sort_by?.field?.trim()) {
10409
+ names.push(payload.sort_by.field.trim());
10410
+ }
10411
+ return names;
10412
+ }
10413
+ function resolveBoundedIdentityColumn(payload, options) {
10414
+ const refs = referencedMutationColumns(payload);
10415
+ const lower = refs.map((name) => name.toLowerCase());
10416
+ if (lower.some((name) => SQLITE_ROWID_ALIASES.has(name))) {
10417
+ throw new D1SqlCompileError(
10418
+ "bounded_mutation_unsafe_identity",
10419
+ "Bounded update/delete cannot use rowid/oid/_rowid_ in filters or order \u2014 those names may be user columns that shadow SQLite row identity. Resolve the table primary key (or a single-column unique index) instead."
10420
+ );
10421
+ }
10422
+ const identity = options?.identityColumn?.trim();
10423
+ if (!identity) {
10424
+ throw new D1SqlCompileError(
10425
+ "bounded_mutation_no_unique_identity",
10426
+ "Bounded update/delete requires a proven unique identity column from the table schema (single-column PRIMARY KEY or UNIQUE index). Cannot assume a column named id."
10427
+ );
10428
+ }
10429
+ if (SQLITE_ROWID_ALIASES.has(identity.toLowerCase())) {
10430
+ throw new D1SqlCompileError(
10431
+ "bounded_mutation_unsafe_identity",
10432
+ `Bounded update/delete cannot use identity column "${identity}" \u2014 it may shadow SQLite row identity.`
10433
+ );
10434
+ }
10435
+ return identity;
10436
+ }
10437
+ function boundedRowidInClause(table, whereSql, whereParams, payload, options) {
10438
+ assertEffectiveMutationBounds(payload);
10439
+ const identity = resolveBoundedIdentityColumn(payload, options);
10440
+ const identitySql = quoteIdent(identity);
10441
+ const innerWhere = whereSql.replace(/^WHERE\s+/i, "");
10442
+ const parts = [
10443
+ `SELECT ${identitySql} FROM ${quoteIdent(table)}`,
10444
+ innerWhere ? `WHERE ${innerWhere}` : "",
10445
+ orderClause(payload.sort_by),
10446
+ limitOffsetClause(payload)
10447
+ ].filter(Boolean);
10448
+ return {
10449
+ sql: `${identitySql} IN (${parts.join(" ")})`,
10450
+ params: [...whereParams]
10451
+ };
10452
+ }
10453
+ var D1SqlCompileError = class extends Error {
10454
+ code;
10455
+ constructor(code, message) {
10456
+ super(message);
10457
+ this.name = "D1SqlCompileError";
10458
+ this.code = code;
10459
+ }
10460
+ };
10461
+ var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
10462
+ function quoteIdent(name) {
10463
+ const trimmed = name.trim();
10464
+ if (!trimmed) {
10465
+ throw new D1SqlCompileError("invalid_identifier", "Identifier is required");
10466
+ }
10467
+ if (trimmed.includes(".")) {
10468
+ throw new D1SqlCompileError(
10469
+ "schema_qualified_name",
10470
+ `Schema-qualified names are unsupported on D1 edge-local: ${trimmed}`
10471
+ );
10472
+ }
10473
+ if (!SAFE_IDENTIFIER.test(trimmed)) {
10474
+ throw new D1SqlCompileError(
10475
+ "invalid_identifier",
10476
+ `Invalid SQL identifier for D1 edge-local: ${trimmed}`
10477
+ );
10478
+ }
10479
+ return quoteQualifiedIdentifier(trimmed);
10480
+ }
10481
+ var RESPONSE_ALIAS_PATTERN2 = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_]*)$/;
10482
+ var SQL_ALIAS_PATTERN2 = /^([A-Za-z_][A-Za-z0-9_]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
10483
+ function quoteSelectTokenStrict(token) {
10484
+ const trimmed = token.trim();
10485
+ if (!trimmed || trimmed === "*") return trimmed || "*";
10486
+ if (SAFE_IDENTIFIER.test(trimmed)) {
10487
+ return quoteQualifiedIdentifier(trimmed);
10488
+ }
10489
+ const responseAlias = RESPONSE_ALIAS_PATTERN2.exec(trimmed);
10490
+ if (responseAlias) {
10491
+ const [, aliasIdentifier, baseIdentifier] = responseAlias;
10492
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteQualifiedIdentifier(aliasIdentifier)}`;
10493
+ }
10494
+ const sqlAlias = SQL_ALIAS_PATTERN2.exec(trimmed);
10495
+ if (sqlAlias) {
10496
+ const [, baseIdentifier, aliasIdentifier] = sqlAlias;
10497
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteQualifiedIdentifier(aliasIdentifier)}`;
10498
+ }
10499
+ throw new D1SqlCompileError(
10500
+ "unsafe_select",
10501
+ `SELECT/RETURNING expressions are not supported on D1 edge-local; use column names or aliases only: ${token}`
10502
+ );
10503
+ }
10504
+ function selectClause(columns) {
10505
+ if (columns === void 0 || columns === "*" || columns === "") return "*";
10506
+ if (typeof columns === "string") {
10507
+ const trimmed = columns.trim();
10508
+ if (!trimmed || trimmed === "*") return "*";
10509
+ return trimmed.split(",").map((part) => quoteSelectTokenStrict(part)).join(", ");
10510
+ }
10511
+ if (columns.length === 0) return "*";
10512
+ return columns.map((column) => quoteSelectTokenStrict(column)).join(", ");
10513
+ }
10514
+ function wantsReturning(payload) {
10515
+ return Boolean(payload.columns) && payload.head !== true;
10516
+ }
10517
+ function conditionToWhere(condition) {
10518
+ const column = condition.column?.trim() || condition.eq_column?.trim() || "";
10519
+ if (!column) {
10520
+ throw new D1SqlCompileError("invalid_condition", "Condition requires a column");
10521
+ }
10522
+ const col = quoteIdent(column);
10523
+ const operator = (condition.operator || "eq").toLowerCase();
10524
+ const value = condition.value !== void 0 ? condition.value : condition.eq_value;
10525
+ switch (operator) {
10526
+ case "eq": {
10527
+ if (Array.isArray(value)) {
10528
+ if (value.length === 0) {
10529
+ return { sql: "1 = 0", params: [] };
10530
+ }
10531
+ const placeholders = value.map(() => "?").join(", ");
10532
+ return { sql: `${col} IN (${placeholders})`, params: [...value] };
10533
+ }
10534
+ if (value === null) {
10535
+ return { sql: `${col} IS NULL`, params: [] };
10536
+ }
10537
+ return { sql: `${col} = ?`, params: [value ?? null] };
10538
+ }
10539
+ case "neq":
10540
+ if (value === null) {
10541
+ return { sql: `${col} IS NOT NULL`, params: [] };
10542
+ }
10543
+ return { sql: `${col} != ?`, params: [value ?? null] };
10544
+ case "gt":
10545
+ return { sql: `${col} > ?`, params: [value ?? null] };
10546
+ case "gte":
10547
+ return { sql: `${col} >= ?`, params: [value ?? null] };
10548
+ case "lt":
10549
+ return { sql: `${col} < ?`, params: [value ?? null] };
10550
+ case "lte":
10551
+ return { sql: `${col} <= ?`, params: [value ?? null] };
10552
+ case "like":
10553
+ return { sql: `${col} LIKE ?`, params: [value ?? null] };
10554
+ case "ilike":
10555
+ return { sql: `${col} LIKE ? COLLATE NOCASE`, params: [value ?? null] };
10556
+ case "in": {
10557
+ const items = Array.isArray(value) ? value : value === void 0 ? [] : [value];
10558
+ if (items.length === 0) {
10559
+ return { sql: "1 = 0", params: [] };
10560
+ }
10561
+ const placeholders = items.map(() => "?").join(", ");
10562
+ return { sql: `${col} IN (${placeholders})`, params: [...items] };
10563
+ }
10564
+ case "is": {
10565
+ if (value === null || value === "null") {
10566
+ return { sql: `${col} IS NULL`, params: [] };
10567
+ }
10568
+ if (value === true || value === "true") {
10569
+ return { sql: `${col} IS TRUE`, params: [] };
10570
+ }
10571
+ if (value === false || value === "false") {
10572
+ return { sql: `${col} IS FALSE`, params: [] };
10573
+ }
10574
+ return { sql: `${col} IS ?`, params: [value] };
10575
+ }
10576
+ case "not":
10577
+ case "or":
10578
+ case "contains":
10579
+ case "containedby":
10580
+ throw new D1SqlCompileError(
10581
+ "unsupported_operator",
10582
+ `Condition operator "${operator}" is not supported on D1 edge-local L1`
10583
+ );
10584
+ default:
10585
+ throw new D1SqlCompileError(
10586
+ "unsupported_operator",
10587
+ `Unknown condition operator "${operator}"`
10588
+ );
10589
+ }
10590
+ }
10591
+ function buildWhere(conditions) {
10592
+ if (!conditions?.length) {
10593
+ return { sql: "", params: [] };
10594
+ }
10595
+ const parts = [];
10596
+ const params = [];
10597
+ for (const condition of conditions) {
10598
+ if (!condition.operator && condition.eq_column) {
10599
+ const clause2 = conditionToWhere({
10600
+ ...condition,
10601
+ operator: "eq",
10602
+ column: condition.eq_column,
10603
+ value: condition.eq_value
10604
+ });
10605
+ parts.push(clause2.sql);
10606
+ params.push(...clause2.params);
10607
+ continue;
10608
+ }
10609
+ const clause = conditionToWhere(condition);
10610
+ parts.push(clause.sql);
10611
+ params.push(...clause.params);
10612
+ }
10613
+ return {
10614
+ sql: parts.length ? `WHERE ${parts.join(" AND ")}` : "",
10615
+ params
10616
+ };
10617
+ }
10618
+ function orderClause(order) {
10619
+ if (!order?.field?.trim()) return "";
10620
+ const direction = order.direction === "descending" ? "DESC" : "ASC";
10621
+ return `ORDER BY ${quoteIdent(order.field)} ${direction}`;
10622
+ }
10623
+ function limitOffsetClause(payload) {
10624
+ let limit = payload.limit;
10625
+ let offset = payload.offset;
10626
+ if (limit === void 0 && payload.page_size !== void 0) {
10627
+ limit = payload.page_size;
10628
+ }
10629
+ if (payload.current_page !== void 0 && offset === void 0) {
10630
+ const pageSize = payload.page_size ?? payload.limit;
10631
+ if (pageSize !== void 0) {
10632
+ offset = Math.max(0, (payload.current_page - 1) * pageSize);
10633
+ }
10634
+ }
10635
+ const parts = [];
10636
+ if (offset !== void 0 && limit === void 0) {
10637
+ parts.push("LIMIT -1");
10638
+ parts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
10639
+ } else {
10640
+ if (limit !== void 0) {
10641
+ parts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
10642
+ }
10643
+ if (offset !== void 0) {
10644
+ parts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
10645
+ }
10646
+ }
10647
+ return parts.join(" ");
10648
+ }
10649
+ function rejectStructuredRelations(payload) {
10650
+ const select = payload.select;
10651
+ if (select && typeof select === "object" && !Array.isArray(select)) {
10652
+ for (const value of Object.values(select)) {
10653
+ if (value && typeof value === "object") {
10654
+ throw new D1SqlCompileError(
10655
+ "relations_unsupported",
10656
+ "Nested relation selects are unsupported on D1 edge-local"
10657
+ );
10658
+ }
10659
+ }
10660
+ }
10661
+ if (payload.view_name) {
10662
+ throw new D1SqlCompileError(
10663
+ "view_unsupported",
10664
+ "view_name is unsupported on D1 edge-local L1"
10665
+ );
10666
+ }
10667
+ }
10668
+ function jsonValue(value) {
10669
+ if (value === void 0) return null;
10670
+ if (value !== null && typeof value === "object") {
10671
+ return JSON.stringify(value);
10672
+ }
10673
+ return value;
10674
+ }
10675
+ function compileD1Fetch(payload) {
10676
+ rejectStructuredRelations(payload);
10677
+ const table = payload.table_name?.trim();
10678
+ if (!table) {
10679
+ throw new D1SqlCompileError("missing_table", "table_name is required for fetch");
10680
+ }
10681
+ let columns = payload.columns;
10682
+ if (payload.select && typeof payload.select === "object" && !Array.isArray(payload.select)) {
10683
+ const keys = Object.entries(payload.select).filter(([, enabled]) => enabled === true || enabled === 1).map(([key]) => key);
10684
+ if (keys.length > 0) {
10685
+ columns = keys;
10686
+ }
10687
+ } else if (typeof payload.select === "string" && payload.select.trim()) {
10688
+ columns = payload.select;
10689
+ }
10690
+ let where = buildWhere(payload.conditions);
10691
+ if (!where.sql && payload.where && typeof payload.where === "object") {
10692
+ const eqConditions = Object.entries(
10693
+ payload.where
10694
+ ).map(([column, value]) => ({
10695
+ column,
10696
+ operator: "eq",
10697
+ value
10698
+ }));
10699
+ where = buildWhere(eqConditions);
10700
+ }
10701
+ if (payload.head === true) {
10702
+ return compileD1CountFromWhere(table, where);
10703
+ }
10704
+ const parts = [
10705
+ `SELECT ${selectClause(columns)} FROM ${quoteIdent(table)}`,
10706
+ where.sql,
10707
+ orderClause(payload.sort_by),
10708
+ limitOffsetClause(payload)
10709
+ ].filter(Boolean);
10710
+ return asSingle(parts.join(" "), where.params);
10711
+ }
10712
+ function compileD1Count(payload) {
10713
+ rejectStructuredRelations(payload);
10714
+ const table = payload.table_name?.trim();
10715
+ if (!table) {
10716
+ throw new D1SqlCompileError("missing_table", "table_name is required for count");
10717
+ }
10718
+ let where = buildWhere(payload.conditions);
10719
+ if (!where.sql && payload.where && typeof payload.where === "object") {
10720
+ const eqConditions = Object.entries(
10721
+ payload.where
10722
+ ).map(([column, value]) => ({
10723
+ column,
10724
+ operator: "eq",
10725
+ value
10726
+ }));
10727
+ where = buildWhere(eqConditions);
10728
+ }
10729
+ return compileD1CountFromWhere(table, where);
10730
+ }
10731
+ function compileD1CountFromWhere(table, where) {
10732
+ const parts = [
10733
+ `SELECT COUNT(*) AS __athena_count FROM ${quoteIdent(table)}`,
10734
+ where.sql
10735
+ ].filter(Boolean);
10736
+ return asSingle(parts.join(" "), where.params);
10737
+ }
10738
+ function extractAthenaCount(rows) {
10739
+ const first = rows[0];
10740
+ const rawCount = first && typeof first === "object" && !Array.isArray(first) ? first.__athena_count : void 0;
10741
+ const count = typeof rawCount === "number" ? rawCount : typeof rawCount === "bigint" ? Number(rawCount) : Number(rawCount ?? 0);
10742
+ return Number.isFinite(count) ? count : 0;
10743
+ }
10744
+ function compileSingleRowInsert(table, row, payload) {
10745
+ const columns = Object.keys(row);
10746
+ if (columns.length === 0) {
10747
+ if (payload.on_conflict) {
10748
+ throw new D1SqlCompileError(
10749
+ "default_values_upsert_unsupported",
10750
+ "DEFAULT VALUES upsert is unsupported on D1 edge-local; provide insert columns or omit onConflict"
10751
+ );
10752
+ }
10753
+ const parts2 = [`INSERT INTO ${quoteIdent(table)} DEFAULT VALUES`];
10754
+ if (wantsReturning(payload)) {
10755
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10756
+ }
10757
+ return { sql: parts2.join(" "), params: [] };
10758
+ }
10759
+ const params = columns.map((column) => jsonValue(row[column]));
10760
+ const parts = [
10761
+ `INSERT INTO ${quoteIdent(table)} (${columns.map(quoteIdent).join(", ")})`,
10762
+ `VALUES (${columns.map(() => "?").join(", ")})`
10763
+ ];
10764
+ appendOnConflict(parts, params, payload, columns);
10765
+ if (wantsReturning(payload)) {
10766
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10767
+ }
10768
+ return { sql: parts.join(" "), params };
10769
+ }
10770
+ function parseOnConflictColumns(onConflict) {
10771
+ const raw = Array.isArray(onConflict) ? onConflict : [onConflict];
10772
+ const columns = [];
10773
+ for (const item of raw) {
10774
+ for (const part of String(item).split(",")) {
10775
+ const trimmed = part.trim();
10776
+ if (trimmed) columns.push(trimmed);
10777
+ }
10778
+ }
10779
+ if (columns.length === 0) {
10780
+ throw new D1SqlCompileError(
10781
+ "invalid_on_conflict",
10782
+ "on_conflict requires at least one column"
10783
+ );
10784
+ }
10785
+ return columns;
10786
+ }
10787
+ function appendOnConflict(parts, params, payload, insertColumns) {
10788
+ if (!payload.on_conflict) return;
10789
+ const conflictCols = parseOnConflictColumns(payload.on_conflict);
10790
+ const conflictSql = conflictCols.map(quoteIdent).join(", ");
10791
+ if (payload.update_body !== void 0 && payload.update_body !== null) {
10792
+ const entries = Object.entries(payload.update_body);
10793
+ if (entries.length === 0) {
10794
+ parts.push(`ON CONFLICT (${conflictSql}) DO NOTHING`);
10795
+ return;
10796
+ }
10797
+ const assignments2 = entries.map(([column, value]) => {
10798
+ params.push(jsonValue(value));
10799
+ return `${quoteIdent(column)} = ?`;
10800
+ });
10801
+ parts.push(`ON CONFLICT (${conflictSql}) DO UPDATE SET ${assignments2.join(", ")}`);
10802
+ return;
10803
+ }
10804
+ const conflictSet = new Set(conflictCols);
10805
+ const assignments = insertColumns.filter((column) => !conflictSet.has(column)).map((column) => {
10806
+ const quoted = quoteIdent(column);
10807
+ return `${quoted} = excluded.${quoted}`;
10808
+ });
10809
+ if (assignments.length === 0) {
10810
+ parts.push(`ON CONFLICT (${conflictSql}) DO NOTHING`);
10811
+ } else {
10812
+ parts.push(`ON CONFLICT (${conflictSql}) DO UPDATE SET ${assignments.join(", ")}`);
10813
+ }
10814
+ }
10815
+ function compileD1Insert(payload) {
10816
+ const table = payload.table_name?.trim();
10817
+ if (!table) {
10818
+ throw new D1SqlCompileError("missing_table", "table_name is required for insert");
10819
+ }
10820
+ const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
10821
+ if (rows.length === 0) {
10822
+ throw new D1SqlCompileError("empty_insert", "insert_body must not be empty");
10823
+ }
10824
+ const columns = [];
10825
+ const seen = /* @__PURE__ */ new Set();
10826
+ for (const row of rows) {
10827
+ for (const key of Object.keys(row ?? {})) {
10828
+ if (seen.has(key)) continue;
10829
+ seen.add(key);
10830
+ columns.push(key);
10831
+ }
10832
+ }
10833
+ if (columns.length === 0) {
10834
+ if (rows.length === 1) {
10835
+ const compiled = compileSingleRowInsert(table, {}, payload);
10836
+ return asSingle(compiled.sql, compiled.params);
10837
+ }
10838
+ throw new D1SqlCompileError(
10839
+ "empty_insert",
10840
+ "Multi-row insert_body cannot be empty objects; use a single {} for DEFAULT VALUES"
10841
+ );
10842
+ }
10843
+ const forceNullForMissing = payload.default_to_null === true;
10844
+ const isSparse = rows.some(
10845
+ (row) => columns.some((column) => !Object.prototype.hasOwnProperty.call(row, column))
10846
+ );
10847
+ if (isSparse && !forceNullForMissing && rows.length > 1) {
10848
+ return asBatch(
10849
+ rows.map((row) => compileSingleRowInsert(table, row, payload))
10850
+ );
10851
+ }
10852
+ if (isSparse && !forceNullForMissing && rows.length === 1) {
10853
+ const compiled = compileSingleRowInsert(table, rows[0], payload);
10854
+ return asSingle(compiled.sql, compiled.params);
10855
+ }
10856
+ const params = [];
10857
+ const valueGroups = rows.map((row) => {
10858
+ const placeholders = columns.map((column) => {
10859
+ const has = Object.prototype.hasOwnProperty.call(row, column);
10860
+ if (!has) {
10861
+ params.push(null);
10862
+ return "?";
10863
+ }
10864
+ params.push(jsonValue(row[column]));
10865
+ return "?";
10866
+ });
10867
+ return `(${placeholders.join(", ")})`;
10868
+ });
10869
+ const parts = [
10870
+ `INSERT INTO ${quoteIdent(table)} (${columns.map(quoteIdent).join(", ")})`,
10871
+ `VALUES ${valueGroups.join(", ")}`
10872
+ ];
10873
+ appendOnConflict(parts, params, payload, columns);
10874
+ if (wantsReturning(payload)) {
10875
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10876
+ }
10877
+ return asSingle(parts.join(" "), params);
10878
+ }
10879
+ function compileD1Update(payload, options) {
10880
+ const table = payload.table_name?.trim();
10881
+ if (!table) {
10882
+ throw new D1SqlCompileError("missing_table", "table_name is required for update");
10883
+ }
10884
+ const entries = Object.entries(payload.update_body ?? {});
10885
+ if (entries.length === 0) {
10886
+ throw new D1SqlCompileError("empty_update", "update_body must not be empty");
10887
+ }
10888
+ const params = [];
10889
+ const assignments = entries.map(([column, value]) => {
10890
+ params.push(jsonValue(value));
10891
+ return `${quoteIdent(column)} = ?`;
10892
+ });
10893
+ const where = buildWhere(payload.conditions);
10894
+ if (!where.sql) {
10895
+ throw new D1SqlCompileError(
10896
+ "unfiltered_update",
10897
+ "UPDATE requires at least one condition on D1 edge-local"
10898
+ );
10899
+ }
10900
+ if (hasPaginationBounds(payload) || payload.sort_by) {
10901
+ if (!hasPaginationBounds(payload)) {
10902
+ throw new D1SqlCompileError(
10903
+ "order_without_bounds",
10904
+ "UPDATE with sort_by requires limit/offset or page_size/current_page on D1 edge-local"
10905
+ );
10906
+ }
10907
+ const bounded = boundedRowidInClause(
10908
+ table,
10909
+ where.sql,
10910
+ where.params,
10911
+ {
10912
+ ...payload,
10913
+ conditions: payload.conditions
10914
+ },
10915
+ options
10916
+ );
10917
+ params.push(...bounded.params);
10918
+ const parts2 = [
10919
+ `UPDATE ${quoteIdent(table)} SET ${assignments.join(", ")}`,
10920
+ `WHERE ${bounded.sql}`
10921
+ ];
10922
+ if (wantsReturning(payload)) {
10923
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10924
+ }
10925
+ return asSingle(parts2.join(" "), params);
10926
+ }
10927
+ params.push(...where.params);
10928
+ const parts = [
10929
+ `UPDATE ${quoteIdent(table)} SET ${assignments.join(", ")}`,
10930
+ where.sql
10931
+ ];
10932
+ if (wantsReturning(payload)) {
10933
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10934
+ }
10935
+ return asSingle(parts.join(" "), params);
10936
+ }
10937
+ function compileD1Delete(payload, options) {
10938
+ const table = payload.table_name?.trim();
10939
+ if (!table) {
10940
+ throw new D1SqlCompileError("missing_table", "table_name is required for delete");
10941
+ }
10942
+ const conditions = [...payload.conditions ?? []];
10943
+ if (payload.resource_id !== void 0 && payload.resource_id !== null) {
10944
+ const hasResourceIdFilter = conditions.some((condition) => {
10945
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
10946
+ return column === "resource_id";
10947
+ });
10948
+ const hasIdFilter = conditions.some((condition) => {
10949
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
10950
+ return column === "id";
10951
+ });
10952
+ if (!hasResourceIdFilter && !hasIdFilter) {
10953
+ conditions.unshift({
10954
+ column: "id",
10955
+ operator: "eq",
10956
+ value: payload.resource_id
10957
+ });
10958
+ }
10959
+ }
10960
+ const where = buildWhere(conditions);
10961
+ if (!where.sql) {
10962
+ throw new D1SqlCompileError(
10963
+ "unfiltered_delete",
10964
+ "DELETE requires at least one condition or resource_id on D1 edge-local"
10965
+ );
10966
+ }
10967
+ if (hasPaginationBounds(payload) || payload.sort_by) {
10968
+ if (!hasPaginationBounds(payload)) {
10969
+ throw new D1SqlCompileError(
10970
+ "order_without_bounds",
10971
+ "DELETE with sort_by requires limit/offset or page_size/current_page on D1 edge-local"
10972
+ );
10973
+ }
10974
+ const bounded = boundedRowidInClause(
10975
+ table,
10976
+ where.sql,
10977
+ where.params,
10978
+ {
10979
+ ...payload,
10980
+ conditions
10981
+ },
10982
+ options
10983
+ );
10984
+ const parts2 = [`DELETE FROM ${quoteIdent(table)}`, `WHERE ${bounded.sql}`];
10985
+ if (wantsReturning(payload)) {
10986
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10987
+ }
10988
+ return asSingle(parts2.join(" "), bounded.params);
10989
+ }
10990
+ const parts = [`DELETE FROM ${quoteIdent(table)}`, where.sql];
10991
+ if (wantsReturning(payload)) {
10992
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10993
+ }
10994
+ return asSingle(parts.join(" "), where.params);
10995
+ }
10996
+
10997
+ // src/cloudflare/d1/sql-rewrite.ts
10998
+ var PG_CAST_TYPES = "text|uuid|citext|varchar|bpchar|char|integer|int4|int8|bigint|smallint|boolean|bool|jsonb|json|numeric|decimal|real|float|double precision|timestamptz|timestamp|date|bytea";
10999
+ function mapSqlOutsideLiterals(sql, transform) {
11000
+ let out = "";
11001
+ let buffer = "";
11002
+ let inSingle = false;
11003
+ let inDouble = false;
11004
+ let inBacktick = false;
11005
+ let inBracket = false;
11006
+ let inLineComment = false;
11007
+ let inBlockComment = false;
11008
+ const flushCode = () => {
11009
+ if (buffer) {
11010
+ out += transform(buffer);
11011
+ buffer = "";
11012
+ }
11013
+ };
11014
+ for (let i = 0; i < sql.length; i += 1) {
11015
+ const ch = sql[i];
11016
+ const next = sql[i + 1];
11017
+ if (inLineComment) {
11018
+ out += ch;
11019
+ if (ch === "\n" || ch === "\r") inLineComment = false;
11020
+ continue;
11021
+ }
11022
+ if (inBlockComment) {
11023
+ out += ch;
11024
+ if (ch === "*" && next === "/") {
11025
+ out += next;
11026
+ i += 1;
11027
+ inBlockComment = false;
11028
+ }
11029
+ continue;
11030
+ }
11031
+ if (inSingle) {
11032
+ out += ch;
11033
+ if (ch === "'" && next === "'") {
11034
+ out += next;
11035
+ i += 1;
11036
+ continue;
11037
+ }
11038
+ if (ch === "'") inSingle = false;
11039
+ continue;
11040
+ }
11041
+ if (inDouble) {
11042
+ out += ch;
11043
+ if (ch === '"' && next === '"') {
11044
+ out += next;
11045
+ i += 1;
11046
+ continue;
11047
+ }
11048
+ if (ch === '"') inDouble = false;
11049
+ continue;
11050
+ }
11051
+ if (inBacktick) {
11052
+ out += ch;
11053
+ if (ch === "`" && next === "`") {
11054
+ out += next;
11055
+ i += 1;
11056
+ continue;
11057
+ }
11058
+ if (ch === "`") inBacktick = false;
11059
+ continue;
11060
+ }
11061
+ if (inBracket) {
11062
+ out += ch;
11063
+ if (ch === "]") inBracket = false;
11064
+ continue;
11065
+ }
11066
+ if (ch === "-" && next === "-") {
11067
+ flushCode();
11068
+ out += ch;
11069
+ out += next;
11070
+ i += 1;
11071
+ inLineComment = true;
11072
+ continue;
11073
+ }
11074
+ if (ch === "/" && next === "*") {
11075
+ flushCode();
11076
+ out += ch;
11077
+ out += next;
11078
+ i += 1;
11079
+ inBlockComment = true;
11080
+ continue;
11081
+ }
11082
+ if (ch === "'") {
11083
+ flushCode();
11084
+ out += ch;
11085
+ inSingle = true;
11086
+ continue;
11087
+ }
11088
+ if (ch === '"') {
11089
+ flushCode();
11090
+ out += ch;
11091
+ inDouble = true;
11092
+ continue;
11093
+ }
11094
+ if (ch === "`") {
11095
+ flushCode();
11096
+ out += ch;
11097
+ inBacktick = true;
11098
+ continue;
11099
+ }
11100
+ if (ch === "[") {
11101
+ flushCode();
11102
+ out += ch;
11103
+ inBracket = true;
11104
+ continue;
11105
+ }
11106
+ buffer += ch;
11107
+ }
11108
+ flushCode();
11109
+ return out;
11110
+ }
11111
+ function isIdentChar2(ch) {
11112
+ if (!ch) return false;
11113
+ return /[A-Za-z0-9_]/.test(ch);
11114
+ }
11115
+ function collectLimitOffsetKeywords(sql) {
11116
+ const hits = [];
11117
+ let depth = 0;
11118
+ let statement = 0;
11119
+ let inSingle = false;
11120
+ let inDouble = false;
11121
+ let inBacktick = false;
11122
+ let inBracket = false;
11123
+ let inLineComment = false;
11124
+ let inBlockComment = false;
11125
+ for (let i = 0; i < sql.length; i += 1) {
11126
+ const ch = sql[i];
11127
+ const next = sql[i + 1];
11128
+ if (inLineComment) {
11129
+ if (ch === "\n" || ch === "\r") inLineComment = false;
11130
+ continue;
11131
+ }
11132
+ if (inBlockComment) {
11133
+ if (ch === "*" && next === "/") {
11134
+ i += 1;
11135
+ inBlockComment = false;
11136
+ }
11137
+ continue;
11138
+ }
11139
+ if (inSingle) {
11140
+ if (ch === "'" && next === "'") {
11141
+ i += 1;
11142
+ continue;
11143
+ }
11144
+ if (ch === "'") inSingle = false;
11145
+ continue;
11146
+ }
11147
+ if (inDouble) {
11148
+ if (ch === '"' && next === '"') {
11149
+ i += 1;
11150
+ continue;
11151
+ }
11152
+ if (ch === '"') inDouble = false;
11153
+ continue;
11154
+ }
11155
+ if (inBacktick) {
11156
+ if (ch === "`" && next === "`") {
11157
+ i += 1;
11158
+ continue;
11159
+ }
11160
+ if (ch === "`") inBacktick = false;
11161
+ continue;
11162
+ }
11163
+ if (inBracket) {
11164
+ if (ch === "]") inBracket = false;
11165
+ continue;
11166
+ }
11167
+ if (ch === "-" && next === "-") {
11168
+ inLineComment = true;
11169
+ i += 1;
11170
+ continue;
11171
+ }
11172
+ if (ch === "/" && next === "*") {
11173
+ inBlockComment = true;
11174
+ i += 1;
11175
+ continue;
11176
+ }
11177
+ if (ch === "'") {
11178
+ inSingle = true;
11179
+ continue;
11180
+ }
11181
+ if (ch === '"') {
11182
+ inDouble = true;
11183
+ continue;
11184
+ }
11185
+ if (ch === "`") {
11186
+ inBacktick = true;
11187
+ continue;
11188
+ }
11189
+ if (ch === "[") {
11190
+ inBracket = true;
11191
+ continue;
11192
+ }
11193
+ if (ch === "(") {
11194
+ depth += 1;
11195
+ continue;
11196
+ }
11197
+ if (ch === ")") {
11198
+ depth = Math.max(0, depth - 1);
11199
+ continue;
11200
+ }
11201
+ if (ch === ";" && depth === 0) {
11202
+ statement += 1;
11203
+ continue;
11204
+ }
11205
+ if (!isIdentChar2(ch) || isIdentChar2(sql[i - 1])) {
11206
+ continue;
11207
+ }
11208
+ const rest = sql.slice(i);
11209
+ if (/^LIMIT\b/i.test(rest)) {
11210
+ hits.push({ kind: "limit", start: i, depth, statement });
11211
+ i += 4;
11212
+ continue;
11213
+ }
11214
+ if (/^OFFSET\b/i.test(rest)) {
11215
+ hits.push({ kind: "offset", start: i, depth, statement });
11216
+ i += 5;
11217
+ }
11218
+ }
11219
+ return hits;
11220
+ }
11221
+ function injectLimitBeforeBareOffsets(sql) {
11222
+ const hits = collectLimitOffsetKeywords(sql);
11223
+ if (hits.length === 0) return sql;
11224
+ const injectAt = [];
11225
+ for (const hit of hits) {
11226
+ if (hit.kind !== "offset") continue;
11227
+ let hasLimit = false;
11228
+ for (let i = hits.length - 1; i >= 0; i -= 1) {
11229
+ const prev = hits[i];
11230
+ if (prev.start >= hit.start) continue;
11231
+ if (prev.statement !== hit.statement) continue;
11232
+ if (prev.depth !== hit.depth) continue;
11233
+ if (prev.kind === "limit") {
11234
+ hasLimit = true;
11235
+ break;
11236
+ }
11237
+ if (prev.kind === "offset") {
11238
+ break;
11239
+ }
11240
+ }
11241
+ if (!hasLimit) {
11242
+ injectAt.push(hit.start);
11243
+ }
11244
+ }
11245
+ if (injectAt.length === 0) return sql;
11246
+ let out = sql;
11247
+ for (let i = injectAt.length - 1; i >= 0; i -= 1) {
11248
+ const at = injectAt[i];
11249
+ out = `${out.slice(0, at)}LIMIT -1 ${out.slice(at)}`;
11250
+ }
11251
+ return out;
11252
+ }
11253
+ function rewritePostgresSqlForSqlite(sql) {
11254
+ const castPattern = new RegExp(`::(?:${PG_CAST_TYPES})\\b`, "gi");
11255
+ const withoutCastsAndIlike = mapSqlOutsideLiterals(sql, (chunk) => {
11256
+ let rewritten = chunk.replace(castPattern, "");
11257
+ rewritten = rewritten.replace(/\bILIKE\b/gi, "LIKE");
11258
+ return rewritten;
11259
+ });
11260
+ return injectLimitBeforeBareOffsets(withoutCastsAndIlike);
11261
+ }
11262
+
11263
+ // src/cloudflare/d1/transport.ts
11264
+ function hasPaginationBounds2(payload) {
11265
+ return payload.limit !== void 0 || payload.offset !== void 0 || payload.page_size !== void 0 || payload.current_page !== void 0;
11266
+ }
11267
+ function normalizeSqliteCollation(name) {
11268
+ const raw = String(name ?? "").trim().replace(/^["'`[]|["'`\]]$/g, "");
11269
+ if (!raw) return "BINARY";
11270
+ return raw.toUpperCase();
11271
+ }
11272
+ function findCreateTableColumnListOpen(createSql) {
11273
+ const m = /\bCREATE\s+(?:(?:TEMP|TEMPORARY|VIRTUAL)\s+)?TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?/i.exec(
11274
+ createSql
11275
+ );
11276
+ if (!m) return -1;
11277
+ let i = m.index + m[0].length;
11278
+ let inSingle = false;
11279
+ let inDouble = false;
11280
+ let inBacktick = false;
11281
+ let inBracket = false;
11282
+ while (i < createSql.length) {
11283
+ const ch = createSql[i];
11284
+ if (inSingle) {
11285
+ if (ch === "'" && createSql[i + 1] === "'") {
11286
+ i += 2;
11287
+ continue;
11288
+ }
11289
+ if (ch === "'") inSingle = false;
11290
+ i++;
11291
+ continue;
11292
+ }
11293
+ if (inDouble) {
11294
+ if (ch === '"') inDouble = false;
11295
+ i++;
11296
+ continue;
11297
+ }
11298
+ if (inBacktick) {
11299
+ if (ch === "`") inBacktick = false;
11300
+ i++;
11301
+ continue;
11302
+ }
11303
+ if (inBracket) {
11304
+ if (ch === "]") inBracket = false;
11305
+ i++;
11306
+ continue;
11307
+ }
11308
+ if (ch === "'") {
11309
+ inSingle = true;
11310
+ i++;
11311
+ continue;
11312
+ }
11313
+ if (ch === '"') {
11314
+ inDouble = true;
11315
+ i++;
11316
+ continue;
11317
+ }
11318
+ if (ch === "`") {
11319
+ inBacktick = true;
11320
+ i++;
11321
+ continue;
11322
+ }
11323
+ if (ch === "[") {
11324
+ inBracket = true;
11325
+ i++;
11326
+ continue;
11327
+ }
11328
+ if (ch === "(") return i;
11329
+ i++;
11330
+ }
11331
+ return -1;
11332
+ }
11333
+ function parseColumnCollationFromCreateSql(createSql, columnName) {
11334
+ if (!createSql || !columnName) return null;
11335
+ const listOpen = findCreateTableColumnListOpen(createSql);
11336
+ if (listOpen < 0) return null;
11337
+ const listStart = listOpen + 1;
11338
+ const escaped = columnName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11339
+ const nameRe = new RegExp(
11340
+ `(?:^|[^\\w])(?:"${escaped}"|\`${escaped}\`|\\[${escaped}\\]|${escaped})\\s+`,
11341
+ "i"
11342
+ );
11343
+ const listSlice = createSql.slice(listStart);
11344
+ let nameMatchAbs = -1;
11345
+ let nameMatchLen = 0;
11346
+ {
11347
+ let i2 = 0;
11348
+ let depth2 = 1;
11349
+ let inSingle2 = false;
11350
+ let inDouble2 = false;
11351
+ let inBacktick2 = false;
11352
+ let inBracket2 = false;
11353
+ let segmentStart = 0;
11354
+ const trySegment = (from, to) => {
11355
+ if (nameMatchAbs >= 0) return;
11356
+ const segment = listSlice.slice(from, to);
11357
+ const m = nameRe.exec(segment);
11358
+ if (!m) return;
11359
+ const leading = segment.slice(0, m.index).trim();
11360
+ if (leading.length > 0) return;
11361
+ nameMatchAbs = listStart + from + m.index;
11362
+ nameMatchLen = m[0].length;
11363
+ };
11364
+ while (i2 < listSlice.length && depth2 > 0) {
11365
+ const ch = listSlice[i2];
11366
+ if (inSingle2) {
11367
+ if (ch === "'" && listSlice[i2 + 1] === "'") {
11368
+ i2 += 2;
11369
+ continue;
11370
+ }
11371
+ if (ch === "'") inSingle2 = false;
11372
+ i2++;
11373
+ continue;
11374
+ }
11375
+ if (inDouble2) {
11376
+ if (ch === '"') inDouble2 = false;
11377
+ i2++;
11378
+ continue;
11379
+ }
11380
+ if (inBacktick2) {
11381
+ if (ch === "`") inBacktick2 = false;
11382
+ i2++;
11383
+ continue;
11384
+ }
11385
+ if (inBracket2) {
11386
+ if (ch === "]") inBracket2 = false;
11387
+ i2++;
11388
+ continue;
11389
+ }
11390
+ if (ch === "'") {
11391
+ inSingle2 = true;
11392
+ i2++;
11393
+ continue;
11394
+ }
11395
+ if (ch === '"') {
11396
+ inDouble2 = true;
11397
+ i2++;
11398
+ continue;
11399
+ }
11400
+ if (ch === "`") {
11401
+ inBacktick2 = true;
11402
+ i2++;
11403
+ continue;
11404
+ }
11405
+ if (ch === "[") {
11406
+ inBracket2 = true;
11407
+ i2++;
11408
+ continue;
11409
+ }
11410
+ if (ch === "(") {
11411
+ depth2++;
11412
+ i2++;
11413
+ continue;
11414
+ }
11415
+ if (ch === ")") {
11416
+ depth2--;
11417
+ if (depth2 === 0) {
11418
+ trySegment(segmentStart, i2);
11419
+ break;
11420
+ }
11421
+ i2++;
11422
+ continue;
11423
+ }
11424
+ if (ch === "," && depth2 === 1) {
11425
+ trySegment(segmentStart, i2);
11426
+ segmentStart = i2 + 1;
11427
+ i2++;
11428
+ continue;
11429
+ }
11430
+ i2++;
11431
+ }
11432
+ }
11433
+ if (nameMatchAbs < 0 || nameMatchLen <= 0) return null;
11434
+ const start = nameMatchAbs + nameMatchLen;
11435
+ let i = start;
11436
+ let depth = 0;
11437
+ let inSingle = false;
11438
+ let inDouble = false;
11439
+ let inBacktick = false;
11440
+ let inBracket = false;
11441
+ while (i < createSql.length) {
11442
+ const ch = createSql[i];
11443
+ if (inSingle) {
11444
+ if (ch === "'" && createSql[i + 1] === "'") {
11445
+ i += 2;
11446
+ continue;
11447
+ }
11448
+ if (ch === "'") inSingle = false;
11449
+ i++;
11450
+ continue;
11451
+ }
11452
+ if (inDouble) {
11453
+ if (ch === '"') inDouble = false;
11454
+ i++;
11455
+ continue;
11456
+ }
11457
+ if (inBacktick) {
11458
+ if (ch === "`") inBacktick = false;
11459
+ i++;
11460
+ continue;
11461
+ }
11462
+ if (inBracket) {
11463
+ if (ch === "]") inBracket = false;
11464
+ i++;
11465
+ continue;
11466
+ }
11467
+ if (ch === "'") {
11468
+ inSingle = true;
11469
+ i++;
11470
+ continue;
11471
+ }
11472
+ if (ch === '"') {
11473
+ inDouble = true;
11474
+ i++;
11475
+ continue;
11476
+ }
11477
+ if (ch === "`") {
11478
+ inBacktick = true;
11479
+ i++;
11480
+ continue;
11481
+ }
11482
+ if (ch === "[") {
11483
+ inBracket = true;
11484
+ i++;
11485
+ continue;
11486
+ }
11487
+ if (ch === "(") {
11488
+ depth++;
11489
+ i++;
11490
+ continue;
11491
+ }
11492
+ if (ch === ")") {
11493
+ if (depth === 0) {
11494
+ break;
11495
+ }
11496
+ depth--;
11497
+ i++;
11498
+ continue;
11499
+ }
11500
+ if (ch === "," && depth === 0) {
11501
+ break;
11502
+ }
11503
+ i++;
11504
+ }
11505
+ const colDef = createSql.slice(start, i);
11506
+ const collRe = /\bCOLLATE\s+("([^"]+)"|'([^']+)'|`([^`]+)`|\[([^\]]+)\]|([A-Za-z_][\w$]*))/i;
11507
+ const match = collRe.exec(colDef);
11508
+ if (!match) return null;
11509
+ return match[2] ?? match[3] ?? match[4] ?? match[5] ?? match[6] ?? match[1] ?? null;
11510
+ }
11511
+ async function indexCollationMatchesColumn(d1, table, tableSafe, indexSafe, columnName, session) {
11512
+ const xinfo = await executeD1Query(d1, {
11513
+ query: `PRAGMA index_xinfo("${indexSafe}")`,
11514
+ params: [],
11515
+ ...session
11516
+ });
11517
+ if (!xinfo.ok) {
11518
+ return false;
11519
+ }
11520
+ const xRows = xinfo.rows ?? [];
11521
+ const keyRows = xRows.filter((row) => {
11522
+ const isKey = row.key === 1 || row.key === true || Number(row.key) === 1;
11523
+ if (!isKey) return false;
11524
+ return typeof row.name === "string" && row.name === columnName;
11525
+ });
11526
+ if (keyRows.length === 0) {
11527
+ const byName = xRows.find(
11528
+ (row) => typeof row.name === "string" && row.name === columnName
11529
+ );
11530
+ if (!byName) return false;
11531
+ keyRows.push(byName);
11532
+ }
11533
+ const indexColl = normalizeSqliteCollation(keyRows[0]?.coll);
11534
+ const master = await executeD1Query(d1, {
11535
+ query: `SELECT sql AS create_sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
11536
+ params: [table],
11537
+ ...session
11538
+ });
11539
+ let createSql = "";
11540
+ if (master.ok && Array.isArray(master.rows) && master.rows.length > 0) {
11541
+ createSql = String(
11542
+ master.rows[0]?.create_sql ?? ""
11543
+ );
11544
+ }
11545
+ const columnCollRaw = parseColumnCollationFromCreateSql(createSql, columnName);
11546
+ const columnColl = normalizeSqliteCollation(columnCollRaw);
11547
+ return indexColl === columnColl;
11548
+ }
11549
+ async function resolveD1BoundedIdentityColumn(d1, tableName, session) {
11550
+ const table = tableName.trim();
11551
+ if (!table) {
11552
+ throw new D1SqlCompileError("missing_table", "table_name is required for bounded mutation");
11553
+ }
11554
+ const safe = table.replace(/"/g, '""');
11555
+ const info = await executeD1Query(d1, {
11556
+ query: `PRAGMA table_info("${safe}")`,
11557
+ params: [],
11558
+ ...session
11559
+ });
11560
+ if (!info.ok) {
11561
+ throw new D1SqlCompileError(
11562
+ "bounded_mutation_no_unique_identity",
11563
+ `Unable to introspect table "${table}" for bounded mutation identity: ${info.message}`
11564
+ );
11565
+ }
11566
+ const cols = info.rows.filter(
11567
+ (row) => typeof row?.name === "string" && row.name.length > 0
11568
+ );
11569
+ const colByName = new Map(cols.map((col) => [col.name, col]));
11570
+ const isNotNullColumn = (name) => {
11571
+ const col = colByName.get(name);
11572
+ if (!col) return false;
11573
+ return col.notnull === 1 || col.notnull === true || Number(col.notnull) === 1;
11574
+ };
11575
+ const isIntegerPrimaryKeyType = (col) => {
11576
+ if (typeof col.pk !== "number" || col.pk <= 0) return false;
11577
+ const declared = String(col.type ?? "").trim().toUpperCase();
11578
+ return declared === "INTEGER";
11579
+ };
11580
+ const loadIndexList = async () => {
11581
+ const indexList = await executeD1Query(d1, {
11582
+ query: `PRAGMA index_list("${safe}")`,
11583
+ params: [],
11584
+ ...session
11585
+ });
11586
+ if (!indexList.ok) return null;
11587
+ return indexList.rows;
11588
+ };
11589
+ const isDescendingIntegerPrimaryKeyException = async (colName, indexes) => {
11590
+ if (indexes) {
11591
+ const hasPkOrigin = indexes.some(
11592
+ (index) => String(index.origin ?? "").toLowerCase() === "pk"
11593
+ );
11594
+ if (hasPkOrigin) return true;
11595
+ const originReported = indexes.some(
11596
+ (index) => index.origin !== void 0 && index.origin !== null && String(index.origin).length > 0
11597
+ );
11598
+ if (indexes.length === 0 || originReported) {
11599
+ return false;
11600
+ }
11601
+ }
11602
+ const master = await executeD1Query(d1, {
11603
+ query: `SELECT sql AS create_sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
11604
+ params: [table],
11605
+ ...session
11606
+ });
11607
+ if (!master.ok || !Array.isArray(master.rows) || master.rows.length === 0) {
11608
+ return false;
11609
+ }
11610
+ const createSql = String(
11611
+ master.rows[0]?.create_sql ?? ""
11612
+ );
11613
+ if (!createSql) return false;
11614
+ const escaped = colName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11615
+ const inlineDesc = new RegExp(
11616
+ `(?:^|[^\\w])(?:"${escaped}"|${escaped})\\s+INTEGER\\s+PRIMARY\\s+KEY\\s+DESC\\b`,
11617
+ "i"
11618
+ );
11619
+ const tableDesc = new RegExp(
11620
+ `PRIMARY\\s+KEY\\s*\\(\\s*(?:"${escaped}"|${escaped})\\s+DESC\\b`,
11621
+ "i"
11622
+ );
11623
+ return inlineDesc.test(createSql) || tableDesc.test(createSql);
11624
+ };
11625
+ const pkCols = cols.filter((row) => typeof row.pk === "number" && row.pk > 0).sort((a, b) => (a.pk ?? 0) - (b.pk ?? 0));
11626
+ let indexRows;
11627
+ if (pkCols.length === 1 && pkCols[0]?.name) {
11628
+ if (isIntegerPrimaryKeyType(pkCols[0])) {
11629
+ indexRows = await loadIndexList();
11630
+ const isDescException = await isDescendingIntegerPrimaryKeyException(
11631
+ pkCols[0].name,
11632
+ indexRows
11633
+ );
11634
+ if (!isDescException) {
11635
+ return pkCols[0].name;
11636
+ }
11637
+ } else if (isNotNullColumn(pkCols[0].name)) {
11638
+ indexRows = await loadIndexList();
11639
+ const pkIndex = (indexRows ?? []).find(
11640
+ (index) => String(index.origin ?? "").toLowerCase() === "pk"
11641
+ );
11642
+ if (pkIndex && typeof pkIndex.name === "string" && pkIndex.name) {
11643
+ const indexSafe = pkIndex.name.replace(/"/g, '""');
11644
+ const collMatch = await indexCollationMatchesColumn(
11645
+ d1,
11646
+ table,
11647
+ safe,
11648
+ indexSafe,
11649
+ pkCols[0].name,
11650
+ session
11651
+ );
11652
+ if (collMatch) {
11653
+ return pkCols[0].name;
11654
+ }
11655
+ }
11656
+ }
11657
+ }
11658
+ if (indexRows === void 0) {
11659
+ indexRows = await loadIndexList();
11660
+ }
11661
+ if (indexRows) {
11662
+ for (const index of indexRows) {
11663
+ const unique = index.unique === 1 || index.unique === true || Number(index.unique) === 1;
11664
+ if (!unique || typeof index.name !== "string" || !index.name) continue;
11665
+ const isPartial = index.partial === 1 || index.partial === true || Number(index.partial) === 1;
11666
+ if (isPartial) {
11667
+ continue;
11668
+ }
11669
+ const indexSafe = index.name.replace(/"/g, '""');
11670
+ const indexInfo = await executeD1Query(d1, {
11671
+ query: `PRAGMA index_info("${indexSafe}")`,
11672
+ params: [],
11673
+ ...session
11674
+ });
11675
+ if (!indexInfo.ok) continue;
11676
+ const rawIndexCols = indexInfo.rows ?? [];
11677
+ const hasExpressionTerm = rawIndexCols.some((row) => {
11678
+ const nameOk = typeof row?.name === "string" && row.name.length > 0;
11679
+ if (!nameOk) return true;
11680
+ if (typeof row.cid === "number" && row.cid < 0) return true;
11681
+ return false;
11682
+ });
11683
+ if (hasExpressionTerm || rawIndexCols.length === 0) {
11684
+ continue;
11685
+ }
11686
+ const indexCols = rawIndexCols.filter(
11687
+ (row) => typeof row?.name === "string" && row.name.length > 0
11688
+ );
11689
+ if (indexCols.length === 1 && indexCols[0]?.name) {
11690
+ const identity = indexCols[0].name;
11691
+ if (!isNotNullColumn(identity)) {
11692
+ continue;
11693
+ }
11694
+ const collMatch = await indexCollationMatchesColumn(
11695
+ d1,
11696
+ table,
11697
+ safe,
11698
+ indexSafe,
11699
+ identity,
11700
+ session
11701
+ );
11702
+ if (!collMatch) {
11703
+ continue;
11704
+ }
11705
+ return identity;
11706
+ }
11707
+ }
11708
+ }
11709
+ throw new D1SqlCompileError(
11710
+ "bounded_mutation_no_unique_identity",
11711
+ `Bounded update/delete on "${table}" requires a proven single-column PRIMARY KEY or UNIQUE index`
11712
+ );
11713
+ }
11714
+ async function compileOptionsForBoundedMutation(d1, payload, session) {
11715
+ if (!hasPaginationBounds2(payload) && !payload.sort_by) {
11716
+ return void 0;
11717
+ }
11718
+ if (!hasPaginationBounds2(payload)) {
11719
+ return void 0;
11720
+ }
11721
+ const identityColumn = await resolveD1BoundedIdentityColumn(
11722
+ d1,
11723
+ payload.table_name ?? "",
11724
+ session
11725
+ );
11726
+ return { identityColumn };
11727
+ }
11728
+ function headerValue2(options, name) {
11729
+ const headers = options?.headers;
11730
+ if (!headers) return void 0;
11731
+ const lower = name.toLowerCase();
11732
+ for (const [key, value] of Object.entries(headers)) {
11733
+ if (key.toLowerCase() === lower && value?.trim()) {
11734
+ return value.trim();
11735
+ }
11736
+ }
11737
+ return void 0;
11738
+ }
11739
+ function sessionFromOptions(options, defaults) {
11740
+ return {
11741
+ bookmark: headerValue2(options, "x-athena-d1-bookmark") ?? null,
11742
+ sessionMode: headerValue2(options, "x-athena-d1-session-mode") ?? defaults.defaultSessionMode ?? null
11743
+ };
11744
+ }
11745
+ function resolveStripNulls(payloadStrip, callOptions, defaultValue = true) {
11746
+ if (typeof payloadStrip === "boolean") return payloadStrip;
11747
+ if (typeof callOptions?.stripNulls === "boolean") return callOptions.stripNulls;
11748
+ return defaultValue;
11749
+ }
11750
+ function stripNullPropertiesFromRows(rows) {
11751
+ return rows.map((row) => {
11752
+ if (row == null || typeof row !== "object" || Array.isArray(row)) {
11753
+ return row;
11754
+ }
11755
+ const out = {};
11756
+ for (const [key, value] of Object.entries(row)) {
11757
+ if (value !== null) {
11758
+ out[key] = value;
11759
+ }
11760
+ }
11761
+ return out;
11762
+ });
11763
+ }
11764
+ function maybeStripNullRows(rows, strip) {
11765
+ return strip ? stripNullPropertiesFromRows(rows) : rows;
11766
+ }
11767
+ function successResponse(data, count, raw, bookmark) {
11768
+ const response = {
11769
+ ok: true,
11770
+ status: 200,
11771
+ statusText: "OK",
11772
+ data,
11773
+ count: count ?? null,
11774
+ error: void 0,
11775
+ errorDetails: null,
11776
+ raw
11777
+ };
11778
+ if (bookmark) {
11779
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
11780
+ const rawRecord = raw;
11781
+ rawRecord.bookmark = bookmark;
11782
+ }
11783
+ }
11784
+ return response;
11785
+ }
11786
+ function errorResponse(status, code, message, endpoint, method, hint) {
11787
+ const error = new AthenaGatewayError({
11788
+ code,
11789
+ message,
11790
+ status,
11791
+ endpoint,
11792
+ method,
11793
+ hint
11794
+ });
11795
+ return {
11796
+ ok: false,
11797
+ status,
11798
+ statusText: null,
11799
+ data: null,
11800
+ error: error.message,
11801
+ errorDetails: error.toDetails(),
11802
+ raw: { error: message, code }
11803
+ };
11804
+ }
11805
+ function compileErrorResponse(error, endpoint, method) {
11806
+ if (error instanceof D1SqlCompileError) {
11807
+ return errorResponse(
11808
+ 400,
11809
+ "HTTP_ERROR",
11810
+ error.message,
11811
+ endpoint,
11812
+ method,
11813
+ `D1 SQL compile failed (${error.code})`
11814
+ );
11815
+ }
11816
+ const message = error instanceof Error ? error.message : String(error);
11817
+ return errorResponse(500, "UNKNOWN_ERROR", message, endpoint, method);
11818
+ }
11819
+ function createCloudflareD1GatewayTransport(options) {
11820
+ const { d1 } = options;
11821
+ async function runCompiled(compiled, callOptions, endpoint, method, mapResult, stripNulls = true) {
11822
+ try {
11823
+ const session = sessionFromOptions(callOptions, options);
11824
+ if (compiled.statements && compiled.statements.length > 1) {
11825
+ const batch = await executeD1Batch(d1, {
11826
+ statements: compiled.statements.map((statement) => ({
11827
+ query: statement.sql,
11828
+ params: statement.params
11829
+ })),
11830
+ ...session
11831
+ });
11832
+ if (!batch.ok) {
11833
+ return errorResponse(400, "HTTP_ERROR", batch.message, endpoint, method);
11834
+ }
11835
+ const rows2 = maybeStripNullRows(
11836
+ batch.results.flatMap(
11837
+ (item) => Array.isArray(item.results) ? item.results : []
11838
+ ),
11839
+ stripNulls
11840
+ );
11841
+ const changes = batch.results.reduce((sum2, item) => {
11842
+ const meta = item?.meta;
11843
+ const n = meta && typeof meta === "object" && typeof meta.changes === "number" ? meta.changes : 0;
11844
+ return sum2 + n;
11845
+ }, 0);
11846
+ const count = rows2.length > 0 ? rows2.length : changes;
11847
+ const mapped2 = mapResult?.(rows2, count) ?? {
11848
+ data: rows2,
11849
+ count
11850
+ };
11851
+ return successResponse(mapped2.data, mapped2.count, batch, batch.bookmark);
11852
+ }
11853
+ const result = await executeD1Query(d1, {
11854
+ query: compiled.sql,
11855
+ params: compiled.params,
11856
+ ...session
11857
+ });
11858
+ if (!result.ok) {
11859
+ return errorResponse(400, "HTTP_ERROR", result.message, endpoint, method);
11860
+ }
11861
+ const rows = maybeStripNullRows(result.rows, stripNulls);
11862
+ const mapped = mapResult?.(rows, result.count) ?? {
11863
+ data: rows,
11864
+ count: result.count
11865
+ };
11866
+ return successResponse(mapped.data, mapped.count, result, result.bookmark);
11867
+ } catch (error) {
11868
+ const message = error instanceof Error ? error.message : String(error);
11869
+ return errorResponse(500, "UNKNOWN_ERROR", message, endpoint, method);
11870
+ }
11871
+ }
11872
+ return {
11873
+ baseUrl: CLOUDFLARE_EDGE_BASE_URL,
11874
+ buildHeaders(callOptions) {
11875
+ return { ...callOptions?.headers ?? {} };
11876
+ },
11877
+ async resolveCallOptions(callOptions) {
11878
+ return callOptions;
11879
+ },
11880
+ async verifyConnection(connectionOptions) {
11881
+ const baseUrl = CLOUDFLARE_EDGE_BASE_URL;
11882
+ try {
11883
+ const result = await executeD1Query(d1, { query: "SELECT 1 AS ok" });
11884
+ if (!result.ok) {
11885
+ return {
11886
+ ok: false,
11887
+ reachable: false,
11888
+ status: 500,
11889
+ statusText: null,
11890
+ baseUrl,
11891
+ url: `${baseUrl}/d1`,
11892
+ error: result.message,
11893
+ errorDetails: null,
11894
+ raw: result
11895
+ };
11896
+ }
11897
+ return {
11898
+ ok: true,
11899
+ reachable: true,
11900
+ status: 200,
11901
+ statusText: "OK",
11902
+ baseUrl,
11903
+ url: `${baseUrl}/d1`,
11904
+ error: void 0,
11905
+ errorDetails: null,
11906
+ raw: result
11907
+ };
11908
+ } catch (error) {
11909
+ const message = error instanceof Error ? error.message : String(error);
11910
+ return {
11911
+ ok: false,
11912
+ reachable: false,
11913
+ status: 0,
11914
+ statusText: null,
11915
+ baseUrl,
11916
+ url: `${baseUrl}/d1`,
11917
+ error: message,
11918
+ errorDetails: null,
11919
+ raw: null
11920
+ };
11921
+ }
11922
+ },
11923
+ async fetchGateway(payload, callOptions) {
11924
+ try {
11925
+ if (payload && typeof payload === "object" && "operation" in payload) {
11926
+ return errorResponse(
11927
+ 400,
11928
+ "HTTP_ERROR",
11929
+ "Direct AST operation payloads are unsupported on D1 edge-local",
11930
+ "/gateway/fetch",
11931
+ "POST"
11932
+ );
11933
+ }
11934
+ const compiled = compileD1Fetch(payload);
11935
+ const stripNulls = resolveStripNulls(payload.strip_nulls, callOptions, true);
11936
+ if (payload.head === true) {
11937
+ return runCompiled(
11938
+ compiled,
11939
+ callOptions,
11940
+ "/gateway/fetch",
11941
+ "POST",
11942
+ (rows) => ({ data: [], count: extractAthenaCount(rows) }),
11943
+ // COUNT rows are meta, not user-facing object rows
11944
+ false
11945
+ );
11946
+ }
11947
+ const wantsTotalCount = payload.count === "exact" || payload.count === "planned" || payload.count === "estimated";
11948
+ if (wantsTotalCount) {
11949
+ const session = sessionFromOptions(callOptions, options);
11950
+ const countCompiled = compileD1Count(payload);
11951
+ const batch = await executeD1Batch(d1, {
11952
+ statements: [
11953
+ {
11954
+ query: compiled.sql,
11955
+ params: compiled.params
11956
+ },
11957
+ {
11958
+ query: countCompiled.sql,
11959
+ params: countCompiled.params
11960
+ }
11961
+ ],
11962
+ ...session
11963
+ });
11964
+ if (!batch.ok) {
11965
+ return errorResponse(400, "HTTP_ERROR", batch.message, "/gateway/fetch", "POST");
11966
+ }
11967
+ const dataItem = batch.results[0];
11968
+ const countItem = batch.results[1];
11969
+ if (!dataItem || dataItem.success === false) {
11970
+ const message = dataItem && typeof dataItem.error === "string" && dataItem.error.trim() ? dataItem.error : "D1 page query failed";
11971
+ return errorResponse(400, "HTTP_ERROR", message, "/gateway/fetch", "POST");
11972
+ }
11973
+ if (!countItem || countItem.success === false) {
11974
+ const message = countItem && typeof countItem.error === "string" && countItem.error.trim() ? countItem.error : "D1 count query failed";
11975
+ return errorResponse(400, "HTTP_ERROR", message, "/gateway/fetch", "POST");
11976
+ }
11977
+ const dataRows = Array.isArray(dataItem.results) ? dataItem.results : [];
11978
+ const countRows = Array.isArray(countItem.results) ? countItem.results : [];
11979
+ const total = extractAthenaCount(countRows);
11980
+ const rows = maybeStripNullRows(dataRows, stripNulls);
11981
+ return successResponse(
11982
+ rows,
11983
+ total,
11984
+ { data: dataItem, count: countItem, batch },
11985
+ batch.bookmark
11986
+ );
11987
+ }
11988
+ return runCompiled(compiled, callOptions, "/gateway/fetch", "POST", void 0, stripNulls);
11989
+ } catch (error) {
11990
+ return compileErrorResponse(error, "/gateway/fetch", "POST");
11991
+ }
11992
+ },
11993
+ async insertGateway(payload, callOptions) {
11994
+ try {
11995
+ const compiled = compileD1Insert(payload);
11996
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
11997
+ return runCompiled(compiled, callOptions, "/gateway/insert", "PUT", void 0, stripNulls);
11998
+ } catch (error) {
11999
+ return compileErrorResponse(error, "/gateway/insert", "PUT");
12000
+ }
12001
+ },
12002
+ async updateGateway(payload, callOptions) {
12003
+ try {
12004
+ const session = sessionFromOptions(callOptions, options);
12005
+ const compileOptions = await compileOptionsForBoundedMutation(d1, payload, session);
12006
+ const compiled = compileD1Update(payload, compileOptions);
12007
+ const stripNulls = resolveStripNulls(payload.strip_nulls, callOptions, true);
12008
+ return runCompiled(compiled, callOptions, "/gateway/update", "POST", void 0, stripNulls);
12009
+ } catch (error) {
12010
+ return compileErrorResponse(error, "/gateway/update", "POST");
12011
+ }
12012
+ },
12013
+ async deleteGateway(payload, callOptions) {
12014
+ try {
12015
+ const session = sessionFromOptions(callOptions, options);
12016
+ const compileOptions = await compileOptionsForBoundedMutation(d1, payload, session);
12017
+ const compiled = compileD1Delete(payload, compileOptions);
12018
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
12019
+ return runCompiled(compiled, callOptions, "/gateway/delete", "DELETE", void 0, stripNulls);
12020
+ } catch (error) {
12021
+ return compileErrorResponse(error, "/gateway/delete", "DELETE");
12022
+ }
12023
+ },
12024
+ async rpcGateway(payload, callOptions) {
12025
+ return errorResponse(
12026
+ 400,
12027
+ "HTTP_ERROR",
12028
+ "RPC is unsupported on D1 edge-local mode",
12029
+ "/gateway/rpc",
12030
+ "POST",
12031
+ "Use flat CRUD or raw query SQL instead"
12032
+ );
12033
+ },
12034
+ async queryGateway(payload, callOptions) {
12035
+ try {
12036
+ const params = payload.params ?? callOptions?.params;
12037
+ const session = sessionFromOptions(callOptions, options);
12038
+ const query = rewritePostgresSqlForSqlite(payload.query);
12039
+ const result = await executeD1Query(d1, {
12040
+ query,
12041
+ params: Array.isArray(params) ? params : [],
12042
+ ...session
12043
+ });
12044
+ if (!result.ok) {
12045
+ return errorResponse(400, "HTTP_ERROR", result.message, "/gateway/query", "POST");
12046
+ }
12047
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
12048
+ const rows = maybeStripNullRows(result.rows, stripNulls);
12049
+ return successResponse(
12050
+ rows,
12051
+ result.count,
12052
+ { ...result, query },
12053
+ result.bookmark
12054
+ );
12055
+ } catch (error) {
12056
+ const message = error instanceof Error ? error.message : String(error);
12057
+ return errorResponse(500, "UNKNOWN_ERROR", message, "/gateway/query", "POST");
12058
+ }
12059
+ }
12060
+ };
12061
+ }
12062
+
12063
+ // src/config/errors.ts
12064
+ var AthenaConfigurationError = class extends Error {
12065
+ code;
12066
+ service;
12067
+ constructor(code, message, service) {
12068
+ super(message);
12069
+ this.name = "AthenaConfigurationError";
12070
+ this.code = code;
12071
+ this.service = service;
12072
+ }
12073
+ };
12074
+
12075
+ // src/cloudflare/execution-mode.ts
12076
+ var ATHENA_EXECUTION_MODE_ENV_KEY = "ATHENA_EXECUTION_MODE";
12077
+ var ATHENA_EXECUTION_PREFER_ENV_KEY = "ATHENA_EXECUTION_PREFER";
12078
+ var MODE_ALIASES = {
12079
+ gateway: "gateway",
12080
+ server: "gateway",
12081
+ remote: "gateway",
12082
+ http: "gateway",
12083
+ edge: "edge",
12084
+ cloudflare: "edge",
12085
+ "cloudflare-edge": "edge",
12086
+ d1: "edge",
12087
+ local: "edge",
12088
+ auto: "auto"
12089
+ };
12090
+ function normalizeOptional(value) {
12091
+ const trimmed = value?.trim();
12092
+ return trimmed || void 0;
12093
+ }
12094
+ function normalizeModeString(value) {
12095
+ if (value == null) return void 0;
12096
+ const key = value.trim().toLowerCase();
12097
+ if (!key) return void 0;
12098
+ const mapped = MODE_ALIASES[key];
12099
+ if (!mapped) {
12100
+ throw new AthenaConfigurationError(
12101
+ "ATHENA_NO_SERVICE_CONFIGURED",
12102
+ `Unknown Athena execution mode "${value}". Use gateway | edge | auto (aliases: server, remote, cloudflare, d1).`,
12103
+ "db"
12104
+ );
12105
+ }
12106
+ return mapped;
12107
+ }
12108
+ function isD1Binding(value) {
12109
+ return Boolean(
12110
+ value && typeof value === "object" && typeof value.prepare === "function"
12111
+ );
12112
+ }
12113
+ var GATEWAY_URL_ENV_KEYS2 = [
12114
+ "ATHENA_URL",
12115
+ "NEXT_PUBLIC_ATHENA_URL",
12116
+ "ATHENA_DB_URL",
12117
+ "ATHENA_GATEWAY_URL",
12118
+ "NEXT_PUBLIC_ATHENA_DB_API_URL"
12119
+ ];
12120
+ function resolveGatewayUrl(url, env) {
12121
+ if (normalizeOptional(url)) {
12122
+ return normalizeOptional(url);
12123
+ }
12124
+ for (const key of GATEWAY_URL_ENV_KEYS2) {
12125
+ const value = normalizeOptional(env[key]);
12126
+ if (value) return value;
12127
+ }
12128
+ return void 0;
12129
+ }
12130
+ function resolvePrefer(prefer, env) {
12131
+ const raw = normalizeOptional(typeof prefer === "string" ? prefer : prefer ?? void 0) ?? normalizeOptional(env[ATHENA_EXECUTION_PREFER_ENV_KEY]) ?? "edge";
12132
+ const key = raw.toLowerCase();
12133
+ if (key === "gateway" || key === "server" || key === "remote" || key === "http") {
12134
+ return "gateway";
12135
+ }
12136
+ if (key === "edge" || key === "d1" || key === "cloudflare" || key === "local") {
12137
+ return "edge";
12138
+ }
12139
+ throw new AthenaConfigurationError(
12140
+ "ATHENA_NO_SERVICE_CONFIGURED",
12141
+ `Unknown Athena execution prefer "${raw}". Use edge | gateway.`,
12142
+ "db"
12143
+ );
12144
+ }
12145
+ function resolveAthenaExecutionMode(input = {}) {
12146
+ const env = input.env ?? {};
12147
+ const fromEnv = normalizeModeString(env[ATHENA_EXECUTION_MODE_ENV_KEY]);
12148
+ const requested = normalizeModeString(input.mode) ?? fromEnv ?? "auto";
12149
+ const url = resolveGatewayUrl(input.url, env);
12150
+ const hasD1 = isD1Binding(input.d1);
12151
+ const hasGateway = Boolean(url);
12152
+ if (requested === "gateway") {
12153
+ if (!hasGateway) {
12154
+ throw new AthenaConfigurationError(
12155
+ "ATHENA_NO_SERVICE_CONFIGURED",
12156
+ 'Athena execution mode is "gateway" but no url / ATHENA_URL / ATHENA_DB_URL / ATHENA_GATEWAY_URL was provided.',
12157
+ "db"
12158
+ );
12159
+ }
12160
+ return "gateway";
12161
+ }
12162
+ if (requested === "edge") {
12163
+ if (!hasD1) {
12164
+ throw new AthenaConfigurationError(
12165
+ "ATHENA_NO_SERVICE_CONFIGURED",
12166
+ 'Athena execution mode is "edge" but no D1 binding was provided (db.d1 / config.d1 / env.DB).',
12167
+ "db"
12168
+ );
12169
+ }
12170
+ return "edge";
12171
+ }
12172
+ if (hasD1 && hasGateway) {
12173
+ return resolvePrefer(input.prefer, env);
12174
+ }
12175
+ if (hasD1) return "edge";
12176
+ if (hasGateway) return "gateway";
12177
+ throw new AthenaConfigurationError(
12178
+ "ATHENA_NO_SERVICE_CONFIGURED",
12179
+ 'Cannot resolve Athena execution mode: provide mode "gateway" with url/key, mode "edge" with d1, or mode "auto" with either a D1 binding or a gateway URL (ATHENA_URL / ATHENA_DB_URL / ATHENA_GATEWAY_URL).',
12180
+ "db"
12181
+ );
12182
+ }
12183
+
12184
+ // src/cloudflare/r2/storage.ts
12185
+ function normalizePrefix(prefix) {
12186
+ if (!prefix?.trim()) return "";
12187
+ const normalized = prefix.replace(/^\/+/, "").replace(/\/?$/, "/");
12188
+ if (normalized.includes("\0")) {
12189
+ throw new Error("storage prefix must not contain null bytes");
12190
+ }
12191
+ if (normalized.split("/").some((segment) => segment === "..")) {
12192
+ throw new Error('storage prefix must not contain ".." path segments');
12193
+ }
12194
+ return normalized;
12195
+ }
12196
+ function assertSafeObjectKey(key) {
12197
+ if (typeof key !== "string" || !key.trim()) {
12198
+ throw new Error("Object key is required");
12199
+ }
12200
+ if (key.includes("\0")) {
12201
+ throw new Error("Object key must not contain null bytes");
12202
+ }
12203
+ const cleaned = key.replace(/^\/+/, "");
12204
+ if (!cleaned) {
12205
+ throw new Error("Object key is required");
12206
+ }
12207
+ const segments = cleaned.split("/");
12208
+ if (segments.some((segment) => segment === "..")) {
12209
+ throw new Error('Object key must not contain ".." path segments');
12210
+ }
12211
+ return cleaned;
12212
+ }
12213
+ function joinKey(prefix, key) {
12214
+ return `${prefix}${assertSafeObjectKey(key)}`;
12215
+ }
12216
+ function toLogicalKey(prefix, physicalKey) {
12217
+ if (!prefix) return physicalKey;
12218
+ if (physicalKey.startsWith(prefix)) {
12219
+ return physicalKey.slice(prefix.length);
12220
+ }
12221
+ return physicalKey;
12222
+ }
12223
+ function toPhysicalKey(prefix, key) {
12224
+ return joinKey(prefix, key);
12225
+ }
12226
+ function unsupported(method) {
12227
+ throw new Error(
12228
+ `storage.${method} is not available in Cloudflare edge-local R2 object mode. Only putObject / getObject / deleteObject / listObjects are supported (L3a).`
12229
+ );
12230
+ }
12231
+ function createCloudflareR2StorageModule(options) {
12232
+ const prefix = normalizePrefix(options.prefix);
12233
+ const { r2 } = options;
12234
+ const putObject = async (input) => {
12235
+ const logical = assertSafeObjectKey(input.key);
12236
+ const physical = toPhysicalKey(prefix, logical);
12237
+ await r2.put(physical, input.body, {
12238
+ httpMetadata: input.contentType ? { contentType: input.contentType } : void 0,
12239
+ customMetadata: input.metadata
12240
+ });
12241
+ return { key: logical };
12242
+ };
12243
+ const getObject = async (input) => {
12244
+ const logical = assertSafeObjectKey(input.key);
12245
+ const physical = toPhysicalKey(prefix, logical);
12246
+ const object = await r2.get(physical);
12247
+ if (!object) return null;
12248
+ return {
12249
+ key: toLogicalKey(prefix, object.key),
12250
+ size: object.size,
12251
+ contentType: object.httpMetadata?.contentType,
12252
+ body: object
12253
+ };
12254
+ };
12255
+ const deleteObject = async (input) => {
12256
+ const logicalKeys = (Array.isArray(input.key) ? input.key : [input.key]).map(
12257
+ (key) => assertSafeObjectKey(key)
12258
+ );
12259
+ const physicalKeys = logicalKeys.map((key) => toPhysicalKey(prefix, key));
12260
+ await r2.delete(physicalKeys.length === 1 ? physicalKeys[0] : physicalKeys);
12261
+ return { deleted: logicalKeys };
12262
+ };
12263
+ const listObjects = async (input) => {
12264
+ const relative = input?.prefix?.trim() ? assertSafeObjectKey(input.prefix) : "";
12265
+ const listPrefix = `${prefix}${relative}`;
12266
+ const listed = await r2.list({
12267
+ prefix: listPrefix || void 0,
12268
+ limit: input?.limit,
12269
+ cursor: input?.cursor
12270
+ });
12271
+ return {
12272
+ objects: listed.objects.map((object) => ({
12273
+ key: toLogicalKey(prefix, object.key),
12274
+ size: object.size,
12275
+ etag: object.etag,
12276
+ uploaded: object.uploaded
12277
+ })),
12278
+ truncated: listed.truncated,
12279
+ cursor: listed.cursor
12280
+ };
12281
+ };
12282
+ const base = {
12283
+ putObject,
12284
+ getObject,
12285
+ deleteObject,
12286
+ listObjects
12287
+ };
12288
+ return new Proxy(base, {
12289
+ get(target, property, receiver) {
12290
+ if (property in target) {
12291
+ return Reflect.get(target, property, receiver);
12292
+ }
12293
+ if (typeof property === "string") {
12294
+ return (...args) => {
12295
+ return unsupported(property);
12296
+ };
12297
+ }
12298
+ return void 0;
12299
+ }
12300
+ });
12301
+ }
12302
+
12303
+ // src/billing/module.ts
12304
+ var SDK_NAME5 = "xylex-group/athena-billing";
12305
+ var SDK_HEADER_VALUE4 = buildSdkHeaderValue(SDK_NAME5);
12306
+ var AthenaBillingError = class extends Error {
12307
+ status;
12308
+ endpoint;
12309
+ method;
12310
+ body;
12311
+ constructor(input) {
12312
+ super(input.message);
12313
+ this.name = "AthenaBillingError";
12314
+ this.status = input.status;
12315
+ this.endpoint = input.endpoint;
12316
+ this.method = input.method;
12317
+ this.body = input.body;
12318
+ }
12319
+ };
12320
+ function withPathParam2(path, name, value) {
12321
+ return path.replace(`{${name}}`, encodeURIComponent(value));
12322
+ }
12323
+ function appendQuery3(path, query) {
12324
+ if (!query) return path;
12325
+ const params = new URLSearchParams();
12326
+ for (const [key, value] of Object.entries(query)) {
12327
+ if (value === void 0 || value === null) continue;
12328
+ params.set(key, String(value));
12329
+ }
12330
+ const serialized = params.toString();
12331
+ return serialized ? `${path}?${serialized}` : path;
12332
+ }
12333
+ function connectionQuery(input) {
12334
+ const query = {
12335
+ connectionId: input.connectionId
12336
+ };
12337
+ if (input.clientName) query.clientName = input.clientName;
12338
+ if ("cursor" in input && input.cursor) query.cursor = input.cursor;
12339
+ if ("source" in input && input.source) query.source = input.source;
12340
+ if ("limit" in input && input.limit !== void 0) query.limit = String(input.limit);
12341
+ if ("offset" in input && input.offset !== void 0) query.offset = String(input.offset);
12342
+ return query;
12343
+ }
12344
+ function parseEnvelopeData(body) {
12345
+ if (body && typeof body === "object" && "data" in body) {
12346
+ return body.data;
12347
+ }
12348
+ return body;
12349
+ }
12350
+ function createBillingModule(config) {
12351
+ const baseUrl = normalizeAthenaGatewayBaseUrl(config.baseUrl, {
12352
+ label: "Athena billing base URL"
12353
+ });
12354
+ const fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);
12355
+ async function call(method, path, body, options, responseType = "json") {
12356
+ const headers = buildAthenaRequestHeaders({
12357
+ profile: "gateway",
12358
+ sdkHeaderValue: SDK_HEADER_VALUE4,
12359
+ apiKey: options?.apiKey ?? config.apiKey,
12360
+ client: config.client,
12361
+ configHeaders: {
12362
+ ...config.headers ?? {}
12363
+ },
12364
+ callHeaders: options?.headers,
12365
+ contentType: "application/json"
12366
+ });
12367
+ let requestBody;
12368
+ if (body !== void 0 && body !== null) {
12369
+ if (typeof body === "string" || body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof FormData || body instanceof URLSearchParams) {
12370
+ requestBody = body;
12371
+ } else {
12372
+ requestBody = JSON.stringify(body);
12373
+ if (!hasHeaderIgnoreCase(headers, "Content-Type")) {
12374
+ headers["Content-Type"] = "application/json";
12375
+ }
12376
+ }
12377
+ }
12378
+ const targetUrl = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
12379
+ const response = await fetchImpl(targetUrl, {
12380
+ method,
12381
+ headers,
12382
+ body: requestBody,
12383
+ signal: options?.signal
12384
+ });
12385
+ if (responseType === "text") {
12386
+ const text = await response.text();
12387
+ if (!response.ok) {
12388
+ throw new AthenaBillingError({
12389
+ message: `Billing request failed (${response.status})`,
12390
+ status: response.status,
12391
+ endpoint: path,
12392
+ method,
12393
+ body: text
12394
+ });
12395
+ }
12396
+ return text;
12397
+ }
12398
+ const rawText = await response.text();
12399
+ let parsed = rawText;
12400
+ if (rawText) {
12401
+ try {
12402
+ parsed = JSON.parse(rawText);
12403
+ } catch {
12404
+ parsed = rawText;
12405
+ }
12406
+ } else {
12407
+ parsed = null;
12408
+ }
12409
+ if (!response.ok) {
12410
+ const message = parsed && typeof parsed === "object" && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `Billing request failed (${response.status})`;
12411
+ throw new AthenaBillingError({
12412
+ message,
12413
+ status: response.status,
12414
+ endpoint: path,
12415
+ method,
12416
+ body: parsed
12417
+ });
12418
+ }
12419
+ return parseEnvelopeData(parsed);
12420
+ }
12421
+ return {
12422
+ getCapabilities(input, options) {
12423
+ return call(
12424
+ "GET",
12425
+ appendQuery3("/billing/v1/capabilities", connectionQuery(input)),
12426
+ void 0,
12427
+ options
12428
+ );
12429
+ },
12430
+ createCheckout(body, options) {
12431
+ return call("POST", "/billing/v1/checkouts", body, options);
12432
+ },
12433
+ listProducts(input, options) {
12434
+ return call(
12435
+ "GET",
12436
+ appendQuery3("/billing/v1/products", connectionQuery(input)),
12437
+ void 0,
12438
+ options
12439
+ );
12440
+ },
12441
+ listPrices(input, options) {
12442
+ return call(
12443
+ "GET",
12444
+ appendQuery3("/billing/v1/prices", {
12445
+ ...connectionQuery(input),
12446
+ ...input.productId ? { productId: input.productId } : {}
12447
+ }),
12448
+ void 0,
12449
+ options
12450
+ );
12451
+ },
12452
+ listCustomers(input, options) {
12453
+ return call(
12454
+ "GET",
12455
+ appendQuery3("/billing/v1/customers", connectionQuery(input)),
12456
+ void 0,
12457
+ options
12458
+ );
12459
+ },
12460
+ createCustomer(input, options) {
12461
+ return call(
12462
+ "POST",
12463
+ "/billing/v1/customers",
12464
+ {
12465
+ connectionId: input.connectionId,
12466
+ clientName: input.clientName,
9798
12467
  email: input.email,
9799
12468
  name: input.name,
9800
12469
  metadata: input.metadata ?? {},
@@ -10227,18 +12896,6 @@ function createBillingModule(config) {
10227
12896
  };
10228
12897
  }
10229
12898
 
10230
- // src/config/errors.ts
10231
- var AthenaConfigurationError = class extends Error {
10232
- code;
10233
- service;
10234
- constructor(code, message, service) {
10235
- super(message);
10236
- this.name = "AthenaConfigurationError";
10237
- this.code = code;
10238
- this.service = service;
10239
- }
10240
- };
10241
-
10242
12899
  // src/context/merge.ts
10243
12900
  function mergeAthenaRequestContexts(base, override) {
10244
12901
  if (!base && !override) return void 0;
@@ -10252,6 +12909,82 @@ function mergeAthenaRequestContexts(base, override) {
10252
12909
  };
10253
12910
  }
10254
12911
 
12912
+ // src/diagnostics.ts
12913
+ function readProcessEnv2() {
12914
+ try {
12915
+ return globalThis.process?.env ?? {};
12916
+ } catch {
12917
+ return {};
12918
+ }
12919
+ }
12920
+ function isTruthyEnv(value) {
12921
+ if (!value) return false;
12922
+ const normalized = value.trim().toLowerCase();
12923
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
12924
+ }
12925
+ function isQuietAthenaDiagnosticsEnvironment(env = readProcessEnv2()) {
12926
+ const nodeEnv = env.NODE_ENV?.trim().toLowerCase();
12927
+ if (nodeEnv === "production") {
12928
+ return true;
12929
+ }
12930
+ if (isTruthyEnv(env.OPENNEXT_BUILD)) {
12931
+ return true;
12932
+ }
12933
+ const nextPhase = env.NEXT_PHASE?.trim();
12934
+ if (nextPhase === "phase-production-build") {
12935
+ return true;
12936
+ }
12937
+ if (isTruthyEnv(env.CI) && nodeEnv !== "test") {
12938
+ if (nodeEnv === "production" || isTruthyEnv(env.OPENNEXT_BUILD)) {
12939
+ return true;
12940
+ }
12941
+ }
12942
+ return false;
12943
+ }
12944
+ function resolveBooleanFlag(explicit, mode, quiet) {
12945
+ if (typeof explicit === "boolean") {
12946
+ return explicit;
12947
+ }
12948
+ if (mode === true) {
12949
+ return true;
12950
+ }
12951
+ if (mode === false) {
12952
+ return false;
12953
+ }
12954
+ if (mode === "auto") {
12955
+ return false;
12956
+ }
12957
+ return false;
12958
+ }
12959
+ function resolveAthenaClientDiagnostics(input) {
12960
+ const env = input.env ?? readProcessEnv2();
12961
+ const quiet = isQuietAthenaDiagnosticsEnvironment(env);
12962
+ const mode = input.diagnostics;
12963
+ const effectiveMode = mode === "auto" && quiet ? false : mode;
12964
+ const debugAst = resolveBooleanFlag(input.debugAst, effectiveMode);
12965
+ const findManyAst = resolveBooleanFlag(input.findManyAst, effectiveMode);
12966
+ let traceQueries;
12967
+ if (input.traceQueries !== void 0) {
12968
+ if (typeof input.traceQueries === "boolean") {
12969
+ traceQueries = input.traceQueries;
12970
+ } else if (effectiveMode === false || mode === "auto" && quiet) {
12971
+ const enabled = input.traceQueries.enabled;
12972
+ traceQueries = typeof enabled === "boolean" ? enabled ? input.traceQueries : false : false;
12973
+ } else {
12974
+ traceQueries = input.traceQueries;
12975
+ }
12976
+ } else if (effectiveMode === true) {
12977
+ traceQueries = true;
12978
+ } else {
12979
+ traceQueries = false;
12980
+ }
12981
+ return {
12982
+ debugAst,
12983
+ findManyAst,
12984
+ traceQueries
12985
+ };
12986
+ }
12987
+
10255
12988
  // src/v3-client.ts
10256
12989
  var ENV_URL_KEYS = ["ATHENA_URL", "NEXT_PUBLIC_ATHENA_URL"];
10257
12990
  var ENV_DB_URL_KEYS = ["ATHENA_DB_URL", "ATHENA_GATEWAY_URL", "NEXT_PUBLIC_ATHENA_DB_API_URL"];
@@ -10260,7 +12993,13 @@ var ENV_CHAT_URL_KEYS = ["ATHENA_CHAT_URL", "NEXT_PUBLIC_ATHENA_CHAT_URL"];
10260
12993
  var ENV_CHAT_WS_URL_KEYS = ["ATHENA_CHAT_WS_URL", "NEXT_PUBLIC_ATHENA_CHAT_WS_URL"];
10261
12994
  var ENV_STORAGE_URL_KEYS = ["ATHENA_STORAGE_URL", "NEXT_PUBLIC_ATHENA_STORAGE_URL"];
10262
12995
  var ENV_KEY_KEYS = ["ATHENA_API_KEY", "NEXT_PUBLIC_ATHENA_API_KEY", "ATHENA_GATEWAY_API_KEY", "X_API_KEY"];
10263
- var ENV_CLIENT_KEYS = ["ATHENA_CLIENT", "NEXT_PUBLIC_ATHENA_CLIENT"];
12996
+ var ENV_CLIENT_KEYS = [
12997
+ "ATHENA_CLIENT",
12998
+ "ATHENA_GATEWAY_CLIENT",
12999
+ "ATHENA_GENERATOR_CLIENT",
13000
+ "NEXT_PUBLIC_ATHENA_CLIENT",
13001
+ "NEXT_PUBLIC_ATHENA_GATEWAY_CLIENT"
13002
+ ];
10264
13003
  var MISSING_DB_SENTINEL = "https://athena.invalid/db";
10265
13004
  function readFirstEnv(env, keys) {
10266
13005
  for (const key of keys) {
@@ -10269,14 +13008,30 @@ function readFirstEnv(env, keys) {
10269
13008
  }
10270
13009
  return void 0;
10271
13010
  }
10272
- function normalizeOptional(value) {
13011
+ function readFirstEnvHttpUrl(env, keys) {
13012
+ for (const key of keys) {
13013
+ const value = env?.[key]?.trim();
13014
+ if (value && isAbsoluteHttpUrl(value)) return value;
13015
+ }
13016
+ return void 0;
13017
+ }
13018
+ function normalizeOptional2(value) {
10273
13019
  const normalized = value?.trim();
10274
13020
  return normalized || void 0;
10275
13021
  }
13022
+ function isAbsoluteHttpUrl(value) {
13023
+ try {
13024
+ const url = new URL(value);
13025
+ return url.protocol === "http:" || url.protocol === "https:";
13026
+ } catch {
13027
+ return false;
13028
+ }
13029
+ }
10276
13030
  function appendPath(baseUrl, path) {
10277
13031
  return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
10278
13032
  }
10279
13033
  function toWebSocketUrl(baseUrl) {
13034
+ if (!isAbsoluteHttpUrl(baseUrl)) return void 0;
10280
13035
  const url = new URL(baseUrl);
10281
13036
  url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
10282
13037
  url.pathname = `${url.pathname.replace(/\/+$/, "")}/wss/gateway`;
@@ -10286,11 +13041,11 @@ function toWebSocketUrl(baseUrl) {
10286
13041
  }
10287
13042
  function resolveCore(config) {
10288
13043
  const env = config.env;
10289
- const explicitRoot = normalizeOptional(config.url);
10290
- const envRoot = readFirstEnv(env, ENV_URL_KEYS);
10291
- const root = explicitRoot ?? envRoot;
10292
- const explicitRootWinsOverEnvServices = explicitRoot !== void 0;
10293
- const resolveService = (explicit, envKeys, path) => normalizeOptional(explicit) ?? (explicitRootWinsOverEnvServices && root ? appendPath(root, path) : void 0) ?? readFirstEnv(env, envKeys) ?? (root ? appendPath(root, path) : void 0);
13044
+ const explicitRoot = normalizeOptional2(config.url);
13045
+ const envRoot = readFirstEnvHttpUrl(env, ENV_URL_KEYS);
13046
+ const root = explicitRoot && isAbsoluteHttpUrl(explicitRoot) ? explicitRoot : explicitRoot ? void 0 : envRoot;
13047
+ const explicitRootWinsOverEnvServices = Boolean(root && explicitRoot && isAbsoluteHttpUrl(explicitRoot));
13048
+ const resolveService = (explicit, envKeys, path) => normalizeOptional2(explicit) ?? (explicitRootWinsOverEnvServices && root ? appendPath(root, path) : void 0) ?? readFirstEnvHttpUrl(env, envKeys) ?? (root ? appendPath(root, path) : void 0);
10294
13049
  const dbUrl = resolveService(config.db?.url, ENV_DB_URL_KEYS, "db");
10295
13050
  const urls = {
10296
13051
  db: dbUrl,
@@ -10298,8 +13053,8 @@ function resolveCore(config) {
10298
13053
  chat: resolveService(config.chat?.url, ENV_CHAT_URL_KEYS, "chat"),
10299
13054
  storage: resolveService(config.storage?.url, ENV_STORAGE_URL_KEYS, "storage"),
10300
13055
  // Billing lives on the main Athena HTTP surface (same host as gateway/db).
10301
- billing: normalizeOptional(config.billing?.url) ?? dbUrl ?? root ?? void 0,
10302
- chatWs: normalizeOptional(config.chat?.wsUrl) ?? (explicitRootWinsOverEnvServices && root ? toWebSocketUrl(root) : void 0) ?? readFirstEnv(env, ENV_CHAT_WS_URL_KEYS) ?? (root ? toWebSocketUrl(root) : void 0)
13056
+ billing: normalizeOptional2(config.billing?.url) ?? dbUrl ?? root ?? void 0,
13057
+ chatWs: normalizeOptional2(config.chat?.wsUrl) ?? (explicitRootWinsOverEnvServices && root ? toWebSocketUrl(root) : void 0) ?? readFirstEnvHttpUrl(env, ENV_CHAT_WS_URL_KEYS) ?? (root ? toWebSocketUrl(root) : void 0)
10303
13058
  };
10304
13059
  if (!urls.db && !urls.auth && !urls.chat && !urls.storage && !urls.billing) {
10305
13060
  throw new AthenaConfigurationError(
@@ -10308,7 +13063,7 @@ function resolveCore(config) {
10308
13063
  "db"
10309
13064
  );
10310
13065
  }
10311
- const key = normalizeOptional(config.key) ?? readFirstEnv(env, ENV_KEY_KEYS);
13066
+ const key = normalizeOptional2(config.key) ?? readFirstEnv(env, ENV_KEY_KEYS);
10312
13067
  if (!key) {
10313
13068
  throw new AthenaConfigurationError(
10314
13069
  "ATHENA_API_KEY_REQUIRED",
@@ -10319,7 +13074,7 @@ function resolveCore(config) {
10319
13074
  config,
10320
13075
  urls,
10321
13076
  key,
10322
- client: normalizeOptional(config.client) ?? readFirstEnv(env, ENV_CLIENT_KEYS)
13077
+ client: normalizeOptional2(config.client) ?? readFirstEnv(env, ENV_CLIENT_KEYS)
10323
13078
  };
10324
13079
  return {
10325
13080
  ...base,
@@ -10334,7 +13089,20 @@ async function resolveConfiguredContext(core, viewContext) {
10334
13089
  function createInternalConfig(core) {
10335
13090
  const { config, urls } = core;
10336
13091
  const { url: _authUrl, ...authOptions } = config.auth ?? {};
10337
- const { url: _storageUrl, directUpload, ...storageOptions } = config.storage ?? {};
13092
+ const {
13093
+ url: _storageUrl,
13094
+ directUpload,
13095
+ r2: _r2,
13096
+ prefix: _r2Prefix,
13097
+ ...storageOptions
13098
+ } = config.storage ?? {};
13099
+ const diagnostics = resolveAthenaClientDiagnostics({
13100
+ diagnostics: config.diagnostics,
13101
+ debugAst: config.debugAst,
13102
+ findManyAst: config.findManyAst,
13103
+ traceQueries: config.traceQueries,
13104
+ env: config.env
13105
+ });
10338
13106
  return {
10339
13107
  baseUrl: urls.db ?? MISSING_DB_SENTINEL,
10340
13108
  apiKey: core.key,
@@ -10351,14 +13119,15 @@ function createInternalConfig(core) {
10351
13119
  models: config.models,
10352
13120
  behavior: {
10353
13121
  retryReads: config.retryReads,
10354
- traceQueries: config.traceQueries,
10355
- debugAst: config.debugAst,
10356
- findManyAst: config.findManyAst
13122
+ traceQueries: diagnostics.traceQueries,
13123
+ debugAst: diagnostics.debugAst,
13124
+ findManyAst: diagnostics.findManyAst
10357
13125
  },
10358
13126
  storage: {
10359
13127
  ...storageOptions,
10360
13128
  ...directUpload ? { directUpload } : {}
10361
- }
13129
+ },
13130
+ gatewayTransport: config.gatewayTransport
10362
13131
  };
10363
13132
  }
10364
13133
  function serviceGuard(urls, service) {
@@ -10381,6 +13150,232 @@ function createUnavailableNamespace(service, urls, path = []) {
10381
13150
  }
10382
13151
  });
10383
13152
  }
13153
+ function isD1Binding2(value) {
13154
+ return Boolean(
13155
+ value && typeof value === "object" && typeof value.prepare === "function"
13156
+ );
13157
+ }
13158
+ function isR2Binding(value) {
13159
+ return Boolean(
13160
+ value && typeof value === "object" && typeof value.put === "function" && typeof value.get === "function"
13161
+ );
13162
+ }
13163
+ function foldBindingAliases(config) {
13164
+ const d1 = config.db?.d1 ?? config.d1;
13165
+ const r2 = config.storage?.r2 ?? config.r2;
13166
+ const sessionMode = config.db?.sessionMode ?? config.sessionMode;
13167
+ const prefix = config.storage?.prefix ?? config.storagePrefix;
13168
+ let next = { ...config };
13169
+ if (d1 !== void 0 || sessionMode !== void 0) {
13170
+ next = {
13171
+ ...next,
13172
+ db: {
13173
+ ...next.db,
13174
+ ...d1 !== void 0 ? { d1 } : {},
13175
+ ...sessionMode !== void 0 ? { sessionMode } : {}
13176
+ }
13177
+ };
13178
+ }
13179
+ if (r2 !== void 0 || prefix !== void 0) {
13180
+ next = {
13181
+ ...next,
13182
+ storage: {
13183
+ ...next.storage,
13184
+ ...r2 !== void 0 ? { r2 } : {},
13185
+ ...prefix !== void 0 ? { prefix } : {}
13186
+ }
13187
+ };
13188
+ }
13189
+ const {
13190
+ d1: _d1,
13191
+ r2: _r2,
13192
+ storagePrefix: _storagePrefix,
13193
+ sessionMode: _sessionMode,
13194
+ ...rest
13195
+ } = next;
13196
+ return rest;
13197
+ }
13198
+ function applyExecutionMode(config) {
13199
+ const d1 = config.db?.d1;
13200
+ const hasD1 = isD1Binding2(d1);
13201
+ const hasUrl = Boolean(
13202
+ normalizeOptional2(config.url) ?? normalizeOptional2(config.db?.url) ?? (config.env ? normalizeOptional2(config.env.ATHENA_URL) ?? normalizeOptional2(config.env.NEXT_PUBLIC_ATHENA_URL) : void 0)
13203
+ );
13204
+ const hasModeHint = config.mode != null || config.prefer != null || Boolean(config.env?.ATHENA_EXECUTION_MODE) || Boolean(config.env?.ATHENA_EXECUTION_PREFER);
13205
+ if (!hasD1 && !hasModeHint) {
13206
+ return config;
13207
+ }
13208
+ if (hasD1 && !hasUrl && !hasModeHint) {
13209
+ return config;
13210
+ }
13211
+ let resolved;
13212
+ try {
13213
+ resolved = resolveAthenaExecutionMode({
13214
+ mode: config.mode,
13215
+ prefer: config.prefer,
13216
+ d1: hasD1 ? d1 : null,
13217
+ url: config.url ?? config.db?.url,
13218
+ env: config.env
13219
+ });
13220
+ } catch (error) {
13221
+ if (!hasModeHint) return config;
13222
+ throw error;
13223
+ }
13224
+ if (resolved === "gateway" && hasD1) {
13225
+ const { d1: _drop, sessionMode: _sm, ...dbRest } = config.db ?? {};
13226
+ return {
13227
+ ...config,
13228
+ db: Object.keys(dbRest).length > 0 ? dbRest : void 0,
13229
+ gatewayTransport: void 0
13230
+ };
13231
+ }
13232
+ return config;
13233
+ }
13234
+ function resolveUnifiedRemoteRoot(config) {
13235
+ return normalizeOptional2(config.url) ?? readFirstEnv(config.env, ENV_URL_KEYS);
13236
+ }
13237
+ function isEdgeLocalSentinelUrl(url) {
13238
+ if (!url) return false;
13239
+ return url === CLOUDFLARE_EDGE_BASE_URL || url.startsWith("https://athena.local/") || url.startsWith("http://athena.local/");
13240
+ }
13241
+ function hasRemoteDbGatewayUrl(config) {
13242
+ const dbUrl = normalizeOptional2(config.db?.url) ?? readFirstEnv(config.env, ENV_DB_URL_KEYS);
13243
+ return Boolean(dbUrl && !isEdgeLocalSentinelUrl(dbUrl));
13244
+ }
13245
+ function hasRemoteHttpServices(config) {
13246
+ return Boolean(
13247
+ resolveUnifiedRemoteRoot(config) || hasRemoteDbGatewayUrl(config) || normalizeOptional2(config.auth?.url) || readFirstEnv(config.env, ENV_AUTH_URL_KEYS) || normalizeOptional2(config.storage?.url) || readFirstEnv(config.env, ENV_STORAGE_URL_KEYS) || normalizeOptional2(config.chat?.url) || readFirstEnv(config.env, ENV_CHAT_URL_KEYS) || normalizeOptional2(config.billing?.url)
13248
+ );
13249
+ }
13250
+ function hasRemoteHttpStorage(config) {
13251
+ return Boolean(
13252
+ normalizeOptional2(config.storage?.url) || readFirstEnv(config.env, ENV_STORAGE_URL_KEYS) || resolveUnifiedRemoteRoot(config)
13253
+ );
13254
+ }
13255
+ function hasRemoteAuthService(config) {
13256
+ return Boolean(
13257
+ normalizeOptional2(config.auth?.url) || readFirstEnv(config.env, ENV_AUTH_URL_KEYS) || resolveUnifiedRemoteRoot(config)
13258
+ );
13259
+ }
13260
+ function materializeEdgeBindings(config) {
13261
+ const d1 = config.db?.d1;
13262
+ const r2 = config.storage?.r2;
13263
+ const hasD1 = isD1Binding2(d1);
13264
+ const hasR2 = isR2Binding(r2);
13265
+ if (!hasD1 && !hasR2) {
13266
+ return config;
13267
+ }
13268
+ if (hasD1 && d1 && typeof d1.prepare !== "function") {
13269
+ throw new AthenaConfigurationError(
13270
+ "ATHENA_NO_SERVICE_CONFIGURED",
13271
+ "db.d1 must be a D1 binding with prepare().",
13272
+ "db"
13273
+ );
13274
+ }
13275
+ const remoteRoot = resolveUnifiedRemoteRoot(config);
13276
+ const remoteServices = hasRemoteHttpServices(config);
13277
+ const remoteStorage = hasRemoteHttpStorage(config);
13278
+ const remoteAuth = hasRemoteAuthService(config);
13279
+ const next = { ...config };
13280
+ if (hasD1 && d1) {
13281
+ if (!config.gatewayTransport) {
13282
+ next.gatewayTransport = createCloudflareD1GatewayTransport({
13283
+ d1,
13284
+ defaultSessionMode: config.db?.sessionMode
13285
+ });
13286
+ }
13287
+ const explicitDbUrl = normalizeOptional2(config.db?.url);
13288
+ const remoteDbGateway = hasRemoteDbGatewayUrl(config);
13289
+ next.db = {
13290
+ ...config.db,
13291
+ d1,
13292
+ url: explicitDbUrl ?? (remoteDbGateway ? void 0 : CLOUDFLARE_EDGE_BASE_URL)
13293
+ };
13294
+ const explicitKey = normalizeOptional2(config.key);
13295
+ if (explicitKey) {
13296
+ next.key = explicitKey;
13297
+ } else if (!remoteServices) {
13298
+ next.key = CLOUDFLARE_EDGE_API_KEY;
13299
+ } else {
13300
+ next.key = void 0;
13301
+ }
13302
+ if (remoteRoot) {
13303
+ next.billing = {
13304
+ ...config.billing ?? {},
13305
+ url: normalizeOptional2(config.billing?.url) ?? remoteRoot
13306
+ };
13307
+ }
13308
+ if (!config.capabilities) {
13309
+ next.capabilities = createCloudflareEdgeCapabilities({
13310
+ hasR2,
13311
+ // Explicit storage.url / env storage URL / unified remote root all count.
13312
+ hasRemoteStorage: remoteStorage,
13313
+ authRemote: remoteAuth,
13314
+ findManyAst: false
13315
+ });
13316
+ }
13317
+ } else if (hasR2 && r2) {
13318
+ if (!remoteRoot && !normalizeOptional2(config.db?.url) && !normalizeOptional2(config.storage?.url) && !readFirstEnv(config.env, ENV_STORAGE_URL_KEYS)) {
13319
+ next.storage = {
13320
+ ...config.storage,
13321
+ r2,
13322
+ // Local sentinel so resolveCore accepts a storage-only binding client.
13323
+ url: CLOUDFLARE_EDGE_BASE_URL
13324
+ };
13325
+ if (!remoteServices) {
13326
+ next.key = normalizeOptional2(config.key) ?? CLOUDFLARE_EDGE_API_KEY;
13327
+ } else if (normalizeOptional2(config.key)) {
13328
+ next.key = normalizeOptional2(config.key);
13329
+ } else {
13330
+ next.key = void 0;
13331
+ }
13332
+ }
13333
+ if (!config.capabilities) {
13334
+ if (remoteRoot || normalizeOptional2(config.db?.url) || readFirstEnv(config.env, ENV_DB_URL_KEYS)) {
13335
+ const base = createGatewayCapabilities({
13336
+ authRemote: remoteAuth,
13337
+ storageConfigured: true
13338
+ });
13339
+ next.capabilities = {
13340
+ ...base,
13341
+ storage: {
13342
+ ...base.storage,
13343
+ local: true,
13344
+ objects: true
13345
+ }
13346
+ };
13347
+ } else {
13348
+ next.capabilities = {
13349
+ mode: "cloudflare-edge",
13350
+ db: {
13351
+ engine: "unknown",
13352
+ local: false,
13353
+ layers: {
13354
+ query: false,
13355
+ flatCrud: false,
13356
+ findManyAst: false,
13357
+ rpc: false,
13358
+ relations: false
13359
+ }
13360
+ },
13361
+ storage: {
13362
+ local: true,
13363
+ objects: true,
13364
+ catalogs: false,
13365
+ backups: false
13366
+ },
13367
+ auth: {
13368
+ remote: remoteAuth
13369
+ }
13370
+ };
13371
+ }
13372
+ }
13373
+ }
13374
+ return next;
13375
+ }
13376
+ function normalizeCreateClientConfig(config) {
13377
+ return materializeEdgeBindings(applyExecutionMode(foldBindingAliases(config)));
13378
+ }
10384
13379
  function createClientView(core, viewContext) {
10385
13380
  const resolved = createInternalClientView(
10386
13381
  core.internalCore,
@@ -10398,12 +13393,23 @@ function createClientView(core, viewContext) {
10398
13393
  },
10399
13394
  ...billingOptions
10400
13395
  }) : createUnavailableNamespace("billing", core.urls);
13396
+ const capabilities = core.config.capabilities ?? createGatewayCapabilities({
13397
+ authRemote: Boolean(core.urls.auth),
13398
+ // Match unavailable storage proxy when no storage URL was resolved.
13399
+ storageConfigured: Boolean(core.urls.storage)
13400
+ });
13401
+ const r2 = core.config.storage?.r2;
13402
+ const storageModule = isR2Binding(r2) ? createCloudflareR2StorageModule({
13403
+ r2,
13404
+ prefix: core.config.storage?.prefix ?? void 0
13405
+ }) : core.urls.storage ? resolved.storage : createUnavailableNamespace("storage", core.urls);
10401
13406
  const client = {
10402
13407
  db: core.urls.db ? resolved.db : createUnavailableNamespace("db", core.urls),
10403
13408
  auth: core.urls.auth ? resolved.auth : createUnavailableNamespace("auth", core.urls),
10404
13409
  chat: core.urls.chat ? resolved.chat : createUnavailableNamespace("chat", core.urls),
10405
- storage: core.urls.storage ? resolved.storage : createUnavailableNamespace("storage", core.urls),
13410
+ storage: storageModule,
10406
13411
  billing: billingModule,
13412
+ capabilities,
10407
13413
  from: ((...args) => {
10408
13414
  requireDb();
10409
13415
  return Reflect.apply(resolved.from, resolved, args);
@@ -10427,13 +13433,34 @@ function createClientView(core, viewContext) {
10427
13433
  return resolved.verifyConnection(options);
10428
13434
  },
10429
13435
  withContext(context) {
13436
+ warnIfEmptyRequestContext(context);
10430
13437
  return createClientView(core, mergeAthenaRequestContexts(viewContext, context));
10431
13438
  }
10432
13439
  };
10433
13440
  return Object.freeze(client);
10434
13441
  }
13442
+ function isEmptyAthenaRequestContext(context) {
13443
+ if (!context) return true;
13444
+ const hasHeaders = context.headers != null && Object.keys(context.headers).length > 0;
13445
+ return context.userId == null && context.organizationId == null && !normalizeOptionalContextString(context.cookie) && !normalizeOptionalContextString(context.bearerToken) && !normalizeOptionalContextString(context.sessionToken) && !context.forceNoCache && !hasHeaders;
13446
+ }
13447
+ function normalizeOptionalContextString(value) {
13448
+ const trimmed = value?.trim();
13449
+ return trimmed || void 0;
13450
+ }
13451
+ function warnIfEmptyRequestContext(context) {
13452
+ if (!isEmptyAthenaRequestContext(context)) return;
13453
+ const nodeEnv = globalThis.process?.env?.NODE_ENV;
13454
+ if (nodeEnv === "production") {
13455
+ return;
13456
+ }
13457
+ console.warn(
13458
+ "[athena] withContext({}) has no userId, organizationId, cookie, bearerToken, sessionToken, headers, or forceNoCache. Gateway scope headers will not change. Pass identity fields, or use createAthenaServerClient({ session, scope })."
13459
+ );
13460
+ }
10435
13461
  function createClient(config) {
10436
- return createClientView(resolveCore(config));
13462
+ const normalized = normalizeCreateClientConfig(config);
13463
+ return createClientView(resolveCore(normalized));
10437
13464
  }
10438
13465
 
10439
13466
  // src/generator/schema-discovery.ts
@@ -10532,6 +13559,8 @@ async function discoverGatewaySchemas(config) {
10532
13559
  const client = createClient({
10533
13560
  db: { url: config.gatewayUrl },
10534
13561
  key: config.apiKey,
13562
+ client: config.client,
13563
+ env: typeof process !== "undefined" ? process.env : void 0,
10535
13564
  backend: {
10536
13565
  type: config.backend ?? "postgresql"
10537
13566
  }
@@ -10618,6 +13647,7 @@ function buildGatewayProviderBlock(schemas) {
10618
13647
  mode: "gateway",
10619
13648
  gatewayUrl: generatorEnv("ATHENA_URL"),
10620
13649
  apiKey: generatorEnv("ATHENA_API_KEY"),
13650
+ client: generatorEnv("ATHENA_CLIENT", { optional: true }),
10621
13651
  database: generatorEnv("ATHENA_GENERATOR_DB", { default: "postgres" }),
10622
13652
  schemas: ${formatStringArray(schemas, " ")},
10623
13653
  }`;
@@ -12932,8 +15962,14 @@ var AthenaGatewayPostgresIntrospectionProvider = class {
12932
15962
  constructor(config) {
12933
15963
  this.config = config;
12934
15964
  this.client = createClient({
15965
+ url: this.config.gatewayUrl,
12935
15966
  db: { url: this.config.gatewayUrl },
12936
15967
  key: this.config.apiKey,
15968
+ // Multi-tenant gateways reject DEFAULT_CLIENT; prefer explicit config.
15969
+ // Also pass process.env so ATHENA_CLIENT / ATHENA_GATEWAY_CLIENT still resolve
15970
+ // when the field was not normalized into provider config.
15971
+ client: this.config.client,
15972
+ env: typeof process !== "undefined" ? process.env : void 0,
12937
15973
  backend: {
12938
15974
  type: this.config.backend ?? "postgresql"
12939
15975
  }
@@ -13165,6 +16201,12 @@ async function runSchemaGenerator(options = {}) {
13165
16201
  }
13166
16202
 
13167
16203
  // src/cli/index.ts
16204
+ function setCliExitCode(code) {
16205
+ const proc = globalThis.process;
16206
+ if (proc) {
16207
+ proc.exitCode = code;
16208
+ }
16209
+ }
13168
16210
  function isDebugEnabled() {
13169
16211
  const value = globalThis.process?.env?.ATHENA_JS_DEBUG;
13170
16212
  return value === "1" || value === "true";
@@ -13636,7 +16678,7 @@ async function runCLI(argv, runtime = {}) {
13636
16678
  parsed = parseCommand(argv);
13637
16679
  } catch (error) {
13638
16680
  logCliError(formatGeneratorError(error), errorLog);
13639
- process.exitCode = 1;
16681
+ setCliExitCode(1);
13640
16682
  return;
13641
16683
  }
13642
16684
  if (parsed.command === "help") {
@@ -13674,7 +16716,7 @@ async function runCLI(argv, runtime = {}) {
13674
16716
  } catch (error) {
13675
16717
  const formatted = formatGeneratorError(error, parsed.configPath);
13676
16718
  logCliError(formatted, errorLog);
13677
- process.exitCode = 1;
16719
+ setCliExitCode(1);
13678
16720
  }
13679
16721
  return;
13680
16722
  }
@@ -13694,7 +16736,7 @@ async function runCLI(argv, runtime = {}) {
13694
16736
  } catch (error) {
13695
16737
  const formatted = formatGeneratorError(error, parsed.configPath);
13696
16738
  logCliError(formatted, errorLog);
13697
- process.exitCode = 1;
16739
+ setCliExitCode(1);
13698
16740
  return;
13699
16741
  }
13700
16742
  if (parsed.dryRun) {