@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
@@ -1619,6 +1619,8 @@ function buildUpdateDebugSql(payload) {
1619
1619
  sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
1620
1620
  }
1621
1621
  const pagination = resolvePagination({
1622
+ limit: payload.limit,
1623
+ offset: payload.offset,
1622
1624
  currentPage: payload.current_page,
1623
1625
  pageSize: payload.page_size
1624
1626
  });
@@ -1641,6 +1643,8 @@ function buildDeleteDebugSql(payload) {
1641
1643
  sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
1642
1644
  }
1643
1645
  const pagination = resolvePagination({
1646
+ limit: payload.limit,
1647
+ offset: payload.offset,
1644
1648
  currentPage: payload.current_page,
1645
1649
  pageSize: payload.page_size
1646
1650
  });
@@ -1784,7 +1788,7 @@ function buildAthenaGatewayUrl(baseUrl, path) {
1784
1788
 
1785
1789
  // package.json
1786
1790
  var package_default = {
1787
- version: "3.1.0"
1791
+ version: "3.5.1"
1788
1792
  };
1789
1793
 
1790
1794
  // src/sdk-version.ts
@@ -3870,6 +3874,14 @@ function createAuthModule(config = {}, runtimeOptions = {}) {
3870
3874
  changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
3871
3875
  deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
3872
3876
  changePassword: (input, options) => postGeneric("/change-password", input, options),
3877
+ // Better Auth UI flat method aliases (also nested under session/account/social/user).
3878
+ listSessions: (input, options) => getGeneric("/list-sessions", input, options),
3879
+ revokeSession: sessionRevokeBinding,
3880
+ revokeOtherSessions,
3881
+ listAccounts: (input, options) => getGeneric("/list-accounts", input, options),
3882
+ unlinkAccount: (input, options) => postGeneric("/unlink-account", input, options),
3883
+ linkSocial: (input, options) => postGeneric("/link-social", input, options),
3884
+ updateUser: (input, options) => postGeneric("/update-user", input, options),
3873
3885
  user: {
3874
3886
  update: (input, options) => postGeneric("/update-user", input, options),
3875
3887
  delete: (input, options) => postGeneric("/delete-user", input, options),
@@ -4975,9 +4987,9 @@ function readHeadersField(value) {
4975
4987
  const headers = value.headers;
4976
4988
  if (!isRecord8(headers)) return {};
4977
4989
  const result = {};
4978
- for (const [key, headerValue2] of Object.entries(headers)) {
4979
- if (typeof headerValue2 === "string") {
4980
- result[key] = headerValue2;
4990
+ for (const [key, headerValue3] of Object.entries(headers)) {
4991
+ if (typeof headerValue3 === "string") {
4992
+ result[key] = headerValue3;
4981
4993
  }
4982
4994
  }
4983
4995
  return result;
@@ -8602,6 +8614,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, beha
8602
8614
  strip_nulls: mergedOptions?.stripNulls ?? true
8603
8615
  };
8604
8616
  if (executionState.order) payload.sort_by = executionState.order;
8617
+ if (executionState.limit !== void 0) payload.limit = executionState.limit;
8618
+ if (executionState.offset !== void 0) payload.offset = executionState.offset;
8605
8619
  if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
8606
8620
  if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
8607
8621
  if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
@@ -8656,6 +8670,8 @@ function createTableBuilder(tableName, client, formatGatewayResult, tracer, beha
8656
8670
  conditions: filters
8657
8671
  };
8658
8672
  if (executionState.order) payload.sort_by = executionState.order;
8673
+ if (executionState.limit !== void 0) payload.limit = executionState.limit;
8674
+ if (executionState.offset !== void 0) payload.offset = executionState.offset;
8659
8675
  if (executionState.currentPage !== void 0) payload.current_page = executionState.currentPage;
8660
8676
  if (executionState.pageSize !== void 0) payload.page_size = executionState.pageSize;
8661
8677
  if (executionState.totalPages !== void 0) payload.total_pages = executionState.totalPages;
@@ -8707,7 +8723,11 @@ function createQueryBuilder(client, formatGatewayResult, behavior, tracer) {
8707
8723
  if (!normalizedQuery) {
8708
8724
  throw new Error("query requires a non-empty string");
8709
8725
  }
8710
- const payload = { query: normalizedQuery };
8726
+ const params = options?.params;
8727
+ const payload = {
8728
+ query: normalizedQuery,
8729
+ ...Array.isArray(params) ? { params } : {}
8730
+ };
8711
8731
  const callsite = captureTraceCallsite(tracer);
8712
8732
  return executeRead(
8713
8733
  behavior,
@@ -8756,7 +8776,7 @@ function normalizeAuthClientConfig(auth, defaultBaseUrl) {
8756
8776
  }
8757
8777
  function createInternalClientCore(config) {
8758
8778
  const normalizedAuthConfig = normalizeAuthClientConfig(config.auth, config.authUrl);
8759
- const gatewayTransport = createAthenaGatewayClient({
8779
+ const gatewayTransport = config.gatewayTransport ?? createAthenaGatewayClient({
8760
8780
  baseUrl: config.baseUrl,
8761
8781
  apiKey: config.apiKey,
8762
8782
  client: config.client ?? void 0,
@@ -8911,178 +8931,2816 @@ function createInternalClientView(core, resolveContext) {
8911
8931
  };
8912
8932
  }
8913
8933
 
8914
- // src/billing/module.ts
8915
- var SDK_NAME5 = "xylex-group/athena-billing";
8916
- var SDK_HEADER_VALUE4 = buildSdkHeaderValue(SDK_NAME5);
8917
- var AthenaBillingError = class extends Error {
8918
- status;
8919
- endpoint;
8920
- method;
8921
- body;
8922
- constructor(input) {
8923
- super(input.message);
8924
- this.name = "AthenaBillingError";
8925
- this.status = input.status;
8926
- this.endpoint = input.endpoint;
8927
- this.method = input.method;
8928
- this.body = input.body;
8929
- }
8930
- };
8931
- function withPathParam2(path, name, value) {
8932
- return path.replace(`{${name}}`, encodeURIComponent(value));
8933
- }
8934
- function appendQuery3(path, query) {
8935
- if (!query) return path;
8936
- const params = new URLSearchParams();
8937
- for (const [key, value] of Object.entries(query)) {
8938
- if (value === void 0 || value === null) continue;
8939
- params.set(key, String(value));
8940
- }
8941
- const serialized = params.toString();
8942
- return serialized ? `${path}?${serialized}` : path;
8934
+ // src/cloudflare/types.ts
8935
+ var CLOUDFLARE_EDGE_BASE_URL = "https://athena.local/cloudflare-edge";
8936
+ var CLOUDFLARE_EDGE_API_KEY = "cloudflare-edge-local";
8937
+
8938
+ // src/cloudflare/capabilities.ts
8939
+ function createGatewayCapabilities(options) {
8940
+ const storageConfigured = options?.storageConfigured ?? true;
8941
+ return {
8942
+ mode: "gateway",
8943
+ db: {
8944
+ engine: options?.engine ?? "postgresql",
8945
+ local: false,
8946
+ layers: {
8947
+ query: true,
8948
+ flatCrud: true,
8949
+ findManyAst: true,
8950
+ rpc: true,
8951
+ relations: true
8952
+ }
8953
+ },
8954
+ storage: {
8955
+ local: false,
8956
+ objects: storageConfigured,
8957
+ catalogs: storageConfigured ? options?.storageCatalogs ?? true : false,
8958
+ backups: storageConfigured ? options?.storageBackups ?? true : false
8959
+ },
8960
+ auth: {
8961
+ remote: options?.authRemote ?? true
8962
+ }
8963
+ };
8943
8964
  }
8944
- function connectionQuery(input) {
8945
- const query = {
8946
- connectionId: input.connectionId
8965
+ function createCloudflareEdgeCapabilities(options) {
8966
+ const hasObjects = options.hasR2 || Boolean(options.hasRemoteStorage);
8967
+ return {
8968
+ mode: "cloudflare-edge",
8969
+ db: {
8970
+ engine: "cloudflare-d1",
8971
+ local: true,
8972
+ layers: {
8973
+ query: true,
8974
+ flatCrud: true,
8975
+ findManyAst: options.findManyAst ?? false,
8976
+ rpc: false,
8977
+ relations: false
8978
+ }
8979
+ },
8980
+ storage: {
8981
+ // Local objects only when an R2 binding is present.
8982
+ local: options.hasR2,
8983
+ // Remote hybrid root can still expose storage.objects via the HTTP API.
8984
+ objects: hasObjects,
8985
+ catalogs: false,
8986
+ backups: false
8987
+ },
8988
+ auth: {
8989
+ remote: options.authRemote
8990
+ }
8947
8991
  };
8948
- if (input.clientName) query.clientName = input.clientName;
8949
- if ("cursor" in input && input.cursor) query.cursor = input.cursor;
8950
- if ("source" in input && input.source) query.source = input.source;
8951
- if ("limit" in input && input.limit !== void 0) query.limit = String(input.limit);
8952
- if ("offset" in input && input.offset !== void 0) query.offset = String(input.offset);
8953
- return query;
8954
8992
  }
8955
- function parseEnvelopeData(body) {
8956
- if (body && typeof body === "object" && "data" in body) {
8957
- return body.data;
8993
+
8994
+ // src/cloudflare/d1/runner.ts
8995
+ function resultColumns(rows) {
8996
+ const first = rows.find((value) => value && typeof value === "object" && !Array.isArray(value));
8997
+ if (!first) return [];
8998
+ return Object.keys(first);
8999
+ }
9000
+ function isIdentChar(ch) {
9001
+ if (!ch) return false;
9002
+ return /[A-Za-z0-9_]/.test(ch);
9003
+ }
9004
+ function scanSqlKeywordsOutsideLiterals(sql, onKeyword) {
9005
+ let inSingle = false;
9006
+ let inDouble = false;
9007
+ let inBacktick = false;
9008
+ let inBracket = false;
9009
+ let inLineComment = false;
9010
+ let inBlockComment = false;
9011
+ for (let i = 0; i < sql.length; i += 1) {
9012
+ const ch = sql[i];
9013
+ const next = sql[i + 1];
9014
+ if (inLineComment) {
9015
+ if (ch === "\n" || ch === "\r") inLineComment = false;
9016
+ continue;
9017
+ }
9018
+ if (inBlockComment) {
9019
+ if (ch === "*" && next === "/") {
9020
+ i += 1;
9021
+ inBlockComment = false;
9022
+ }
9023
+ continue;
9024
+ }
9025
+ if (inSingle) {
9026
+ if (ch === "'" && next === "'") {
9027
+ i += 1;
9028
+ continue;
9029
+ }
9030
+ if (ch === "'") inSingle = false;
9031
+ continue;
9032
+ }
9033
+ if (inDouble) {
9034
+ if (ch === '"' && next === '"') {
9035
+ i += 1;
9036
+ continue;
9037
+ }
9038
+ if (ch === '"') inDouble = false;
9039
+ continue;
9040
+ }
9041
+ if (inBacktick) {
9042
+ if (ch === "`" && next === "`") {
9043
+ i += 1;
9044
+ continue;
9045
+ }
9046
+ if (ch === "`") inBacktick = false;
9047
+ continue;
9048
+ }
9049
+ if (inBracket) {
9050
+ if (ch === "]") inBracket = false;
9051
+ continue;
9052
+ }
9053
+ if (ch === "-" && next === "-") {
9054
+ inLineComment = true;
9055
+ i += 1;
9056
+ continue;
9057
+ }
9058
+ if (ch === "/" && next === "*") {
9059
+ inBlockComment = true;
9060
+ i += 1;
9061
+ continue;
9062
+ }
9063
+ if (ch === "'") {
9064
+ inSingle = true;
9065
+ continue;
9066
+ }
9067
+ if (ch === '"') {
9068
+ inDouble = true;
9069
+ continue;
9070
+ }
9071
+ if (ch === "`") {
9072
+ inBacktick = true;
9073
+ continue;
9074
+ }
9075
+ if (ch === "[") {
9076
+ inBracket = true;
9077
+ continue;
9078
+ }
9079
+ if (!isIdentChar(ch) || isIdentChar(sql[i - 1])) {
9080
+ continue;
9081
+ }
9082
+ let end = i + 1;
9083
+ while (end < sql.length && isIdentChar(sql[end])) {
9084
+ end += 1;
9085
+ }
9086
+ const keyword = sql.slice(i, end);
9087
+ if (onKeyword(keyword, i)) {
9088
+ return;
9089
+ }
9090
+ i = end - 1;
8958
9091
  }
8959
- return body;
8960
9092
  }
8961
- function createBillingModule(config) {
8962
- const baseUrl = normalizeAthenaGatewayBaseUrl(config.baseUrl, {
8963
- label: "Athena billing base URL"
9093
+ function sqlContainsKeywordOutsideLiterals(sql, keyword) {
9094
+ const target = keyword.toUpperCase();
9095
+ let found = false;
9096
+ scanSqlKeywordsOutsideLiterals(sql, (token) => {
9097
+ if (token.toUpperCase() === target) {
9098
+ found = true;
9099
+ return true;
9100
+ }
9101
+ return false;
8964
9102
  });
8965
- const fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);
8966
- async function call(method, path, body, options, responseType = "json") {
8967
- const headers = buildAthenaRequestHeaders({
8968
- profile: "gateway",
8969
- sdkHeaderValue: SDK_HEADER_VALUE4,
8970
- apiKey: options?.apiKey ?? config.apiKey,
8971
- client: config.client,
8972
- configHeaders: {
8973
- ...config.headers ?? {}
8974
- },
8975
- callHeaders: options?.headers,
8976
- contentType: "application/json"
8977
- });
8978
- let requestBody;
8979
- if (body !== void 0 && body !== null) {
8980
- if (typeof body === "string" || body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof FormData || body instanceof URLSearchParams) {
8981
- requestBody = body;
8982
- } else {
8983
- requestBody = JSON.stringify(body);
8984
- if (!hasHeaderIgnoreCase(headers, "Content-Type")) {
8985
- headers["Content-Type"] = "application/json";
8986
- }
9103
+ return found;
9104
+ }
9105
+ function sqlFirstKeywordOutsideLiterals(sql) {
9106
+ let first = null;
9107
+ scanSqlKeywordsOutsideLiterals(sql, (token) => {
9108
+ first = token;
9109
+ return true;
9110
+ });
9111
+ return first;
9112
+ }
9113
+ var ROW_PRODUCING_LEAD_KEYWORDS = /* @__PURE__ */ new Set(["SELECT", "PRAGMA", "EXPLAIN", "VALUES"]);
9114
+ var MUTATION_LEAD_KEYWORDS = /* @__PURE__ */ new Set(["INSERT", "UPDATE", "DELETE", "REPLACE"]);
9115
+ var WITH_TERMINAL_KEYWORDS = /* @__PURE__ */ new Set([
9116
+ "SELECT",
9117
+ "INSERT",
9118
+ "UPDATE",
9119
+ "DELETE",
9120
+ "REPLACE",
9121
+ "VALUES",
9122
+ "PRAGMA",
9123
+ "EXPLAIN"
9124
+ ]);
9125
+ function sqlTerminalKeywordAfterWith(sql) {
9126
+ let inSingle = false;
9127
+ let inDouble = false;
9128
+ let inBacktick = false;
9129
+ let inBracket = false;
9130
+ let inLineComment = false;
9131
+ let inBlockComment = false;
9132
+ let depth = 0;
9133
+ let sawWith = false;
9134
+ for (let i = 0; i < sql.length; i += 1) {
9135
+ const ch = sql[i];
9136
+ const next = sql[i + 1];
9137
+ if (inLineComment) {
9138
+ if (ch === "\n" || ch === "\r") inLineComment = false;
9139
+ continue;
9140
+ }
9141
+ if (inBlockComment) {
9142
+ if (ch === "*" && next === "/") {
9143
+ i += 1;
9144
+ inBlockComment = false;
8987
9145
  }
9146
+ continue;
8988
9147
  }
8989
- const targetUrl = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
8990
- const response = await fetchImpl(targetUrl, {
8991
- method,
8992
- headers,
8993
- body: requestBody,
8994
- signal: options?.signal
8995
- });
8996
- if (responseType === "text") {
8997
- const text = await response.text();
8998
- if (!response.ok) {
8999
- throw new AthenaBillingError({
9000
- message: `Billing request failed (${response.status})`,
9001
- status: response.status,
9002
- endpoint: path,
9003
- method,
9004
- body: text
9005
- });
9148
+ if (inSingle) {
9149
+ if (ch === "'" && next === "'") {
9150
+ i += 1;
9151
+ continue;
9006
9152
  }
9007
- return text;
9153
+ if (ch === "'") inSingle = false;
9154
+ continue;
9008
9155
  }
9009
- const rawText = await response.text();
9010
- let parsed = rawText;
9011
- if (rawText) {
9012
- try {
9013
- parsed = JSON.parse(rawText);
9014
- } catch {
9015
- parsed = rawText;
9156
+ if (inDouble) {
9157
+ if (ch === '"' && next === '"') {
9158
+ i += 1;
9159
+ continue;
9016
9160
  }
9017
- } else {
9018
- parsed = null;
9161
+ if (ch === '"') inDouble = false;
9162
+ continue;
9019
9163
  }
9020
- if (!response.ok) {
9021
- const message = parsed && typeof parsed === "object" && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `Billing request failed (${response.status})`;
9022
- throw new AthenaBillingError({
9023
- message,
9024
- status: response.status,
9025
- endpoint: path,
9026
- method,
9027
- body: parsed
9028
- });
9164
+ if (inBacktick) {
9165
+ if (ch === "`" && next === "`") {
9166
+ i += 1;
9167
+ continue;
9168
+ }
9169
+ if (ch === "`") inBacktick = false;
9170
+ continue;
9029
9171
  }
9030
- return parseEnvelopeData(parsed);
9172
+ if (inBracket) {
9173
+ if (ch === "]") inBracket = false;
9174
+ continue;
9175
+ }
9176
+ if (ch === "-" && next === "-") {
9177
+ inLineComment = true;
9178
+ i += 1;
9179
+ continue;
9180
+ }
9181
+ if (ch === "/" && next === "*") {
9182
+ inBlockComment = true;
9183
+ i += 1;
9184
+ continue;
9185
+ }
9186
+ if (ch === "'") {
9187
+ inSingle = true;
9188
+ continue;
9189
+ }
9190
+ if (ch === '"') {
9191
+ inDouble = true;
9192
+ continue;
9193
+ }
9194
+ if (ch === "`") {
9195
+ inBacktick = true;
9196
+ continue;
9197
+ }
9198
+ if (ch === "[") {
9199
+ inBracket = true;
9200
+ continue;
9201
+ }
9202
+ if (ch === "(") {
9203
+ depth += 1;
9204
+ continue;
9205
+ }
9206
+ if (ch === ")") {
9207
+ if (depth > 0) depth -= 1;
9208
+ continue;
9209
+ }
9210
+ if (depth !== 0 || !isIdentChar(ch) || isIdentChar(sql[i - 1])) {
9211
+ continue;
9212
+ }
9213
+ let end = i + 1;
9214
+ while (end < sql.length && isIdentChar(sql[end])) {
9215
+ end += 1;
9216
+ }
9217
+ const keyword = sql.slice(i, end);
9218
+ const upper = keyword.toUpperCase();
9219
+ if (!sawWith) {
9220
+ if (upper === "WITH") {
9221
+ sawWith = true;
9222
+ }
9223
+ i = end - 1;
9224
+ continue;
9225
+ }
9226
+ if (WITH_TERMINAL_KEYWORDS.has(upper)) {
9227
+ return keyword;
9228
+ }
9229
+ i = end - 1;
9031
9230
  }
9032
- return {
9033
- getCapabilities(input, options) {
9034
- return call(
9035
- "GET",
9036
- appendQuery3("/billing/v1/capabilities", connectionQuery(input)),
9037
- void 0,
9038
- options
9039
- );
9040
- },
9041
- createCheckout(body, options) {
9042
- return call("POST", "/billing/v1/checkouts", body, options);
9043
- },
9044
- listProducts(input, options) {
9045
- return call(
9046
- "GET",
9047
- appendQuery3("/billing/v1/products", connectionQuery(input)),
9048
- void 0,
9049
- options
9050
- );
9051
- },
9052
- listPrices(input, options) {
9053
- return call(
9054
- "GET",
9055
- appendQuery3("/billing/v1/prices", {
9056
- ...connectionQuery(input),
9057
- ...input.productId ? { productId: input.productId } : {}
9058
- }),
9059
- void 0,
9060
- options
9061
- );
9062
- },
9063
- listCustomers(input, options) {
9064
- return call(
9065
- "GET",
9066
- appendQuery3("/billing/v1/customers", connectionQuery(input)),
9067
- void 0,
9068
- options
9069
- );
9070
- },
9071
- createCustomer(input, options) {
9072
- return call(
9073
- "POST",
9074
- "/billing/v1/customers",
9075
- {
9076
- connectionId: input.connectionId,
9077
- clientName: input.clientName,
9078
- email: input.email,
9079
- name: input.name,
9080
- metadata: input.metadata ?? {},
9081
- idempotencyKey: input.idempotencyKey
9082
- },
9083
- options
9084
- );
9085
- },
9231
+ return null;
9232
+ }
9233
+ function sqlLeadStatementKeyword(sql) {
9234
+ const first = sqlFirstKeywordOutsideLiterals(sql);
9235
+ if (!first) return null;
9236
+ if (first.toUpperCase() !== "WITH") return first;
9237
+ return sqlTerminalKeywordAfterWith(sql) ?? first;
9238
+ }
9239
+ function statementExpectsResultRows(sql) {
9240
+ const lead = sqlLeadStatementKeyword(sql);
9241
+ if (lead) {
9242
+ const upper = lead.toUpperCase();
9243
+ if (ROW_PRODUCING_LEAD_KEYWORDS.has(upper)) {
9244
+ return true;
9245
+ }
9246
+ if (MUTATION_LEAD_KEYWORDS.has(upper)) {
9247
+ return sqlContainsKeywordOutsideLiterals(sql, "RETURNING");
9248
+ }
9249
+ }
9250
+ return sqlContainsKeywordOutsideLiterals(sql, "RETURNING");
9251
+ }
9252
+ function collectRowsFromBatchResults(results) {
9253
+ const rows = [];
9254
+ for (const item of results) {
9255
+ if (Array.isArray(item.results) && item.results.length > 0) {
9256
+ rows.push(...item.results);
9257
+ }
9258
+ }
9259
+ return rows;
9260
+ }
9261
+ function sumBatchAffectedRows(results, statementCount) {
9262
+ let sum2 = 0;
9263
+ let sawChanges = false;
9264
+ for (const item of results) {
9265
+ const changes = item.meta?.changes;
9266
+ if (typeof changes === "number") {
9267
+ sum2 += changes;
9268
+ sawChanges = true;
9269
+ }
9270
+ }
9271
+ return sawChanges ? sum2 : statementCount;
9272
+ }
9273
+ function matchSqlKeywordAt(query, index, keyword) {
9274
+ const len = keyword.length;
9275
+ if (index + len > query.length) {
9276
+ return null;
9277
+ }
9278
+ const slice = query.slice(index, index + len);
9279
+ if (slice.toLowerCase() !== keyword.toLowerCase()) {
9280
+ return null;
9281
+ }
9282
+ const before = index === 0 ? "" : query[index - 1];
9283
+ const after = index + len >= query.length ? "" : query[index + len];
9284
+ const isIdent = (c) => /[A-Za-z0-9_]/.test(c);
9285
+ if (before && isIdent(before)) {
9286
+ return null;
9287
+ }
9288
+ if (after && isIdent(after)) {
9289
+ return null;
9290
+ }
9291
+ return len;
9292
+ }
9293
+ function splitSqlStatements(query) {
9294
+ const statements = [];
9295
+ let inSingle = false;
9296
+ let inDouble = false;
9297
+ let inBacktick = false;
9298
+ let inBracket = false;
9299
+ let inLineComment = false;
9300
+ let inBlockComment = false;
9301
+ let segmentStart = 0;
9302
+ let segmentHasContent = false;
9303
+ let awaitTriggerBegin = false;
9304
+ let triggerBodyDepth = 0;
9305
+ let caseDepth = 0;
9306
+ const flushSegment = (end) => {
9307
+ if (!segmentHasContent) {
9308
+ segmentStart = end + 1;
9309
+ return;
9310
+ }
9311
+ const sql = query.slice(segmentStart, end).trim();
9312
+ if (sql) {
9313
+ statements.push(sql);
9314
+ }
9315
+ segmentHasContent = false;
9316
+ segmentStart = end + 1;
9317
+ awaitTriggerBegin = false;
9318
+ triggerBodyDepth = 0;
9319
+ caseDepth = 0;
9320
+ };
9321
+ for (let i = 0; i < query.length; i += 1) {
9322
+ const ch = query[i];
9323
+ const next = query[i + 1];
9324
+ if (inLineComment) {
9325
+ if (ch === "\n" || ch === "\r") {
9326
+ inLineComment = false;
9327
+ }
9328
+ continue;
9329
+ }
9330
+ if (inBlockComment) {
9331
+ if (ch === "*" && next === "/") {
9332
+ inBlockComment = false;
9333
+ i += 1;
9334
+ }
9335
+ continue;
9336
+ }
9337
+ if (inSingle) {
9338
+ if (ch === "'" && next === "'") {
9339
+ i += 1;
9340
+ continue;
9341
+ }
9342
+ if (ch === "'") {
9343
+ inSingle = false;
9344
+ }
9345
+ continue;
9346
+ }
9347
+ if (inDouble) {
9348
+ if (ch === '"' && next === '"') {
9349
+ i += 1;
9350
+ continue;
9351
+ }
9352
+ if (ch === '"') {
9353
+ inDouble = false;
9354
+ }
9355
+ continue;
9356
+ }
9357
+ if (inBacktick) {
9358
+ if (ch === "`" && next === "`") {
9359
+ i += 1;
9360
+ continue;
9361
+ }
9362
+ if (ch === "`") {
9363
+ inBacktick = false;
9364
+ }
9365
+ continue;
9366
+ }
9367
+ if (inBracket) {
9368
+ if (ch === "]") {
9369
+ inBracket = false;
9370
+ }
9371
+ continue;
9372
+ }
9373
+ if (ch === "-" && next === "-") {
9374
+ inLineComment = true;
9375
+ i += 1;
9376
+ continue;
9377
+ }
9378
+ if (ch === "/" && next === "*") {
9379
+ inBlockComment = true;
9380
+ i += 1;
9381
+ continue;
9382
+ }
9383
+ if (ch === "'") {
9384
+ inSingle = true;
9385
+ segmentHasContent = true;
9386
+ continue;
9387
+ }
9388
+ if (ch === '"') {
9389
+ inDouble = true;
9390
+ segmentHasContent = true;
9391
+ continue;
9392
+ }
9393
+ if (ch === "`") {
9394
+ inBacktick = true;
9395
+ segmentHasContent = true;
9396
+ continue;
9397
+ }
9398
+ if (ch === "[") {
9399
+ inBracket = true;
9400
+ segmentHasContent = true;
9401
+ continue;
9402
+ }
9403
+ if (/[A-Za-z_]/.test(ch)) {
9404
+ const createLen = matchSqlKeywordAt(query, i, "CREATE");
9405
+ if (createLen != null) {
9406
+ let j2 = i + createLen;
9407
+ const skipWsAndComments = () => {
9408
+ while (j2 < query.length) {
9409
+ const c = query[j2];
9410
+ const n = query[j2 + 1];
9411
+ if (/\s/.test(c)) {
9412
+ j2 += 1;
9413
+ continue;
9414
+ }
9415
+ if (c === "-" && n === "-") {
9416
+ j2 += 2;
9417
+ while (j2 < query.length && query[j2] !== "\n" && query[j2] !== "\r") {
9418
+ j2 += 1;
9419
+ }
9420
+ continue;
9421
+ }
9422
+ if (c === "/" && n === "*") {
9423
+ j2 += 2;
9424
+ while (j2 < query.length) {
9425
+ if (query[j2] === "*" && query[j2 + 1] === "/") {
9426
+ j2 += 2;
9427
+ break;
9428
+ }
9429
+ j2 += 1;
9430
+ }
9431
+ continue;
9432
+ }
9433
+ break;
9434
+ }
9435
+ };
9436
+ skipWsAndComments();
9437
+ const tempLen = matchSqlKeywordAt(query, j2, "TEMPORARY") ?? matchSqlKeywordAt(query, j2, "TEMP");
9438
+ if (tempLen != null) {
9439
+ j2 += tempLen;
9440
+ skipWsAndComments();
9441
+ }
9442
+ const triggerLen = matchSqlKeywordAt(query, j2, "TRIGGER");
9443
+ if (triggerLen != null) {
9444
+ awaitTriggerBegin = true;
9445
+ segmentHasContent = true;
9446
+ i += createLen - 1;
9447
+ continue;
9448
+ }
9449
+ segmentHasContent = true;
9450
+ i += createLen - 1;
9451
+ continue;
9452
+ }
9453
+ const caseLen = matchSqlKeywordAt(query, i, "CASE");
9454
+ if (caseLen != null) {
9455
+ caseDepth += 1;
9456
+ segmentHasContent = true;
9457
+ i += caseLen - 1;
9458
+ continue;
9459
+ }
9460
+ const beginLen = matchSqlKeywordAt(query, i, "BEGIN");
9461
+ if (beginLen != null) {
9462
+ if (awaitTriggerBegin) {
9463
+ triggerBodyDepth += 1;
9464
+ awaitTriggerBegin = false;
9465
+ }
9466
+ segmentHasContent = true;
9467
+ i += beginLen - 1;
9468
+ continue;
9469
+ }
9470
+ const endLen = matchSqlKeywordAt(query, i, "END");
9471
+ if (endLen != null) {
9472
+ if (caseDepth > 0) {
9473
+ caseDepth -= 1;
9474
+ } else if (triggerBodyDepth > 0) {
9475
+ triggerBodyDepth -= 1;
9476
+ }
9477
+ segmentHasContent = true;
9478
+ i += endLen - 1;
9479
+ continue;
9480
+ }
9481
+ let j = i + 1;
9482
+ while (j < query.length && /[A-Za-z0-9_]/.test(query[j])) {
9483
+ j += 1;
9484
+ }
9485
+ segmentHasContent = true;
9486
+ i = j - 1;
9487
+ continue;
9488
+ }
9489
+ if (ch === ";") {
9490
+ if (triggerBodyDepth > 0 || caseDepth > 0) {
9491
+ segmentHasContent = true;
9492
+ continue;
9493
+ }
9494
+ flushSegment(i);
9495
+ continue;
9496
+ }
9497
+ if (!/\s/.test(ch)) {
9498
+ segmentHasContent = true;
9499
+ }
9500
+ }
9501
+ flushSegment(query.length);
9502
+ return statements;
9503
+ }
9504
+ function isMultiStatement(query) {
9505
+ return splitSqlStatements(query).length > 1;
9506
+ }
9507
+ function resolveSessionTarget(db, input) {
9508
+ const sessionValue = input.bookmark?.trim() || input.sessionMode?.trim();
9509
+ if (!sessionValue) {
9510
+ return { target: db, session: null };
9511
+ }
9512
+ if (typeof db.withSession !== "function") {
9513
+ throw new Error("D1 session mode/bookmark requested but withSession is not available");
9514
+ }
9515
+ const session = db.withSession(sessionValue);
9516
+ return { target: session, session };
9517
+ }
9518
+ function normalizeD1BindParams(params) {
9519
+ return params.map((value) => {
9520
+ if (typeof value === "boolean") {
9521
+ return value ? 1 : 0;
9522
+ }
9523
+ return value;
9524
+ });
9525
+ }
9526
+ async function executeD1Query(db, input) {
9527
+ const query = input.query?.trim();
9528
+ if (!query) {
9529
+ return { ok: false, error: "invalid_query", message: "query is required" };
9530
+ }
9531
+ const params = normalizeD1BindParams(Array.isArray(input.params) ? input.params : []);
9532
+ const { target, session } = resolveSessionTarget(db, input);
9533
+ if (isMultiStatement(query)) {
9534
+ if (params.length > 0) {
9535
+ return {
9536
+ ok: false,
9537
+ error: "invalid_query",
9538
+ message: "params are only supported for single prepared statements"
9539
+ };
9540
+ }
9541
+ const resolveBookmark = () => session?.getBookmark() ?? null;
9542
+ const parts = splitSqlStatements(query);
9543
+ if (typeof target.batch === "function") {
9544
+ const prepared = parts.map((part) => target.prepare(part));
9545
+ const results = await target.batch(prepared);
9546
+ const rows2 = collectRowsFromBatchResults(results);
9547
+ return {
9548
+ ok: true,
9549
+ rows: rows2,
9550
+ columns: resultColumns(rows2),
9551
+ // Prefer returned rows; otherwise sum mutation meta.changes (not statement count).
9552
+ count: rows2.length > 0 ? rows2.length : sumBatchAffectedRows(results, parts.length),
9553
+ bookmark: resolveBookmark(),
9554
+ meta: { statementCount: parts.length, results },
9555
+ statementCount: parts.length
9556
+ };
9557
+ }
9558
+ const canExec = typeof target.exec === "function" && !session;
9559
+ if (canExec) {
9560
+ const execResult = await target.exec(query);
9561
+ return {
9562
+ ok: true,
9563
+ rows: [],
9564
+ columns: [],
9565
+ durationMs: execResult.duration,
9566
+ count: execResult.count,
9567
+ bookmark: resolveBookmark(),
9568
+ meta: { statementCount: execResult.count },
9569
+ statementCount: execResult.count
9570
+ };
9571
+ }
9572
+ return {
9573
+ ok: false,
9574
+ error: "invalid_query",
9575
+ message: "multi-statement query requires D1 batch() or exec() support"
9576
+ };
9577
+ }
9578
+ let statement = target.prepare(query);
9579
+ if (params.length > 0) {
9580
+ statement = statement.bind(...params);
9581
+ }
9582
+ const expectsRows = statementExpectsResultRows(query);
9583
+ const result = expectsRows ? await statement.all() : await statement.run();
9584
+ if (result.success === false) {
9585
+ const errorField = result.error;
9586
+ const message = typeof errorField === "string" && errorField.trim() ? errorField : "D1 query failed";
9587
+ return {
9588
+ ok: false,
9589
+ error: "query_failed",
9590
+ message
9591
+ };
9592
+ }
9593
+ const rows = Array.isArray(result.results) ? result.results : [];
9594
+ const bookmark = session?.getBookmark() ?? null;
9595
+ const meta = result.meta ?? {};
9596
+ const changes = typeof meta.changes === "number" ? meta.changes : typeof result.meta?.changes === "number" ? result.meta.changes : void 0;
9597
+ return {
9598
+ ok: true,
9599
+ rows,
9600
+ columns: resultColumns(rows),
9601
+ durationMs: typeof result.meta?.duration === "number" ? result.meta.duration : void 0,
9602
+ count: expectsRows ? rows.length : changes ?? rows.length,
9603
+ bookmark,
9604
+ meta
9605
+ };
9606
+ }
9607
+ async function executeD1Batch(db, input) {
9608
+ const statements = Array.isArray(input.statements) ? input.statements : [];
9609
+ if (statements.length === 0) {
9610
+ return {
9611
+ ok: false,
9612
+ error: "invalid_batch",
9613
+ message: "statements must contain at least one item"
9614
+ };
9615
+ }
9616
+ const { target, session } = resolveSessionTarget(db, input);
9617
+ const prepared = statements.map((item) => {
9618
+ const query = item.query?.trim();
9619
+ if (!query) {
9620
+ throw new Error("statements[].query is required");
9621
+ }
9622
+ const params = normalizeD1BindParams(Array.isArray(item.params) ? item.params : []);
9623
+ let statement = target.prepare(query);
9624
+ if (params.length > 0) {
9625
+ statement = statement.bind(...params);
9626
+ }
9627
+ return statement;
9628
+ });
9629
+ const results = await target.batch(prepared);
9630
+ const bookmark = session?.getBookmark() ?? null;
9631
+ return {
9632
+ ok: true,
9633
+ results,
9634
+ bookmark
9635
+ };
9636
+ }
9637
+
9638
+ // src/cloudflare/d1/sql.ts
9639
+ function asSingle(sql, params) {
9640
+ return { sql, params };
9641
+ }
9642
+ function asBatch(statements) {
9643
+ if (statements.length === 0) {
9644
+ throw new D1SqlCompileError("empty_insert", "batch requires at least one statement");
9645
+ }
9646
+ return {
9647
+ sql: statements[0].sql,
9648
+ params: statements[0].params,
9649
+ statements
9650
+ };
9651
+ }
9652
+ function hasPaginationBounds(payload) {
9653
+ return payload.limit !== void 0 || payload.offset !== void 0 || payload.page_size !== void 0 || payload.current_page !== void 0;
9654
+ }
9655
+ function assertEffectiveMutationBounds(payload) {
9656
+ if (payload.current_page !== void 0 && payload.page_size === void 0 && payload.limit === void 0) {
9657
+ throw new D1SqlCompileError(
9658
+ "page_without_size",
9659
+ "current_page requires page_size (or limit) for bounded update/delete on D1 edge-local"
9660
+ );
9661
+ }
9662
+ const clause = limitOffsetClause(payload);
9663
+ if (!clause.trim()) {
9664
+ throw new D1SqlCompileError(
9665
+ "invalid_pagination_bounds",
9666
+ "Bounded update/delete requires limit, offset, and/or page_size on D1 edge-local"
9667
+ );
9668
+ }
9669
+ }
9670
+ var SQLITE_ROWID_ALIASES = /* @__PURE__ */ new Set(["rowid", "oid", "_rowid_"]);
9671
+ function referencedMutationColumns(payload) {
9672
+ const names = [];
9673
+ for (const condition of payload.conditions ?? []) {
9674
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
9675
+ if (column) names.push(column);
9676
+ }
9677
+ if (payload.sort_by?.field?.trim()) {
9678
+ names.push(payload.sort_by.field.trim());
9679
+ }
9680
+ return names;
9681
+ }
9682
+ function resolveBoundedIdentityColumn(payload, options) {
9683
+ const refs = referencedMutationColumns(payload);
9684
+ const lower = refs.map((name) => name.toLowerCase());
9685
+ if (lower.some((name) => SQLITE_ROWID_ALIASES.has(name))) {
9686
+ throw new D1SqlCompileError(
9687
+ "bounded_mutation_unsafe_identity",
9688
+ "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."
9689
+ );
9690
+ }
9691
+ const identity = options?.identityColumn?.trim();
9692
+ if (!identity) {
9693
+ throw new D1SqlCompileError(
9694
+ "bounded_mutation_no_unique_identity",
9695
+ "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."
9696
+ );
9697
+ }
9698
+ if (SQLITE_ROWID_ALIASES.has(identity.toLowerCase())) {
9699
+ throw new D1SqlCompileError(
9700
+ "bounded_mutation_unsafe_identity",
9701
+ `Bounded update/delete cannot use identity column "${identity}" \u2014 it may shadow SQLite row identity.`
9702
+ );
9703
+ }
9704
+ return identity;
9705
+ }
9706
+ function boundedRowidInClause(table, whereSql, whereParams, payload, options) {
9707
+ assertEffectiveMutationBounds(payload);
9708
+ const identity = resolveBoundedIdentityColumn(payload, options);
9709
+ const identitySql = quoteIdent(identity);
9710
+ const innerWhere = whereSql.replace(/^WHERE\s+/i, "");
9711
+ const parts = [
9712
+ `SELECT ${identitySql} FROM ${quoteIdent(table)}`,
9713
+ innerWhere ? `WHERE ${innerWhere}` : "",
9714
+ orderClause(payload.sort_by),
9715
+ limitOffsetClause(payload)
9716
+ ].filter(Boolean);
9717
+ return {
9718
+ sql: `${identitySql} IN (${parts.join(" ")})`,
9719
+ params: [...whereParams]
9720
+ };
9721
+ }
9722
+ var D1SqlCompileError = class extends Error {
9723
+ code;
9724
+ constructor(code, message) {
9725
+ super(message);
9726
+ this.name = "D1SqlCompileError";
9727
+ this.code = code;
9728
+ }
9729
+ };
9730
+ var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
9731
+ function quoteIdent(name) {
9732
+ const trimmed = name.trim();
9733
+ if (!trimmed) {
9734
+ throw new D1SqlCompileError("invalid_identifier", "Identifier is required");
9735
+ }
9736
+ if (trimmed.includes(".")) {
9737
+ throw new D1SqlCompileError(
9738
+ "schema_qualified_name",
9739
+ `Schema-qualified names are unsupported on D1 edge-local: ${trimmed}`
9740
+ );
9741
+ }
9742
+ if (!SAFE_IDENTIFIER.test(trimmed)) {
9743
+ throw new D1SqlCompileError(
9744
+ "invalid_identifier",
9745
+ `Invalid SQL identifier for D1 edge-local: ${trimmed}`
9746
+ );
9747
+ }
9748
+ return quoteQualifiedIdentifier(trimmed);
9749
+ }
9750
+ var RESPONSE_ALIAS_PATTERN2 = /^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([A-Za-z_][A-Za-z0-9_]*)$/;
9751
+ var SQL_ALIAS_PATTERN2 = /^([A-Za-z_][A-Za-z0-9_]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
9752
+ function quoteSelectTokenStrict(token) {
9753
+ const trimmed = token.trim();
9754
+ if (!trimmed || trimmed === "*") return trimmed || "*";
9755
+ if (SAFE_IDENTIFIER.test(trimmed)) {
9756
+ return quoteQualifiedIdentifier(trimmed);
9757
+ }
9758
+ const responseAlias = RESPONSE_ALIAS_PATTERN2.exec(trimmed);
9759
+ if (responseAlias) {
9760
+ const [, aliasIdentifier, baseIdentifier] = responseAlias;
9761
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteQualifiedIdentifier(aliasIdentifier)}`;
9762
+ }
9763
+ const sqlAlias = SQL_ALIAS_PATTERN2.exec(trimmed);
9764
+ if (sqlAlias) {
9765
+ const [, baseIdentifier, aliasIdentifier] = sqlAlias;
9766
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteQualifiedIdentifier(aliasIdentifier)}`;
9767
+ }
9768
+ throw new D1SqlCompileError(
9769
+ "unsafe_select",
9770
+ `SELECT/RETURNING expressions are not supported on D1 edge-local; use column names or aliases only: ${token}`
9771
+ );
9772
+ }
9773
+ function selectClause(columns) {
9774
+ if (columns === void 0 || columns === "*" || columns === "") return "*";
9775
+ if (typeof columns === "string") {
9776
+ const trimmed = columns.trim();
9777
+ if (!trimmed || trimmed === "*") return "*";
9778
+ return trimmed.split(",").map((part) => quoteSelectTokenStrict(part)).join(", ");
9779
+ }
9780
+ if (columns.length === 0) return "*";
9781
+ return columns.map((column) => quoteSelectTokenStrict(column)).join(", ");
9782
+ }
9783
+ function wantsReturning(payload) {
9784
+ return Boolean(payload.columns) && payload.head !== true;
9785
+ }
9786
+ function conditionToWhere(condition) {
9787
+ const column = condition.column?.trim() || condition.eq_column?.trim() || "";
9788
+ if (!column) {
9789
+ throw new D1SqlCompileError("invalid_condition", "Condition requires a column");
9790
+ }
9791
+ const col = quoteIdent(column);
9792
+ const operator = (condition.operator || "eq").toLowerCase();
9793
+ const value = condition.value !== void 0 ? condition.value : condition.eq_value;
9794
+ switch (operator) {
9795
+ case "eq": {
9796
+ if (Array.isArray(value)) {
9797
+ if (value.length === 0) {
9798
+ return { sql: "1 = 0", params: [] };
9799
+ }
9800
+ const placeholders = value.map(() => "?").join(", ");
9801
+ return { sql: `${col} IN (${placeholders})`, params: [...value] };
9802
+ }
9803
+ if (value === null) {
9804
+ return { sql: `${col} IS NULL`, params: [] };
9805
+ }
9806
+ return { sql: `${col} = ?`, params: [value ?? null] };
9807
+ }
9808
+ case "neq":
9809
+ if (value === null) {
9810
+ return { sql: `${col} IS NOT NULL`, params: [] };
9811
+ }
9812
+ return { sql: `${col} != ?`, params: [value ?? null] };
9813
+ case "gt":
9814
+ return { sql: `${col} > ?`, params: [value ?? null] };
9815
+ case "gte":
9816
+ return { sql: `${col} >= ?`, params: [value ?? null] };
9817
+ case "lt":
9818
+ return { sql: `${col} < ?`, params: [value ?? null] };
9819
+ case "lte":
9820
+ return { sql: `${col} <= ?`, params: [value ?? null] };
9821
+ case "like":
9822
+ return { sql: `${col} LIKE ?`, params: [value ?? null] };
9823
+ case "ilike":
9824
+ return { sql: `${col} LIKE ? COLLATE NOCASE`, params: [value ?? null] };
9825
+ case "in": {
9826
+ const items = Array.isArray(value) ? value : value === void 0 ? [] : [value];
9827
+ if (items.length === 0) {
9828
+ return { sql: "1 = 0", params: [] };
9829
+ }
9830
+ const placeholders = items.map(() => "?").join(", ");
9831
+ return { sql: `${col} IN (${placeholders})`, params: [...items] };
9832
+ }
9833
+ case "is": {
9834
+ if (value === null || value === "null") {
9835
+ return { sql: `${col} IS NULL`, params: [] };
9836
+ }
9837
+ if (value === true || value === "true") {
9838
+ return { sql: `${col} IS TRUE`, params: [] };
9839
+ }
9840
+ if (value === false || value === "false") {
9841
+ return { sql: `${col} IS FALSE`, params: [] };
9842
+ }
9843
+ return { sql: `${col} IS ?`, params: [value] };
9844
+ }
9845
+ case "not":
9846
+ case "or":
9847
+ case "contains":
9848
+ case "containedby":
9849
+ throw new D1SqlCompileError(
9850
+ "unsupported_operator",
9851
+ `Condition operator "${operator}" is not supported on D1 edge-local L1`
9852
+ );
9853
+ default:
9854
+ throw new D1SqlCompileError(
9855
+ "unsupported_operator",
9856
+ `Unknown condition operator "${operator}"`
9857
+ );
9858
+ }
9859
+ }
9860
+ function buildWhere(conditions) {
9861
+ if (!conditions?.length) {
9862
+ return { sql: "", params: [] };
9863
+ }
9864
+ const parts = [];
9865
+ const params = [];
9866
+ for (const condition of conditions) {
9867
+ if (!condition.operator && condition.eq_column) {
9868
+ const clause2 = conditionToWhere({
9869
+ ...condition,
9870
+ operator: "eq",
9871
+ column: condition.eq_column,
9872
+ value: condition.eq_value
9873
+ });
9874
+ parts.push(clause2.sql);
9875
+ params.push(...clause2.params);
9876
+ continue;
9877
+ }
9878
+ const clause = conditionToWhere(condition);
9879
+ parts.push(clause.sql);
9880
+ params.push(...clause.params);
9881
+ }
9882
+ return {
9883
+ sql: parts.length ? `WHERE ${parts.join(" AND ")}` : "",
9884
+ params
9885
+ };
9886
+ }
9887
+ function orderClause(order) {
9888
+ if (!order?.field?.trim()) return "";
9889
+ const direction = order.direction === "descending" ? "DESC" : "ASC";
9890
+ return `ORDER BY ${quoteIdent(order.field)} ${direction}`;
9891
+ }
9892
+ function limitOffsetClause(payload) {
9893
+ let limit = payload.limit;
9894
+ let offset = payload.offset;
9895
+ if (limit === void 0 && payload.page_size !== void 0) {
9896
+ limit = payload.page_size;
9897
+ }
9898
+ if (payload.current_page !== void 0 && offset === void 0) {
9899
+ const pageSize = payload.page_size ?? payload.limit;
9900
+ if (pageSize !== void 0) {
9901
+ offset = Math.max(0, (payload.current_page - 1) * pageSize);
9902
+ }
9903
+ }
9904
+ const parts = [];
9905
+ if (offset !== void 0 && limit === void 0) {
9906
+ parts.push("LIMIT -1");
9907
+ parts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
9908
+ } else {
9909
+ if (limit !== void 0) {
9910
+ parts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
9911
+ }
9912
+ if (offset !== void 0) {
9913
+ parts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
9914
+ }
9915
+ }
9916
+ return parts.join(" ");
9917
+ }
9918
+ function rejectStructuredRelations(payload) {
9919
+ const select = payload.select;
9920
+ if (select && typeof select === "object" && !Array.isArray(select)) {
9921
+ for (const value of Object.values(select)) {
9922
+ if (value && typeof value === "object") {
9923
+ throw new D1SqlCompileError(
9924
+ "relations_unsupported",
9925
+ "Nested relation selects are unsupported on D1 edge-local"
9926
+ );
9927
+ }
9928
+ }
9929
+ }
9930
+ if (payload.view_name) {
9931
+ throw new D1SqlCompileError(
9932
+ "view_unsupported",
9933
+ "view_name is unsupported on D1 edge-local L1"
9934
+ );
9935
+ }
9936
+ }
9937
+ function jsonValue(value) {
9938
+ if (value === void 0) return null;
9939
+ if (value !== null && typeof value === "object") {
9940
+ return JSON.stringify(value);
9941
+ }
9942
+ return value;
9943
+ }
9944
+ function compileD1Fetch(payload) {
9945
+ rejectStructuredRelations(payload);
9946
+ const table = payload.table_name?.trim();
9947
+ if (!table) {
9948
+ throw new D1SqlCompileError("missing_table", "table_name is required for fetch");
9949
+ }
9950
+ let columns = payload.columns;
9951
+ if (payload.select && typeof payload.select === "object" && !Array.isArray(payload.select)) {
9952
+ const keys = Object.entries(payload.select).filter(([, enabled]) => enabled === true || enabled === 1).map(([key]) => key);
9953
+ if (keys.length > 0) {
9954
+ columns = keys;
9955
+ }
9956
+ } else if (typeof payload.select === "string" && payload.select.trim()) {
9957
+ columns = payload.select;
9958
+ }
9959
+ let where = buildWhere(payload.conditions);
9960
+ if (!where.sql && payload.where && typeof payload.where === "object") {
9961
+ const eqConditions = Object.entries(
9962
+ payload.where
9963
+ ).map(([column, value]) => ({
9964
+ column,
9965
+ operator: "eq",
9966
+ value
9967
+ }));
9968
+ where = buildWhere(eqConditions);
9969
+ }
9970
+ if (payload.head === true) {
9971
+ return compileD1CountFromWhere(table, where);
9972
+ }
9973
+ const parts = [
9974
+ `SELECT ${selectClause(columns)} FROM ${quoteIdent(table)}`,
9975
+ where.sql,
9976
+ orderClause(payload.sort_by),
9977
+ limitOffsetClause(payload)
9978
+ ].filter(Boolean);
9979
+ return asSingle(parts.join(" "), where.params);
9980
+ }
9981
+ function compileD1Count(payload) {
9982
+ rejectStructuredRelations(payload);
9983
+ const table = payload.table_name?.trim();
9984
+ if (!table) {
9985
+ throw new D1SqlCompileError("missing_table", "table_name is required for count");
9986
+ }
9987
+ let where = buildWhere(payload.conditions);
9988
+ if (!where.sql && payload.where && typeof payload.where === "object") {
9989
+ const eqConditions = Object.entries(
9990
+ payload.where
9991
+ ).map(([column, value]) => ({
9992
+ column,
9993
+ operator: "eq",
9994
+ value
9995
+ }));
9996
+ where = buildWhere(eqConditions);
9997
+ }
9998
+ return compileD1CountFromWhere(table, where);
9999
+ }
10000
+ function compileD1CountFromWhere(table, where) {
10001
+ const parts = [
10002
+ `SELECT COUNT(*) AS __athena_count FROM ${quoteIdent(table)}`,
10003
+ where.sql
10004
+ ].filter(Boolean);
10005
+ return asSingle(parts.join(" "), where.params);
10006
+ }
10007
+ function extractAthenaCount(rows) {
10008
+ const first = rows[0];
10009
+ const rawCount = first && typeof first === "object" && !Array.isArray(first) ? first.__athena_count : void 0;
10010
+ const count = typeof rawCount === "number" ? rawCount : typeof rawCount === "bigint" ? Number(rawCount) : Number(rawCount ?? 0);
10011
+ return Number.isFinite(count) ? count : 0;
10012
+ }
10013
+ function compileSingleRowInsert(table, row, payload) {
10014
+ const columns = Object.keys(row);
10015
+ if (columns.length === 0) {
10016
+ if (payload.on_conflict) {
10017
+ throw new D1SqlCompileError(
10018
+ "default_values_upsert_unsupported",
10019
+ "DEFAULT VALUES upsert is unsupported on D1 edge-local; provide insert columns or omit onConflict"
10020
+ );
10021
+ }
10022
+ const parts2 = [`INSERT INTO ${quoteIdent(table)} DEFAULT VALUES`];
10023
+ if (wantsReturning(payload)) {
10024
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10025
+ }
10026
+ return { sql: parts2.join(" "), params: [] };
10027
+ }
10028
+ const params = columns.map((column) => jsonValue(row[column]));
10029
+ const parts = [
10030
+ `INSERT INTO ${quoteIdent(table)} (${columns.map(quoteIdent).join(", ")})`,
10031
+ `VALUES (${columns.map(() => "?").join(", ")})`
10032
+ ];
10033
+ appendOnConflict(parts, params, payload, columns);
10034
+ if (wantsReturning(payload)) {
10035
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10036
+ }
10037
+ return { sql: parts.join(" "), params };
10038
+ }
10039
+ function parseOnConflictColumns(onConflict) {
10040
+ const raw = Array.isArray(onConflict) ? onConflict : [onConflict];
10041
+ const columns = [];
10042
+ for (const item of raw) {
10043
+ for (const part of String(item).split(",")) {
10044
+ const trimmed = part.trim();
10045
+ if (trimmed) columns.push(trimmed);
10046
+ }
10047
+ }
10048
+ if (columns.length === 0) {
10049
+ throw new D1SqlCompileError(
10050
+ "invalid_on_conflict",
10051
+ "on_conflict requires at least one column"
10052
+ );
10053
+ }
10054
+ return columns;
10055
+ }
10056
+ function appendOnConflict(parts, params, payload, insertColumns) {
10057
+ if (!payload.on_conflict) return;
10058
+ const conflictCols = parseOnConflictColumns(payload.on_conflict);
10059
+ const conflictSql = conflictCols.map(quoteIdent).join(", ");
10060
+ if (payload.update_body !== void 0 && payload.update_body !== null) {
10061
+ const entries = Object.entries(payload.update_body);
10062
+ if (entries.length === 0) {
10063
+ parts.push(`ON CONFLICT (${conflictSql}) DO NOTHING`);
10064
+ return;
10065
+ }
10066
+ const assignments2 = entries.map(([column, value]) => {
10067
+ params.push(jsonValue(value));
10068
+ return `${quoteIdent(column)} = ?`;
10069
+ });
10070
+ parts.push(`ON CONFLICT (${conflictSql}) DO UPDATE SET ${assignments2.join(", ")}`);
10071
+ return;
10072
+ }
10073
+ const conflictSet = new Set(conflictCols);
10074
+ const assignments = insertColumns.filter((column) => !conflictSet.has(column)).map((column) => {
10075
+ const quoted = quoteIdent(column);
10076
+ return `${quoted} = excluded.${quoted}`;
10077
+ });
10078
+ if (assignments.length === 0) {
10079
+ parts.push(`ON CONFLICT (${conflictSql}) DO NOTHING`);
10080
+ } else {
10081
+ parts.push(`ON CONFLICT (${conflictSql}) DO UPDATE SET ${assignments.join(", ")}`);
10082
+ }
10083
+ }
10084
+ function compileD1Insert(payload) {
10085
+ const table = payload.table_name?.trim();
10086
+ if (!table) {
10087
+ throw new D1SqlCompileError("missing_table", "table_name is required for insert");
10088
+ }
10089
+ const rows = Array.isArray(payload.insert_body) ? payload.insert_body : [payload.insert_body];
10090
+ if (rows.length === 0) {
10091
+ throw new D1SqlCompileError("empty_insert", "insert_body must not be empty");
10092
+ }
10093
+ const columns = [];
10094
+ const seen = /* @__PURE__ */ new Set();
10095
+ for (const row of rows) {
10096
+ for (const key of Object.keys(row ?? {})) {
10097
+ if (seen.has(key)) continue;
10098
+ seen.add(key);
10099
+ columns.push(key);
10100
+ }
10101
+ }
10102
+ if (columns.length === 0) {
10103
+ if (rows.length === 1) {
10104
+ const compiled = compileSingleRowInsert(table, {}, payload);
10105
+ return asSingle(compiled.sql, compiled.params);
10106
+ }
10107
+ throw new D1SqlCompileError(
10108
+ "empty_insert",
10109
+ "Multi-row insert_body cannot be empty objects; use a single {} for DEFAULT VALUES"
10110
+ );
10111
+ }
10112
+ const forceNullForMissing = payload.default_to_null === true;
10113
+ const isSparse = rows.some(
10114
+ (row) => columns.some((column) => !Object.prototype.hasOwnProperty.call(row, column))
10115
+ );
10116
+ if (isSparse && !forceNullForMissing && rows.length > 1) {
10117
+ return asBatch(
10118
+ rows.map((row) => compileSingleRowInsert(table, row, payload))
10119
+ );
10120
+ }
10121
+ if (isSparse && !forceNullForMissing && rows.length === 1) {
10122
+ const compiled = compileSingleRowInsert(table, rows[0], payload);
10123
+ return asSingle(compiled.sql, compiled.params);
10124
+ }
10125
+ const params = [];
10126
+ const valueGroups = rows.map((row) => {
10127
+ const placeholders = columns.map((column) => {
10128
+ const has = Object.prototype.hasOwnProperty.call(row, column);
10129
+ if (!has) {
10130
+ params.push(null);
10131
+ return "?";
10132
+ }
10133
+ params.push(jsonValue(row[column]));
10134
+ return "?";
10135
+ });
10136
+ return `(${placeholders.join(", ")})`;
10137
+ });
10138
+ const parts = [
10139
+ `INSERT INTO ${quoteIdent(table)} (${columns.map(quoteIdent).join(", ")})`,
10140
+ `VALUES ${valueGroups.join(", ")}`
10141
+ ];
10142
+ appendOnConflict(parts, params, payload, columns);
10143
+ if (wantsReturning(payload)) {
10144
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10145
+ }
10146
+ return asSingle(parts.join(" "), params);
10147
+ }
10148
+ function compileD1Update(payload, options) {
10149
+ const table = payload.table_name?.trim();
10150
+ if (!table) {
10151
+ throw new D1SqlCompileError("missing_table", "table_name is required for update");
10152
+ }
10153
+ const entries = Object.entries(payload.update_body ?? {});
10154
+ if (entries.length === 0) {
10155
+ throw new D1SqlCompileError("empty_update", "update_body must not be empty");
10156
+ }
10157
+ const params = [];
10158
+ const assignments = entries.map(([column, value]) => {
10159
+ params.push(jsonValue(value));
10160
+ return `${quoteIdent(column)} = ?`;
10161
+ });
10162
+ const where = buildWhere(payload.conditions);
10163
+ if (!where.sql) {
10164
+ throw new D1SqlCompileError(
10165
+ "unfiltered_update",
10166
+ "UPDATE requires at least one condition on D1 edge-local"
10167
+ );
10168
+ }
10169
+ if (hasPaginationBounds(payload) || payload.sort_by) {
10170
+ if (!hasPaginationBounds(payload)) {
10171
+ throw new D1SqlCompileError(
10172
+ "order_without_bounds",
10173
+ "UPDATE with sort_by requires limit/offset or page_size/current_page on D1 edge-local"
10174
+ );
10175
+ }
10176
+ const bounded = boundedRowidInClause(
10177
+ table,
10178
+ where.sql,
10179
+ where.params,
10180
+ {
10181
+ ...payload,
10182
+ conditions: payload.conditions
10183
+ },
10184
+ options
10185
+ );
10186
+ params.push(...bounded.params);
10187
+ const parts2 = [
10188
+ `UPDATE ${quoteIdent(table)} SET ${assignments.join(", ")}`,
10189
+ `WHERE ${bounded.sql}`
10190
+ ];
10191
+ if (wantsReturning(payload)) {
10192
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10193
+ }
10194
+ return asSingle(parts2.join(" "), params);
10195
+ }
10196
+ params.push(...where.params);
10197
+ const parts = [
10198
+ `UPDATE ${quoteIdent(table)} SET ${assignments.join(", ")}`,
10199
+ where.sql
10200
+ ];
10201
+ if (wantsReturning(payload)) {
10202
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10203
+ }
10204
+ return asSingle(parts.join(" "), params);
10205
+ }
10206
+ function compileD1Delete(payload, options) {
10207
+ const table = payload.table_name?.trim();
10208
+ if (!table) {
10209
+ throw new D1SqlCompileError("missing_table", "table_name is required for delete");
10210
+ }
10211
+ const conditions = [...payload.conditions ?? []];
10212
+ if (payload.resource_id !== void 0 && payload.resource_id !== null) {
10213
+ const hasResourceIdFilter = conditions.some((condition) => {
10214
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
10215
+ return column === "resource_id";
10216
+ });
10217
+ const hasIdFilter = conditions.some((condition) => {
10218
+ const column = (condition.column ?? condition.eq_column ?? "").trim();
10219
+ return column === "id";
10220
+ });
10221
+ if (!hasResourceIdFilter && !hasIdFilter) {
10222
+ conditions.unshift({
10223
+ column: "id",
10224
+ operator: "eq",
10225
+ value: payload.resource_id
10226
+ });
10227
+ }
10228
+ }
10229
+ const where = buildWhere(conditions);
10230
+ if (!where.sql) {
10231
+ throw new D1SqlCompileError(
10232
+ "unfiltered_delete",
10233
+ "DELETE requires at least one condition or resource_id on D1 edge-local"
10234
+ );
10235
+ }
10236
+ if (hasPaginationBounds(payload) || payload.sort_by) {
10237
+ if (!hasPaginationBounds(payload)) {
10238
+ throw new D1SqlCompileError(
10239
+ "order_without_bounds",
10240
+ "DELETE with sort_by requires limit/offset or page_size/current_page on D1 edge-local"
10241
+ );
10242
+ }
10243
+ const bounded = boundedRowidInClause(
10244
+ table,
10245
+ where.sql,
10246
+ where.params,
10247
+ {
10248
+ ...payload,
10249
+ conditions
10250
+ },
10251
+ options
10252
+ );
10253
+ const parts2 = [`DELETE FROM ${quoteIdent(table)}`, `WHERE ${bounded.sql}`];
10254
+ if (wantsReturning(payload)) {
10255
+ parts2.push(`RETURNING ${selectClause(payload.columns)}`);
10256
+ }
10257
+ return asSingle(parts2.join(" "), bounded.params);
10258
+ }
10259
+ const parts = [`DELETE FROM ${quoteIdent(table)}`, where.sql];
10260
+ if (wantsReturning(payload)) {
10261
+ parts.push(`RETURNING ${selectClause(payload.columns)}`);
10262
+ }
10263
+ return asSingle(parts.join(" "), where.params);
10264
+ }
10265
+
10266
+ // src/cloudflare/d1/sql-rewrite.ts
10267
+ 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";
10268
+ function mapSqlOutsideLiterals(sql, transform) {
10269
+ let out = "";
10270
+ let buffer = "";
10271
+ let inSingle = false;
10272
+ let inDouble = false;
10273
+ let inBacktick = false;
10274
+ let inBracket = false;
10275
+ let inLineComment = false;
10276
+ let inBlockComment = false;
10277
+ const flushCode = () => {
10278
+ if (buffer) {
10279
+ out += transform(buffer);
10280
+ buffer = "";
10281
+ }
10282
+ };
10283
+ for (let i = 0; i < sql.length; i += 1) {
10284
+ const ch = sql[i];
10285
+ const next = sql[i + 1];
10286
+ if (inLineComment) {
10287
+ out += ch;
10288
+ if (ch === "\n" || ch === "\r") inLineComment = false;
10289
+ continue;
10290
+ }
10291
+ if (inBlockComment) {
10292
+ out += ch;
10293
+ if (ch === "*" && next === "/") {
10294
+ out += next;
10295
+ i += 1;
10296
+ inBlockComment = false;
10297
+ }
10298
+ continue;
10299
+ }
10300
+ if (inSingle) {
10301
+ out += ch;
10302
+ if (ch === "'" && next === "'") {
10303
+ out += next;
10304
+ i += 1;
10305
+ continue;
10306
+ }
10307
+ if (ch === "'") inSingle = false;
10308
+ continue;
10309
+ }
10310
+ if (inDouble) {
10311
+ out += ch;
10312
+ if (ch === '"' && next === '"') {
10313
+ out += next;
10314
+ i += 1;
10315
+ continue;
10316
+ }
10317
+ if (ch === '"') inDouble = false;
10318
+ continue;
10319
+ }
10320
+ if (inBacktick) {
10321
+ out += ch;
10322
+ if (ch === "`" && next === "`") {
10323
+ out += next;
10324
+ i += 1;
10325
+ continue;
10326
+ }
10327
+ if (ch === "`") inBacktick = false;
10328
+ continue;
10329
+ }
10330
+ if (inBracket) {
10331
+ out += ch;
10332
+ if (ch === "]") inBracket = false;
10333
+ continue;
10334
+ }
10335
+ if (ch === "-" && next === "-") {
10336
+ flushCode();
10337
+ out += ch;
10338
+ out += next;
10339
+ i += 1;
10340
+ inLineComment = true;
10341
+ continue;
10342
+ }
10343
+ if (ch === "/" && next === "*") {
10344
+ flushCode();
10345
+ out += ch;
10346
+ out += next;
10347
+ i += 1;
10348
+ inBlockComment = true;
10349
+ continue;
10350
+ }
10351
+ if (ch === "'") {
10352
+ flushCode();
10353
+ out += ch;
10354
+ inSingle = true;
10355
+ continue;
10356
+ }
10357
+ if (ch === '"') {
10358
+ flushCode();
10359
+ out += ch;
10360
+ inDouble = true;
10361
+ continue;
10362
+ }
10363
+ if (ch === "`") {
10364
+ flushCode();
10365
+ out += ch;
10366
+ inBacktick = true;
10367
+ continue;
10368
+ }
10369
+ if (ch === "[") {
10370
+ flushCode();
10371
+ out += ch;
10372
+ inBracket = true;
10373
+ continue;
10374
+ }
10375
+ buffer += ch;
10376
+ }
10377
+ flushCode();
10378
+ return out;
10379
+ }
10380
+ function isIdentChar2(ch) {
10381
+ if (!ch) return false;
10382
+ return /[A-Za-z0-9_]/.test(ch);
10383
+ }
10384
+ function collectLimitOffsetKeywords(sql) {
10385
+ const hits = [];
10386
+ let depth = 0;
10387
+ let statement = 0;
10388
+ let inSingle = false;
10389
+ let inDouble = false;
10390
+ let inBacktick = false;
10391
+ let inBracket = false;
10392
+ let inLineComment = false;
10393
+ let inBlockComment = false;
10394
+ for (let i = 0; i < sql.length; i += 1) {
10395
+ const ch = sql[i];
10396
+ const next = sql[i + 1];
10397
+ if (inLineComment) {
10398
+ if (ch === "\n" || ch === "\r") inLineComment = false;
10399
+ continue;
10400
+ }
10401
+ if (inBlockComment) {
10402
+ if (ch === "*" && next === "/") {
10403
+ i += 1;
10404
+ inBlockComment = false;
10405
+ }
10406
+ continue;
10407
+ }
10408
+ if (inSingle) {
10409
+ if (ch === "'" && next === "'") {
10410
+ i += 1;
10411
+ continue;
10412
+ }
10413
+ if (ch === "'") inSingle = false;
10414
+ continue;
10415
+ }
10416
+ if (inDouble) {
10417
+ if (ch === '"' && next === '"') {
10418
+ i += 1;
10419
+ continue;
10420
+ }
10421
+ if (ch === '"') inDouble = false;
10422
+ continue;
10423
+ }
10424
+ if (inBacktick) {
10425
+ if (ch === "`" && next === "`") {
10426
+ i += 1;
10427
+ continue;
10428
+ }
10429
+ if (ch === "`") inBacktick = false;
10430
+ continue;
10431
+ }
10432
+ if (inBracket) {
10433
+ if (ch === "]") inBracket = false;
10434
+ continue;
10435
+ }
10436
+ if (ch === "-" && next === "-") {
10437
+ inLineComment = true;
10438
+ i += 1;
10439
+ continue;
10440
+ }
10441
+ if (ch === "/" && next === "*") {
10442
+ inBlockComment = true;
10443
+ i += 1;
10444
+ continue;
10445
+ }
10446
+ if (ch === "'") {
10447
+ inSingle = true;
10448
+ continue;
10449
+ }
10450
+ if (ch === '"') {
10451
+ inDouble = true;
10452
+ continue;
10453
+ }
10454
+ if (ch === "`") {
10455
+ inBacktick = true;
10456
+ continue;
10457
+ }
10458
+ if (ch === "[") {
10459
+ inBracket = true;
10460
+ continue;
10461
+ }
10462
+ if (ch === "(") {
10463
+ depth += 1;
10464
+ continue;
10465
+ }
10466
+ if (ch === ")") {
10467
+ depth = Math.max(0, depth - 1);
10468
+ continue;
10469
+ }
10470
+ if (ch === ";" && depth === 0) {
10471
+ statement += 1;
10472
+ continue;
10473
+ }
10474
+ if (!isIdentChar2(ch) || isIdentChar2(sql[i - 1])) {
10475
+ continue;
10476
+ }
10477
+ const rest = sql.slice(i);
10478
+ if (/^LIMIT\b/i.test(rest)) {
10479
+ hits.push({ kind: "limit", start: i, depth, statement });
10480
+ i += 4;
10481
+ continue;
10482
+ }
10483
+ if (/^OFFSET\b/i.test(rest)) {
10484
+ hits.push({ kind: "offset", start: i, depth, statement });
10485
+ i += 5;
10486
+ }
10487
+ }
10488
+ return hits;
10489
+ }
10490
+ function injectLimitBeforeBareOffsets(sql) {
10491
+ const hits = collectLimitOffsetKeywords(sql);
10492
+ if (hits.length === 0) return sql;
10493
+ const injectAt = [];
10494
+ for (const hit of hits) {
10495
+ if (hit.kind !== "offset") continue;
10496
+ let hasLimit = false;
10497
+ for (let i = hits.length - 1; i >= 0; i -= 1) {
10498
+ const prev = hits[i];
10499
+ if (prev.start >= hit.start) continue;
10500
+ if (prev.statement !== hit.statement) continue;
10501
+ if (prev.depth !== hit.depth) continue;
10502
+ if (prev.kind === "limit") {
10503
+ hasLimit = true;
10504
+ break;
10505
+ }
10506
+ if (prev.kind === "offset") {
10507
+ break;
10508
+ }
10509
+ }
10510
+ if (!hasLimit) {
10511
+ injectAt.push(hit.start);
10512
+ }
10513
+ }
10514
+ if (injectAt.length === 0) return sql;
10515
+ let out = sql;
10516
+ for (let i = injectAt.length - 1; i >= 0; i -= 1) {
10517
+ const at = injectAt[i];
10518
+ out = `${out.slice(0, at)}LIMIT -1 ${out.slice(at)}`;
10519
+ }
10520
+ return out;
10521
+ }
10522
+ function rewritePostgresSqlForSqlite(sql) {
10523
+ const castPattern = new RegExp(`::(?:${PG_CAST_TYPES})\\b`, "gi");
10524
+ const withoutCastsAndIlike = mapSqlOutsideLiterals(sql, (chunk) => {
10525
+ let rewritten = chunk.replace(castPattern, "");
10526
+ rewritten = rewritten.replace(/\bILIKE\b/gi, "LIKE");
10527
+ return rewritten;
10528
+ });
10529
+ return injectLimitBeforeBareOffsets(withoutCastsAndIlike);
10530
+ }
10531
+
10532
+ // src/cloudflare/d1/transport.ts
10533
+ function hasPaginationBounds2(payload) {
10534
+ return payload.limit !== void 0 || payload.offset !== void 0 || payload.page_size !== void 0 || payload.current_page !== void 0;
10535
+ }
10536
+ function normalizeSqliteCollation(name) {
10537
+ const raw = String(name ?? "").trim().replace(/^["'`[]|["'`\]]$/g, "");
10538
+ if (!raw) return "BINARY";
10539
+ return raw.toUpperCase();
10540
+ }
10541
+ function findCreateTableColumnListOpen(createSql) {
10542
+ const m = /\bCREATE\s+(?:(?:TEMP|TEMPORARY|VIRTUAL)\s+)?TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?/i.exec(
10543
+ createSql
10544
+ );
10545
+ if (!m) return -1;
10546
+ let i = m.index + m[0].length;
10547
+ let inSingle = false;
10548
+ let inDouble = false;
10549
+ let inBacktick = false;
10550
+ let inBracket = false;
10551
+ while (i < createSql.length) {
10552
+ const ch = createSql[i];
10553
+ if (inSingle) {
10554
+ if (ch === "'" && createSql[i + 1] === "'") {
10555
+ i += 2;
10556
+ continue;
10557
+ }
10558
+ if (ch === "'") inSingle = false;
10559
+ i++;
10560
+ continue;
10561
+ }
10562
+ if (inDouble) {
10563
+ if (ch === '"') inDouble = false;
10564
+ i++;
10565
+ continue;
10566
+ }
10567
+ if (inBacktick) {
10568
+ if (ch === "`") inBacktick = false;
10569
+ i++;
10570
+ continue;
10571
+ }
10572
+ if (inBracket) {
10573
+ if (ch === "]") inBracket = false;
10574
+ i++;
10575
+ continue;
10576
+ }
10577
+ if (ch === "'") {
10578
+ inSingle = true;
10579
+ i++;
10580
+ continue;
10581
+ }
10582
+ if (ch === '"') {
10583
+ inDouble = true;
10584
+ i++;
10585
+ continue;
10586
+ }
10587
+ if (ch === "`") {
10588
+ inBacktick = true;
10589
+ i++;
10590
+ continue;
10591
+ }
10592
+ if (ch === "[") {
10593
+ inBracket = true;
10594
+ i++;
10595
+ continue;
10596
+ }
10597
+ if (ch === "(") return i;
10598
+ i++;
10599
+ }
10600
+ return -1;
10601
+ }
10602
+ function parseColumnCollationFromCreateSql(createSql, columnName) {
10603
+ if (!createSql || !columnName) return null;
10604
+ const listOpen = findCreateTableColumnListOpen(createSql);
10605
+ if (listOpen < 0) return null;
10606
+ const listStart = listOpen + 1;
10607
+ const escaped = columnName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10608
+ const nameRe = new RegExp(
10609
+ `(?:^|[^\\w])(?:"${escaped}"|\`${escaped}\`|\\[${escaped}\\]|${escaped})\\s+`,
10610
+ "i"
10611
+ );
10612
+ const listSlice = createSql.slice(listStart);
10613
+ let nameMatchAbs = -1;
10614
+ let nameMatchLen = 0;
10615
+ {
10616
+ let i2 = 0;
10617
+ let depth2 = 1;
10618
+ let inSingle2 = false;
10619
+ let inDouble2 = false;
10620
+ let inBacktick2 = false;
10621
+ let inBracket2 = false;
10622
+ let segmentStart = 0;
10623
+ const trySegment = (from, to) => {
10624
+ if (nameMatchAbs >= 0) return;
10625
+ const segment = listSlice.slice(from, to);
10626
+ const m = nameRe.exec(segment);
10627
+ if (!m) return;
10628
+ const leading = segment.slice(0, m.index).trim();
10629
+ if (leading.length > 0) return;
10630
+ nameMatchAbs = listStart + from + m.index;
10631
+ nameMatchLen = m[0].length;
10632
+ };
10633
+ while (i2 < listSlice.length && depth2 > 0) {
10634
+ const ch = listSlice[i2];
10635
+ if (inSingle2) {
10636
+ if (ch === "'" && listSlice[i2 + 1] === "'") {
10637
+ i2 += 2;
10638
+ continue;
10639
+ }
10640
+ if (ch === "'") inSingle2 = false;
10641
+ i2++;
10642
+ continue;
10643
+ }
10644
+ if (inDouble2) {
10645
+ if (ch === '"') inDouble2 = false;
10646
+ i2++;
10647
+ continue;
10648
+ }
10649
+ if (inBacktick2) {
10650
+ if (ch === "`") inBacktick2 = false;
10651
+ i2++;
10652
+ continue;
10653
+ }
10654
+ if (inBracket2) {
10655
+ if (ch === "]") inBracket2 = false;
10656
+ i2++;
10657
+ continue;
10658
+ }
10659
+ if (ch === "'") {
10660
+ inSingle2 = true;
10661
+ i2++;
10662
+ continue;
10663
+ }
10664
+ if (ch === '"') {
10665
+ inDouble2 = true;
10666
+ i2++;
10667
+ continue;
10668
+ }
10669
+ if (ch === "`") {
10670
+ inBacktick2 = true;
10671
+ i2++;
10672
+ continue;
10673
+ }
10674
+ if (ch === "[") {
10675
+ inBracket2 = true;
10676
+ i2++;
10677
+ continue;
10678
+ }
10679
+ if (ch === "(") {
10680
+ depth2++;
10681
+ i2++;
10682
+ continue;
10683
+ }
10684
+ if (ch === ")") {
10685
+ depth2--;
10686
+ if (depth2 === 0) {
10687
+ trySegment(segmentStart, i2);
10688
+ break;
10689
+ }
10690
+ i2++;
10691
+ continue;
10692
+ }
10693
+ if (ch === "," && depth2 === 1) {
10694
+ trySegment(segmentStart, i2);
10695
+ segmentStart = i2 + 1;
10696
+ i2++;
10697
+ continue;
10698
+ }
10699
+ i2++;
10700
+ }
10701
+ }
10702
+ if (nameMatchAbs < 0 || nameMatchLen <= 0) return null;
10703
+ const start = nameMatchAbs + nameMatchLen;
10704
+ let i = start;
10705
+ let depth = 0;
10706
+ let inSingle = false;
10707
+ let inDouble = false;
10708
+ let inBacktick = false;
10709
+ let inBracket = false;
10710
+ while (i < createSql.length) {
10711
+ const ch = createSql[i];
10712
+ if (inSingle) {
10713
+ if (ch === "'" && createSql[i + 1] === "'") {
10714
+ i += 2;
10715
+ continue;
10716
+ }
10717
+ if (ch === "'") inSingle = false;
10718
+ i++;
10719
+ continue;
10720
+ }
10721
+ if (inDouble) {
10722
+ if (ch === '"') inDouble = false;
10723
+ i++;
10724
+ continue;
10725
+ }
10726
+ if (inBacktick) {
10727
+ if (ch === "`") inBacktick = false;
10728
+ i++;
10729
+ continue;
10730
+ }
10731
+ if (inBracket) {
10732
+ if (ch === "]") inBracket = false;
10733
+ i++;
10734
+ continue;
10735
+ }
10736
+ if (ch === "'") {
10737
+ inSingle = true;
10738
+ i++;
10739
+ continue;
10740
+ }
10741
+ if (ch === '"') {
10742
+ inDouble = true;
10743
+ i++;
10744
+ continue;
10745
+ }
10746
+ if (ch === "`") {
10747
+ inBacktick = true;
10748
+ i++;
10749
+ continue;
10750
+ }
10751
+ if (ch === "[") {
10752
+ inBracket = true;
10753
+ i++;
10754
+ continue;
10755
+ }
10756
+ if (ch === "(") {
10757
+ depth++;
10758
+ i++;
10759
+ continue;
10760
+ }
10761
+ if (ch === ")") {
10762
+ if (depth === 0) {
10763
+ break;
10764
+ }
10765
+ depth--;
10766
+ i++;
10767
+ continue;
10768
+ }
10769
+ if (ch === "," && depth === 0) {
10770
+ break;
10771
+ }
10772
+ i++;
10773
+ }
10774
+ const colDef = createSql.slice(start, i);
10775
+ const collRe = /\bCOLLATE\s+("([^"]+)"|'([^']+)'|`([^`]+)`|\[([^\]]+)\]|([A-Za-z_][\w$]*))/i;
10776
+ const match = collRe.exec(colDef);
10777
+ if (!match) return null;
10778
+ return match[2] ?? match[3] ?? match[4] ?? match[5] ?? match[6] ?? match[1] ?? null;
10779
+ }
10780
+ async function indexCollationMatchesColumn(d1, table, tableSafe, indexSafe, columnName, session) {
10781
+ const xinfo = await executeD1Query(d1, {
10782
+ query: `PRAGMA index_xinfo("${indexSafe}")`,
10783
+ params: [],
10784
+ ...session
10785
+ });
10786
+ if (!xinfo.ok) {
10787
+ return false;
10788
+ }
10789
+ const xRows = xinfo.rows ?? [];
10790
+ const keyRows = xRows.filter((row) => {
10791
+ const isKey = row.key === 1 || row.key === true || Number(row.key) === 1;
10792
+ if (!isKey) return false;
10793
+ return typeof row.name === "string" && row.name === columnName;
10794
+ });
10795
+ if (keyRows.length === 0) {
10796
+ const byName = xRows.find(
10797
+ (row) => typeof row.name === "string" && row.name === columnName
10798
+ );
10799
+ if (!byName) return false;
10800
+ keyRows.push(byName);
10801
+ }
10802
+ const indexColl = normalizeSqliteCollation(keyRows[0]?.coll);
10803
+ const master = await executeD1Query(d1, {
10804
+ query: `SELECT sql AS create_sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
10805
+ params: [table],
10806
+ ...session
10807
+ });
10808
+ let createSql = "";
10809
+ if (master.ok && Array.isArray(master.rows) && master.rows.length > 0) {
10810
+ createSql = String(
10811
+ master.rows[0]?.create_sql ?? ""
10812
+ );
10813
+ }
10814
+ const columnCollRaw = parseColumnCollationFromCreateSql(createSql, columnName);
10815
+ const columnColl = normalizeSqliteCollation(columnCollRaw);
10816
+ return indexColl === columnColl;
10817
+ }
10818
+ async function resolveD1BoundedIdentityColumn(d1, tableName, session) {
10819
+ const table = tableName.trim();
10820
+ if (!table) {
10821
+ throw new D1SqlCompileError("missing_table", "table_name is required for bounded mutation");
10822
+ }
10823
+ const safe = table.replace(/"/g, '""');
10824
+ const info = await executeD1Query(d1, {
10825
+ query: `PRAGMA table_info("${safe}")`,
10826
+ params: [],
10827
+ ...session
10828
+ });
10829
+ if (!info.ok) {
10830
+ throw new D1SqlCompileError(
10831
+ "bounded_mutation_no_unique_identity",
10832
+ `Unable to introspect table "${table}" for bounded mutation identity: ${info.message}`
10833
+ );
10834
+ }
10835
+ const cols = info.rows.filter(
10836
+ (row) => typeof row?.name === "string" && row.name.length > 0
10837
+ );
10838
+ const colByName = new Map(cols.map((col) => [col.name, col]));
10839
+ const isNotNullColumn = (name) => {
10840
+ const col = colByName.get(name);
10841
+ if (!col) return false;
10842
+ return col.notnull === 1 || col.notnull === true || Number(col.notnull) === 1;
10843
+ };
10844
+ const isIntegerPrimaryKeyType = (col) => {
10845
+ if (typeof col.pk !== "number" || col.pk <= 0) return false;
10846
+ const declared = String(col.type ?? "").trim().toUpperCase();
10847
+ return declared === "INTEGER";
10848
+ };
10849
+ const loadIndexList = async () => {
10850
+ const indexList = await executeD1Query(d1, {
10851
+ query: `PRAGMA index_list("${safe}")`,
10852
+ params: [],
10853
+ ...session
10854
+ });
10855
+ if (!indexList.ok) return null;
10856
+ return indexList.rows;
10857
+ };
10858
+ const isDescendingIntegerPrimaryKeyException = async (colName, indexes) => {
10859
+ if (indexes) {
10860
+ const hasPkOrigin = indexes.some(
10861
+ (index) => String(index.origin ?? "").toLowerCase() === "pk"
10862
+ );
10863
+ if (hasPkOrigin) return true;
10864
+ const originReported = indexes.some(
10865
+ (index) => index.origin !== void 0 && index.origin !== null && String(index.origin).length > 0
10866
+ );
10867
+ if (indexes.length === 0 || originReported) {
10868
+ return false;
10869
+ }
10870
+ }
10871
+ const master = await executeD1Query(d1, {
10872
+ query: `SELECT sql AS create_sql FROM sqlite_master WHERE type = 'table' AND name = ?`,
10873
+ params: [table],
10874
+ ...session
10875
+ });
10876
+ if (!master.ok || !Array.isArray(master.rows) || master.rows.length === 0) {
10877
+ return false;
10878
+ }
10879
+ const createSql = String(
10880
+ master.rows[0]?.create_sql ?? ""
10881
+ );
10882
+ if (!createSql) return false;
10883
+ const escaped = colName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10884
+ const inlineDesc = new RegExp(
10885
+ `(?:^|[^\\w])(?:"${escaped}"|${escaped})\\s+INTEGER\\s+PRIMARY\\s+KEY\\s+DESC\\b`,
10886
+ "i"
10887
+ );
10888
+ const tableDesc = new RegExp(
10889
+ `PRIMARY\\s+KEY\\s*\\(\\s*(?:"${escaped}"|${escaped})\\s+DESC\\b`,
10890
+ "i"
10891
+ );
10892
+ return inlineDesc.test(createSql) || tableDesc.test(createSql);
10893
+ };
10894
+ const pkCols = cols.filter((row) => typeof row.pk === "number" && row.pk > 0).sort((a, b) => (a.pk ?? 0) - (b.pk ?? 0));
10895
+ let indexRows;
10896
+ if (pkCols.length === 1 && pkCols[0]?.name) {
10897
+ if (isIntegerPrimaryKeyType(pkCols[0])) {
10898
+ indexRows = await loadIndexList();
10899
+ const isDescException = await isDescendingIntegerPrimaryKeyException(
10900
+ pkCols[0].name,
10901
+ indexRows
10902
+ );
10903
+ if (!isDescException) {
10904
+ return pkCols[0].name;
10905
+ }
10906
+ } else if (isNotNullColumn(pkCols[0].name)) {
10907
+ indexRows = await loadIndexList();
10908
+ const pkIndex = (indexRows ?? []).find(
10909
+ (index) => String(index.origin ?? "").toLowerCase() === "pk"
10910
+ );
10911
+ if (pkIndex && typeof pkIndex.name === "string" && pkIndex.name) {
10912
+ const indexSafe = pkIndex.name.replace(/"/g, '""');
10913
+ const collMatch = await indexCollationMatchesColumn(
10914
+ d1,
10915
+ table,
10916
+ safe,
10917
+ indexSafe,
10918
+ pkCols[0].name,
10919
+ session
10920
+ );
10921
+ if (collMatch) {
10922
+ return pkCols[0].name;
10923
+ }
10924
+ }
10925
+ }
10926
+ }
10927
+ if (indexRows === void 0) {
10928
+ indexRows = await loadIndexList();
10929
+ }
10930
+ if (indexRows) {
10931
+ for (const index of indexRows) {
10932
+ const unique = index.unique === 1 || index.unique === true || Number(index.unique) === 1;
10933
+ if (!unique || typeof index.name !== "string" || !index.name) continue;
10934
+ const isPartial = index.partial === 1 || index.partial === true || Number(index.partial) === 1;
10935
+ if (isPartial) {
10936
+ continue;
10937
+ }
10938
+ const indexSafe = index.name.replace(/"/g, '""');
10939
+ const indexInfo = await executeD1Query(d1, {
10940
+ query: `PRAGMA index_info("${indexSafe}")`,
10941
+ params: [],
10942
+ ...session
10943
+ });
10944
+ if (!indexInfo.ok) continue;
10945
+ const rawIndexCols = indexInfo.rows ?? [];
10946
+ const hasExpressionTerm = rawIndexCols.some((row) => {
10947
+ const nameOk = typeof row?.name === "string" && row.name.length > 0;
10948
+ if (!nameOk) return true;
10949
+ if (typeof row.cid === "number" && row.cid < 0) return true;
10950
+ return false;
10951
+ });
10952
+ if (hasExpressionTerm || rawIndexCols.length === 0) {
10953
+ continue;
10954
+ }
10955
+ const indexCols = rawIndexCols.filter(
10956
+ (row) => typeof row?.name === "string" && row.name.length > 0
10957
+ );
10958
+ if (indexCols.length === 1 && indexCols[0]?.name) {
10959
+ const identity = indexCols[0].name;
10960
+ if (!isNotNullColumn(identity)) {
10961
+ continue;
10962
+ }
10963
+ const collMatch = await indexCollationMatchesColumn(
10964
+ d1,
10965
+ table,
10966
+ safe,
10967
+ indexSafe,
10968
+ identity,
10969
+ session
10970
+ );
10971
+ if (!collMatch) {
10972
+ continue;
10973
+ }
10974
+ return identity;
10975
+ }
10976
+ }
10977
+ }
10978
+ throw new D1SqlCompileError(
10979
+ "bounded_mutation_no_unique_identity",
10980
+ `Bounded update/delete on "${table}" requires a proven single-column PRIMARY KEY or UNIQUE index`
10981
+ );
10982
+ }
10983
+ async function compileOptionsForBoundedMutation(d1, payload, session) {
10984
+ if (!hasPaginationBounds2(payload) && !payload.sort_by) {
10985
+ return void 0;
10986
+ }
10987
+ if (!hasPaginationBounds2(payload)) {
10988
+ return void 0;
10989
+ }
10990
+ const identityColumn = await resolveD1BoundedIdentityColumn(
10991
+ d1,
10992
+ payload.table_name ?? "",
10993
+ session
10994
+ );
10995
+ return { identityColumn };
10996
+ }
10997
+ function headerValue2(options, name) {
10998
+ const headers = options?.headers;
10999
+ if (!headers) return void 0;
11000
+ const lower = name.toLowerCase();
11001
+ for (const [key, value] of Object.entries(headers)) {
11002
+ if (key.toLowerCase() === lower && value?.trim()) {
11003
+ return value.trim();
11004
+ }
11005
+ }
11006
+ return void 0;
11007
+ }
11008
+ function sessionFromOptions(options, defaults) {
11009
+ return {
11010
+ bookmark: headerValue2(options, "x-athena-d1-bookmark") ?? null,
11011
+ sessionMode: headerValue2(options, "x-athena-d1-session-mode") ?? defaults.defaultSessionMode ?? null
11012
+ };
11013
+ }
11014
+ function resolveStripNulls(payloadStrip, callOptions, defaultValue = true) {
11015
+ if (typeof payloadStrip === "boolean") return payloadStrip;
11016
+ if (typeof callOptions?.stripNulls === "boolean") return callOptions.stripNulls;
11017
+ return defaultValue;
11018
+ }
11019
+ function stripNullPropertiesFromRows(rows) {
11020
+ return rows.map((row) => {
11021
+ if (row == null || typeof row !== "object" || Array.isArray(row)) {
11022
+ return row;
11023
+ }
11024
+ const out = {};
11025
+ for (const [key, value] of Object.entries(row)) {
11026
+ if (value !== null) {
11027
+ out[key] = value;
11028
+ }
11029
+ }
11030
+ return out;
11031
+ });
11032
+ }
11033
+ function maybeStripNullRows(rows, strip) {
11034
+ return strip ? stripNullPropertiesFromRows(rows) : rows;
11035
+ }
11036
+ function successResponse(data, count, raw, bookmark) {
11037
+ const response = {
11038
+ ok: true,
11039
+ status: 200,
11040
+ statusText: "OK",
11041
+ data,
11042
+ count: count ?? null,
11043
+ error: void 0,
11044
+ errorDetails: null,
11045
+ raw
11046
+ };
11047
+ if (bookmark) {
11048
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
11049
+ const rawRecord = raw;
11050
+ rawRecord.bookmark = bookmark;
11051
+ }
11052
+ }
11053
+ return response;
11054
+ }
11055
+ function errorResponse(status, code, message, endpoint, method, hint) {
11056
+ const error = new AthenaGatewayError({
11057
+ code,
11058
+ message,
11059
+ status,
11060
+ endpoint,
11061
+ method,
11062
+ hint
11063
+ });
11064
+ return {
11065
+ ok: false,
11066
+ status,
11067
+ statusText: null,
11068
+ data: null,
11069
+ error: error.message,
11070
+ errorDetails: error.toDetails(),
11071
+ raw: { error: message, code }
11072
+ };
11073
+ }
11074
+ function compileErrorResponse(error, endpoint, method) {
11075
+ if (error instanceof D1SqlCompileError) {
11076
+ return errorResponse(
11077
+ 400,
11078
+ "HTTP_ERROR",
11079
+ error.message,
11080
+ endpoint,
11081
+ method,
11082
+ `D1 SQL compile failed (${error.code})`
11083
+ );
11084
+ }
11085
+ const message = error instanceof Error ? error.message : String(error);
11086
+ return errorResponse(500, "UNKNOWN_ERROR", message, endpoint, method);
11087
+ }
11088
+ function createCloudflareD1GatewayTransport(options) {
11089
+ const { d1 } = options;
11090
+ async function runCompiled(compiled, callOptions, endpoint, method, mapResult, stripNulls = true) {
11091
+ try {
11092
+ const session = sessionFromOptions(callOptions, options);
11093
+ if (compiled.statements && compiled.statements.length > 1) {
11094
+ const batch = await executeD1Batch(d1, {
11095
+ statements: compiled.statements.map((statement) => ({
11096
+ query: statement.sql,
11097
+ params: statement.params
11098
+ })),
11099
+ ...session
11100
+ });
11101
+ if (!batch.ok) {
11102
+ return errorResponse(400, "HTTP_ERROR", batch.message, endpoint, method);
11103
+ }
11104
+ const rows2 = maybeStripNullRows(
11105
+ batch.results.flatMap(
11106
+ (item) => Array.isArray(item.results) ? item.results : []
11107
+ ),
11108
+ stripNulls
11109
+ );
11110
+ const changes = batch.results.reduce((sum2, item) => {
11111
+ const meta = item?.meta;
11112
+ const n = meta && typeof meta === "object" && typeof meta.changes === "number" ? meta.changes : 0;
11113
+ return sum2 + n;
11114
+ }, 0);
11115
+ const count = rows2.length > 0 ? rows2.length : changes;
11116
+ const mapped2 = mapResult?.(rows2, count) ?? {
11117
+ data: rows2,
11118
+ count
11119
+ };
11120
+ return successResponse(mapped2.data, mapped2.count, batch, batch.bookmark);
11121
+ }
11122
+ const result = await executeD1Query(d1, {
11123
+ query: compiled.sql,
11124
+ params: compiled.params,
11125
+ ...session
11126
+ });
11127
+ if (!result.ok) {
11128
+ return errorResponse(400, "HTTP_ERROR", result.message, endpoint, method);
11129
+ }
11130
+ const rows = maybeStripNullRows(result.rows, stripNulls);
11131
+ const mapped = mapResult?.(rows, result.count) ?? {
11132
+ data: rows,
11133
+ count: result.count
11134
+ };
11135
+ return successResponse(mapped.data, mapped.count, result, result.bookmark);
11136
+ } catch (error) {
11137
+ const message = error instanceof Error ? error.message : String(error);
11138
+ return errorResponse(500, "UNKNOWN_ERROR", message, endpoint, method);
11139
+ }
11140
+ }
11141
+ return {
11142
+ baseUrl: CLOUDFLARE_EDGE_BASE_URL,
11143
+ buildHeaders(callOptions) {
11144
+ return { ...callOptions?.headers ?? {} };
11145
+ },
11146
+ async resolveCallOptions(callOptions) {
11147
+ return callOptions;
11148
+ },
11149
+ async verifyConnection(connectionOptions) {
11150
+ const baseUrl = CLOUDFLARE_EDGE_BASE_URL;
11151
+ try {
11152
+ const result = await executeD1Query(d1, { query: "SELECT 1 AS ok" });
11153
+ if (!result.ok) {
11154
+ return {
11155
+ ok: false,
11156
+ reachable: false,
11157
+ status: 500,
11158
+ statusText: null,
11159
+ baseUrl,
11160
+ url: `${baseUrl}/d1`,
11161
+ error: result.message,
11162
+ errorDetails: null,
11163
+ raw: result
11164
+ };
11165
+ }
11166
+ return {
11167
+ ok: true,
11168
+ reachable: true,
11169
+ status: 200,
11170
+ statusText: "OK",
11171
+ baseUrl,
11172
+ url: `${baseUrl}/d1`,
11173
+ error: void 0,
11174
+ errorDetails: null,
11175
+ raw: result
11176
+ };
11177
+ } catch (error) {
11178
+ const message = error instanceof Error ? error.message : String(error);
11179
+ return {
11180
+ ok: false,
11181
+ reachable: false,
11182
+ status: 0,
11183
+ statusText: null,
11184
+ baseUrl,
11185
+ url: `${baseUrl}/d1`,
11186
+ error: message,
11187
+ errorDetails: null,
11188
+ raw: null
11189
+ };
11190
+ }
11191
+ },
11192
+ async fetchGateway(payload, callOptions) {
11193
+ try {
11194
+ if (payload && typeof payload === "object" && "operation" in payload) {
11195
+ return errorResponse(
11196
+ 400,
11197
+ "HTTP_ERROR",
11198
+ "Direct AST operation payloads are unsupported on D1 edge-local",
11199
+ "/gateway/fetch",
11200
+ "POST"
11201
+ );
11202
+ }
11203
+ const compiled = compileD1Fetch(payload);
11204
+ const stripNulls = resolveStripNulls(payload.strip_nulls, callOptions, true);
11205
+ if (payload.head === true) {
11206
+ return runCompiled(
11207
+ compiled,
11208
+ callOptions,
11209
+ "/gateway/fetch",
11210
+ "POST",
11211
+ (rows) => ({ data: [], count: extractAthenaCount(rows) }),
11212
+ // COUNT rows are meta, not user-facing object rows
11213
+ false
11214
+ );
11215
+ }
11216
+ const wantsTotalCount = payload.count === "exact" || payload.count === "planned" || payload.count === "estimated";
11217
+ if (wantsTotalCount) {
11218
+ const session = sessionFromOptions(callOptions, options);
11219
+ const countCompiled = compileD1Count(payload);
11220
+ const batch = await executeD1Batch(d1, {
11221
+ statements: [
11222
+ {
11223
+ query: compiled.sql,
11224
+ params: compiled.params
11225
+ },
11226
+ {
11227
+ query: countCompiled.sql,
11228
+ params: countCompiled.params
11229
+ }
11230
+ ],
11231
+ ...session
11232
+ });
11233
+ if (!batch.ok) {
11234
+ return errorResponse(400, "HTTP_ERROR", batch.message, "/gateway/fetch", "POST");
11235
+ }
11236
+ const dataItem = batch.results[0];
11237
+ const countItem = batch.results[1];
11238
+ if (!dataItem || dataItem.success === false) {
11239
+ const message = dataItem && typeof dataItem.error === "string" && dataItem.error.trim() ? dataItem.error : "D1 page query failed";
11240
+ return errorResponse(400, "HTTP_ERROR", message, "/gateway/fetch", "POST");
11241
+ }
11242
+ if (!countItem || countItem.success === false) {
11243
+ const message = countItem && typeof countItem.error === "string" && countItem.error.trim() ? countItem.error : "D1 count query failed";
11244
+ return errorResponse(400, "HTTP_ERROR", message, "/gateway/fetch", "POST");
11245
+ }
11246
+ const dataRows = Array.isArray(dataItem.results) ? dataItem.results : [];
11247
+ const countRows = Array.isArray(countItem.results) ? countItem.results : [];
11248
+ const total = extractAthenaCount(countRows);
11249
+ const rows = maybeStripNullRows(dataRows, stripNulls);
11250
+ return successResponse(
11251
+ rows,
11252
+ total,
11253
+ { data: dataItem, count: countItem, batch },
11254
+ batch.bookmark
11255
+ );
11256
+ }
11257
+ return runCompiled(compiled, callOptions, "/gateway/fetch", "POST", void 0, stripNulls);
11258
+ } catch (error) {
11259
+ return compileErrorResponse(error, "/gateway/fetch", "POST");
11260
+ }
11261
+ },
11262
+ async insertGateway(payload, callOptions) {
11263
+ try {
11264
+ const compiled = compileD1Insert(payload);
11265
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
11266
+ return runCompiled(compiled, callOptions, "/gateway/insert", "PUT", void 0, stripNulls);
11267
+ } catch (error) {
11268
+ return compileErrorResponse(error, "/gateway/insert", "PUT");
11269
+ }
11270
+ },
11271
+ async updateGateway(payload, callOptions) {
11272
+ try {
11273
+ const session = sessionFromOptions(callOptions, options);
11274
+ const compileOptions = await compileOptionsForBoundedMutation(d1, payload, session);
11275
+ const compiled = compileD1Update(payload, compileOptions);
11276
+ const stripNulls = resolveStripNulls(payload.strip_nulls, callOptions, true);
11277
+ return runCompiled(compiled, callOptions, "/gateway/update", "POST", void 0, stripNulls);
11278
+ } catch (error) {
11279
+ return compileErrorResponse(error, "/gateway/update", "POST");
11280
+ }
11281
+ },
11282
+ async deleteGateway(payload, callOptions) {
11283
+ try {
11284
+ const session = sessionFromOptions(callOptions, options);
11285
+ const compileOptions = await compileOptionsForBoundedMutation(d1, payload, session);
11286
+ const compiled = compileD1Delete(payload, compileOptions);
11287
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
11288
+ return runCompiled(compiled, callOptions, "/gateway/delete", "DELETE", void 0, stripNulls);
11289
+ } catch (error) {
11290
+ return compileErrorResponse(error, "/gateway/delete", "DELETE");
11291
+ }
11292
+ },
11293
+ async rpcGateway(payload, callOptions) {
11294
+ return errorResponse(
11295
+ 400,
11296
+ "HTTP_ERROR",
11297
+ "RPC is unsupported on D1 edge-local mode",
11298
+ "/gateway/rpc",
11299
+ "POST",
11300
+ "Use flat CRUD or raw query SQL instead"
11301
+ );
11302
+ },
11303
+ async queryGateway(payload, callOptions) {
11304
+ try {
11305
+ const params = payload.params ?? callOptions?.params;
11306
+ const session = sessionFromOptions(callOptions, options);
11307
+ const query = rewritePostgresSqlForSqlite(payload.query);
11308
+ const result = await executeD1Query(d1, {
11309
+ query,
11310
+ params: Array.isArray(params) ? params : [],
11311
+ ...session
11312
+ });
11313
+ if (!result.ok) {
11314
+ return errorResponse(400, "HTTP_ERROR", result.message, "/gateway/query", "POST");
11315
+ }
11316
+ const stripNulls = resolveStripNulls(void 0, callOptions, true);
11317
+ const rows = maybeStripNullRows(result.rows, stripNulls);
11318
+ return successResponse(
11319
+ rows,
11320
+ result.count,
11321
+ { ...result, query },
11322
+ result.bookmark
11323
+ );
11324
+ } catch (error) {
11325
+ const message = error instanceof Error ? error.message : String(error);
11326
+ return errorResponse(500, "UNKNOWN_ERROR", message, "/gateway/query", "POST");
11327
+ }
11328
+ }
11329
+ };
11330
+ }
11331
+
11332
+ // src/config/errors.ts
11333
+ var AthenaConfigurationError = class extends Error {
11334
+ code;
11335
+ service;
11336
+ constructor(code, message, service) {
11337
+ super(message);
11338
+ this.name = "AthenaConfigurationError";
11339
+ this.code = code;
11340
+ this.service = service;
11341
+ }
11342
+ };
11343
+
11344
+ // src/cloudflare/execution-mode.ts
11345
+ var ATHENA_EXECUTION_MODE_ENV_KEY = "ATHENA_EXECUTION_MODE";
11346
+ var ATHENA_EXECUTION_PREFER_ENV_KEY = "ATHENA_EXECUTION_PREFER";
11347
+ var MODE_ALIASES = {
11348
+ gateway: "gateway",
11349
+ server: "gateway",
11350
+ remote: "gateway",
11351
+ http: "gateway",
11352
+ edge: "edge",
11353
+ cloudflare: "edge",
11354
+ "cloudflare-edge": "edge",
11355
+ d1: "edge",
11356
+ local: "edge",
11357
+ auto: "auto"
11358
+ };
11359
+ function normalizeOptional(value) {
11360
+ const trimmed = value?.trim();
11361
+ return trimmed || void 0;
11362
+ }
11363
+ function normalizeModeString(value) {
11364
+ if (value == null) return void 0;
11365
+ const key = value.trim().toLowerCase();
11366
+ if (!key) return void 0;
11367
+ const mapped = MODE_ALIASES[key];
11368
+ if (!mapped) {
11369
+ throw new AthenaConfigurationError(
11370
+ "ATHENA_NO_SERVICE_CONFIGURED",
11371
+ `Unknown Athena execution mode "${value}". Use gateway | edge | auto (aliases: server, remote, cloudflare, d1).`,
11372
+ "db"
11373
+ );
11374
+ }
11375
+ return mapped;
11376
+ }
11377
+ function isD1Binding(value) {
11378
+ return Boolean(
11379
+ value && typeof value === "object" && typeof value.prepare === "function"
11380
+ );
11381
+ }
11382
+ var GATEWAY_URL_ENV_KEYS = [
11383
+ "ATHENA_URL",
11384
+ "NEXT_PUBLIC_ATHENA_URL",
11385
+ "ATHENA_DB_URL",
11386
+ "ATHENA_GATEWAY_URL",
11387
+ "NEXT_PUBLIC_ATHENA_DB_API_URL"
11388
+ ];
11389
+ function resolveGatewayUrl(url, env) {
11390
+ if (normalizeOptional(url)) {
11391
+ return normalizeOptional(url);
11392
+ }
11393
+ for (const key of GATEWAY_URL_ENV_KEYS) {
11394
+ const value = normalizeOptional(env[key]);
11395
+ if (value) return value;
11396
+ }
11397
+ return void 0;
11398
+ }
11399
+ function resolvePrefer(prefer, env) {
11400
+ const raw = normalizeOptional(typeof prefer === "string" ? prefer : prefer ?? void 0) ?? normalizeOptional(env[ATHENA_EXECUTION_PREFER_ENV_KEY]) ?? "edge";
11401
+ const key = raw.toLowerCase();
11402
+ if (key === "gateway" || key === "server" || key === "remote" || key === "http") {
11403
+ return "gateway";
11404
+ }
11405
+ if (key === "edge" || key === "d1" || key === "cloudflare" || key === "local") {
11406
+ return "edge";
11407
+ }
11408
+ throw new AthenaConfigurationError(
11409
+ "ATHENA_NO_SERVICE_CONFIGURED",
11410
+ `Unknown Athena execution prefer "${raw}". Use edge | gateway.`,
11411
+ "db"
11412
+ );
11413
+ }
11414
+ function resolveAthenaExecutionMode(input = {}) {
11415
+ const env = input.env ?? {};
11416
+ const fromEnv = normalizeModeString(env[ATHENA_EXECUTION_MODE_ENV_KEY]);
11417
+ const requested = normalizeModeString(input.mode) ?? fromEnv ?? "auto";
11418
+ const url = resolveGatewayUrl(input.url, env);
11419
+ const hasD1 = isD1Binding(input.d1);
11420
+ const hasGateway = Boolean(url);
11421
+ if (requested === "gateway") {
11422
+ if (!hasGateway) {
11423
+ throw new AthenaConfigurationError(
11424
+ "ATHENA_NO_SERVICE_CONFIGURED",
11425
+ 'Athena execution mode is "gateway" but no url / ATHENA_URL / ATHENA_DB_URL / ATHENA_GATEWAY_URL was provided.',
11426
+ "db"
11427
+ );
11428
+ }
11429
+ return "gateway";
11430
+ }
11431
+ if (requested === "edge") {
11432
+ if (!hasD1) {
11433
+ throw new AthenaConfigurationError(
11434
+ "ATHENA_NO_SERVICE_CONFIGURED",
11435
+ 'Athena execution mode is "edge" but no D1 binding was provided (db.d1 / config.d1 / env.DB).',
11436
+ "db"
11437
+ );
11438
+ }
11439
+ return "edge";
11440
+ }
11441
+ if (hasD1 && hasGateway) {
11442
+ return resolvePrefer(input.prefer, env);
11443
+ }
11444
+ if (hasD1) return "edge";
11445
+ if (hasGateway) return "gateway";
11446
+ throw new AthenaConfigurationError(
11447
+ "ATHENA_NO_SERVICE_CONFIGURED",
11448
+ '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).',
11449
+ "db"
11450
+ );
11451
+ }
11452
+
11453
+ // src/cloudflare/r2/storage.ts
11454
+ function normalizePrefix(prefix) {
11455
+ if (!prefix?.trim()) return "";
11456
+ const normalized = prefix.replace(/^\/+/, "").replace(/\/?$/, "/");
11457
+ if (normalized.includes("\0")) {
11458
+ throw new Error("storage prefix must not contain null bytes");
11459
+ }
11460
+ if (normalized.split("/").some((segment) => segment === "..")) {
11461
+ throw new Error('storage prefix must not contain ".." path segments');
11462
+ }
11463
+ return normalized;
11464
+ }
11465
+ function assertSafeObjectKey(key) {
11466
+ if (typeof key !== "string" || !key.trim()) {
11467
+ throw new Error("Object key is required");
11468
+ }
11469
+ if (key.includes("\0")) {
11470
+ throw new Error("Object key must not contain null bytes");
11471
+ }
11472
+ const cleaned = key.replace(/^\/+/, "");
11473
+ if (!cleaned) {
11474
+ throw new Error("Object key is required");
11475
+ }
11476
+ const segments = cleaned.split("/");
11477
+ if (segments.some((segment) => segment === "..")) {
11478
+ throw new Error('Object key must not contain ".." path segments');
11479
+ }
11480
+ return cleaned;
11481
+ }
11482
+ function joinKey(prefix, key) {
11483
+ return `${prefix}${assertSafeObjectKey(key)}`;
11484
+ }
11485
+ function toLogicalKey(prefix, physicalKey) {
11486
+ if (!prefix) return physicalKey;
11487
+ if (physicalKey.startsWith(prefix)) {
11488
+ return physicalKey.slice(prefix.length);
11489
+ }
11490
+ return physicalKey;
11491
+ }
11492
+ function toPhysicalKey(prefix, key) {
11493
+ return joinKey(prefix, key);
11494
+ }
11495
+ function unsupported(method) {
11496
+ throw new Error(
11497
+ `storage.${method} is not available in Cloudflare edge-local R2 object mode. Only putObject / getObject / deleteObject / listObjects are supported (L3a).`
11498
+ );
11499
+ }
11500
+ function createCloudflareR2StorageModule(options) {
11501
+ const prefix = normalizePrefix(options.prefix);
11502
+ const { r2 } = options;
11503
+ const putObject = async (input) => {
11504
+ const logical = assertSafeObjectKey(input.key);
11505
+ const physical = toPhysicalKey(prefix, logical);
11506
+ await r2.put(physical, input.body, {
11507
+ httpMetadata: input.contentType ? { contentType: input.contentType } : void 0,
11508
+ customMetadata: input.metadata
11509
+ });
11510
+ return { key: logical };
11511
+ };
11512
+ const getObject = async (input) => {
11513
+ const logical = assertSafeObjectKey(input.key);
11514
+ const physical = toPhysicalKey(prefix, logical);
11515
+ const object = await r2.get(physical);
11516
+ if (!object) return null;
11517
+ return {
11518
+ key: toLogicalKey(prefix, object.key),
11519
+ size: object.size,
11520
+ contentType: object.httpMetadata?.contentType,
11521
+ body: object
11522
+ };
11523
+ };
11524
+ const deleteObject = async (input) => {
11525
+ const logicalKeys = (Array.isArray(input.key) ? input.key : [input.key]).map(
11526
+ (key) => assertSafeObjectKey(key)
11527
+ );
11528
+ const physicalKeys = logicalKeys.map((key) => toPhysicalKey(prefix, key));
11529
+ await r2.delete(physicalKeys.length === 1 ? physicalKeys[0] : physicalKeys);
11530
+ return { deleted: logicalKeys };
11531
+ };
11532
+ const listObjects = async (input) => {
11533
+ const relative = input?.prefix?.trim() ? assertSafeObjectKey(input.prefix) : "";
11534
+ const listPrefix = `${prefix}${relative}`;
11535
+ const listed = await r2.list({
11536
+ prefix: listPrefix || void 0,
11537
+ limit: input?.limit,
11538
+ cursor: input?.cursor
11539
+ });
11540
+ return {
11541
+ objects: listed.objects.map((object) => ({
11542
+ key: toLogicalKey(prefix, object.key),
11543
+ size: object.size,
11544
+ etag: object.etag,
11545
+ uploaded: object.uploaded
11546
+ })),
11547
+ truncated: listed.truncated,
11548
+ cursor: listed.cursor
11549
+ };
11550
+ };
11551
+ const base = {
11552
+ putObject,
11553
+ getObject,
11554
+ deleteObject,
11555
+ listObjects
11556
+ };
11557
+ return new Proxy(base, {
11558
+ get(target, property, receiver) {
11559
+ if (property in target) {
11560
+ return Reflect.get(target, property, receiver);
11561
+ }
11562
+ if (typeof property === "string") {
11563
+ return (...args) => {
11564
+ return unsupported(property);
11565
+ };
11566
+ }
11567
+ return void 0;
11568
+ }
11569
+ });
11570
+ }
11571
+
11572
+ // src/billing/module.ts
11573
+ var SDK_NAME5 = "xylex-group/athena-billing";
11574
+ var SDK_HEADER_VALUE4 = buildSdkHeaderValue(SDK_NAME5);
11575
+ var AthenaBillingError = class extends Error {
11576
+ status;
11577
+ endpoint;
11578
+ method;
11579
+ body;
11580
+ constructor(input) {
11581
+ super(input.message);
11582
+ this.name = "AthenaBillingError";
11583
+ this.status = input.status;
11584
+ this.endpoint = input.endpoint;
11585
+ this.method = input.method;
11586
+ this.body = input.body;
11587
+ }
11588
+ };
11589
+ function withPathParam2(path, name, value) {
11590
+ return path.replace(`{${name}}`, encodeURIComponent(value));
11591
+ }
11592
+ function appendQuery3(path, query) {
11593
+ if (!query) return path;
11594
+ const params = new URLSearchParams();
11595
+ for (const [key, value] of Object.entries(query)) {
11596
+ if (value === void 0 || value === null) continue;
11597
+ params.set(key, String(value));
11598
+ }
11599
+ const serialized = params.toString();
11600
+ return serialized ? `${path}?${serialized}` : path;
11601
+ }
11602
+ function connectionQuery(input) {
11603
+ const query = {
11604
+ connectionId: input.connectionId
11605
+ };
11606
+ if (input.clientName) query.clientName = input.clientName;
11607
+ if ("cursor" in input && input.cursor) query.cursor = input.cursor;
11608
+ if ("source" in input && input.source) query.source = input.source;
11609
+ if ("limit" in input && input.limit !== void 0) query.limit = String(input.limit);
11610
+ if ("offset" in input && input.offset !== void 0) query.offset = String(input.offset);
11611
+ return query;
11612
+ }
11613
+ function parseEnvelopeData(body) {
11614
+ if (body && typeof body === "object" && "data" in body) {
11615
+ return body.data;
11616
+ }
11617
+ return body;
11618
+ }
11619
+ function createBillingModule(config) {
11620
+ const baseUrl = normalizeAthenaGatewayBaseUrl(config.baseUrl, {
11621
+ label: "Athena billing base URL"
11622
+ });
11623
+ const fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);
11624
+ async function call(method, path, body, options, responseType = "json") {
11625
+ const headers = buildAthenaRequestHeaders({
11626
+ profile: "gateway",
11627
+ sdkHeaderValue: SDK_HEADER_VALUE4,
11628
+ apiKey: options?.apiKey ?? config.apiKey,
11629
+ client: config.client,
11630
+ configHeaders: {
11631
+ ...config.headers ?? {}
11632
+ },
11633
+ callHeaders: options?.headers,
11634
+ contentType: "application/json"
11635
+ });
11636
+ let requestBody;
11637
+ if (body !== void 0 && body !== null) {
11638
+ if (typeof body === "string" || body instanceof Blob || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof FormData || body instanceof URLSearchParams) {
11639
+ requestBody = body;
11640
+ } else {
11641
+ requestBody = JSON.stringify(body);
11642
+ if (!hasHeaderIgnoreCase(headers, "Content-Type")) {
11643
+ headers["Content-Type"] = "application/json";
11644
+ }
11645
+ }
11646
+ }
11647
+ const targetUrl = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
11648
+ const response = await fetchImpl(targetUrl, {
11649
+ method,
11650
+ headers,
11651
+ body: requestBody,
11652
+ signal: options?.signal
11653
+ });
11654
+ if (responseType === "text") {
11655
+ const text = await response.text();
11656
+ if (!response.ok) {
11657
+ throw new AthenaBillingError({
11658
+ message: `Billing request failed (${response.status})`,
11659
+ status: response.status,
11660
+ endpoint: path,
11661
+ method,
11662
+ body: text
11663
+ });
11664
+ }
11665
+ return text;
11666
+ }
11667
+ const rawText = await response.text();
11668
+ let parsed = rawText;
11669
+ if (rawText) {
11670
+ try {
11671
+ parsed = JSON.parse(rawText);
11672
+ } catch {
11673
+ parsed = rawText;
11674
+ }
11675
+ } else {
11676
+ parsed = null;
11677
+ }
11678
+ if (!response.ok) {
11679
+ const message = parsed && typeof parsed === "object" && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `Billing request failed (${response.status})`;
11680
+ throw new AthenaBillingError({
11681
+ message,
11682
+ status: response.status,
11683
+ endpoint: path,
11684
+ method,
11685
+ body: parsed
11686
+ });
11687
+ }
11688
+ return parseEnvelopeData(parsed);
11689
+ }
11690
+ return {
11691
+ getCapabilities(input, options) {
11692
+ return call(
11693
+ "GET",
11694
+ appendQuery3("/billing/v1/capabilities", connectionQuery(input)),
11695
+ void 0,
11696
+ options
11697
+ );
11698
+ },
11699
+ createCheckout(body, options) {
11700
+ return call("POST", "/billing/v1/checkouts", body, options);
11701
+ },
11702
+ listProducts(input, options) {
11703
+ return call(
11704
+ "GET",
11705
+ appendQuery3("/billing/v1/products", connectionQuery(input)),
11706
+ void 0,
11707
+ options
11708
+ );
11709
+ },
11710
+ listPrices(input, options) {
11711
+ return call(
11712
+ "GET",
11713
+ appendQuery3("/billing/v1/prices", {
11714
+ ...connectionQuery(input),
11715
+ ...input.productId ? { productId: input.productId } : {}
11716
+ }),
11717
+ void 0,
11718
+ options
11719
+ );
11720
+ },
11721
+ listCustomers(input, options) {
11722
+ return call(
11723
+ "GET",
11724
+ appendQuery3("/billing/v1/customers", connectionQuery(input)),
11725
+ void 0,
11726
+ options
11727
+ );
11728
+ },
11729
+ createCustomer(input, options) {
11730
+ return call(
11731
+ "POST",
11732
+ "/billing/v1/customers",
11733
+ {
11734
+ connectionId: input.connectionId,
11735
+ clientName: input.clientName,
11736
+ email: input.email,
11737
+ name: input.name,
11738
+ metadata: input.metadata ?? {},
11739
+ idempotencyKey: input.idempotencyKey
11740
+ },
11741
+ options
11742
+ );
11743
+ },
9086
11744
  getCustomer(id, input, options) {
9087
11745
  return call(
9088
11746
  "GET",
@@ -9507,18 +12165,6 @@ function createBillingModule(config) {
9507
12165
  };
9508
12166
  }
9509
12167
 
9510
- // src/config/errors.ts
9511
- var AthenaConfigurationError = class extends Error {
9512
- code;
9513
- service;
9514
- constructor(code, message, service) {
9515
- super(message);
9516
- this.name = "AthenaConfigurationError";
9517
- this.code = code;
9518
- this.service = service;
9519
- }
9520
- };
9521
-
9522
12168
  // src/context/merge.ts
9523
12169
  function mergeAthenaRequestContexts(base, override) {
9524
12170
  if (!base && !override) return void 0;
@@ -9532,6 +12178,82 @@ function mergeAthenaRequestContexts(base, override) {
9532
12178
  };
9533
12179
  }
9534
12180
 
12181
+ // src/diagnostics.ts
12182
+ function readProcessEnv2() {
12183
+ try {
12184
+ return globalThis.process?.env ?? {};
12185
+ } catch {
12186
+ return {};
12187
+ }
12188
+ }
12189
+ function isTruthyEnv(value) {
12190
+ if (!value) return false;
12191
+ const normalized = value.trim().toLowerCase();
12192
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
12193
+ }
12194
+ function isQuietAthenaDiagnosticsEnvironment(env = readProcessEnv2()) {
12195
+ const nodeEnv = env.NODE_ENV?.trim().toLowerCase();
12196
+ if (nodeEnv === "production") {
12197
+ return true;
12198
+ }
12199
+ if (isTruthyEnv(env.OPENNEXT_BUILD)) {
12200
+ return true;
12201
+ }
12202
+ const nextPhase = env.NEXT_PHASE?.trim();
12203
+ if (nextPhase === "phase-production-build") {
12204
+ return true;
12205
+ }
12206
+ if (isTruthyEnv(env.CI) && nodeEnv !== "test") {
12207
+ if (nodeEnv === "production" || isTruthyEnv(env.OPENNEXT_BUILD)) {
12208
+ return true;
12209
+ }
12210
+ }
12211
+ return false;
12212
+ }
12213
+ function resolveBooleanFlag(explicit, mode, quiet) {
12214
+ if (typeof explicit === "boolean") {
12215
+ return explicit;
12216
+ }
12217
+ if (mode === true) {
12218
+ return true;
12219
+ }
12220
+ if (mode === false) {
12221
+ return false;
12222
+ }
12223
+ if (mode === "auto") {
12224
+ return false;
12225
+ }
12226
+ return false;
12227
+ }
12228
+ function resolveAthenaClientDiagnostics(input) {
12229
+ const env = input.env ?? readProcessEnv2();
12230
+ const quiet = isQuietAthenaDiagnosticsEnvironment(env);
12231
+ const mode = input.diagnostics;
12232
+ const effectiveMode = mode === "auto" && quiet ? false : mode;
12233
+ const debugAst = resolveBooleanFlag(input.debugAst, effectiveMode);
12234
+ const findManyAst = resolveBooleanFlag(input.findManyAst, effectiveMode);
12235
+ let traceQueries;
12236
+ if (input.traceQueries !== void 0) {
12237
+ if (typeof input.traceQueries === "boolean") {
12238
+ traceQueries = input.traceQueries;
12239
+ } else if (effectiveMode === false || mode === "auto" && quiet) {
12240
+ const enabled = input.traceQueries.enabled;
12241
+ traceQueries = typeof enabled === "boolean" ? enabled ? input.traceQueries : false : false;
12242
+ } else {
12243
+ traceQueries = input.traceQueries;
12244
+ }
12245
+ } else if (effectiveMode === true) {
12246
+ traceQueries = true;
12247
+ } else {
12248
+ traceQueries = false;
12249
+ }
12250
+ return {
12251
+ debugAst,
12252
+ findManyAst,
12253
+ traceQueries
12254
+ };
12255
+ }
12256
+
9535
12257
  // src/v3-client.ts
9536
12258
  var ENV_URL_KEYS = ["ATHENA_URL", "NEXT_PUBLIC_ATHENA_URL"];
9537
12259
  var ENV_DB_URL_KEYS = ["ATHENA_DB_URL", "ATHENA_GATEWAY_URL", "NEXT_PUBLIC_ATHENA_DB_API_URL"];
@@ -9540,7 +12262,13 @@ var ENV_CHAT_URL_KEYS = ["ATHENA_CHAT_URL", "NEXT_PUBLIC_ATHENA_CHAT_URL"];
9540
12262
  var ENV_CHAT_WS_URL_KEYS = ["ATHENA_CHAT_WS_URL", "NEXT_PUBLIC_ATHENA_CHAT_WS_URL"];
9541
12263
  var ENV_STORAGE_URL_KEYS = ["ATHENA_STORAGE_URL", "NEXT_PUBLIC_ATHENA_STORAGE_URL"];
9542
12264
  var ENV_KEY_KEYS = ["ATHENA_API_KEY", "NEXT_PUBLIC_ATHENA_API_KEY", "ATHENA_GATEWAY_API_KEY", "X_API_KEY"];
9543
- var ENV_CLIENT_KEYS = ["ATHENA_CLIENT", "NEXT_PUBLIC_ATHENA_CLIENT"];
12265
+ var ENV_CLIENT_KEYS = [
12266
+ "ATHENA_CLIENT",
12267
+ "ATHENA_GATEWAY_CLIENT",
12268
+ "ATHENA_GENERATOR_CLIENT",
12269
+ "NEXT_PUBLIC_ATHENA_CLIENT",
12270
+ "NEXT_PUBLIC_ATHENA_GATEWAY_CLIENT"
12271
+ ];
9544
12272
  var MISSING_DB_SENTINEL = "https://athena.invalid/db";
9545
12273
  function readFirstEnv(env, keys) {
9546
12274
  for (const key of keys) {
@@ -9549,14 +12277,30 @@ function readFirstEnv(env, keys) {
9549
12277
  }
9550
12278
  return void 0;
9551
12279
  }
9552
- function normalizeOptional(value) {
12280
+ function readFirstEnvHttpUrl(env, keys) {
12281
+ for (const key of keys) {
12282
+ const value = env?.[key]?.trim();
12283
+ if (value && isAbsoluteHttpUrl(value)) return value;
12284
+ }
12285
+ return void 0;
12286
+ }
12287
+ function normalizeOptional2(value) {
9553
12288
  const normalized = value?.trim();
9554
12289
  return normalized || void 0;
9555
12290
  }
12291
+ function isAbsoluteHttpUrl(value) {
12292
+ try {
12293
+ const url = new URL(value);
12294
+ return url.protocol === "http:" || url.protocol === "https:";
12295
+ } catch {
12296
+ return false;
12297
+ }
12298
+ }
9556
12299
  function appendPath(baseUrl, path) {
9557
12300
  return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
9558
12301
  }
9559
12302
  function toWebSocketUrl(baseUrl) {
12303
+ if (!isAbsoluteHttpUrl(baseUrl)) return void 0;
9560
12304
  const url = new URL(baseUrl);
9561
12305
  url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
9562
12306
  url.pathname = `${url.pathname.replace(/\/+$/, "")}/wss/gateway`;
@@ -9566,11 +12310,11 @@ function toWebSocketUrl(baseUrl) {
9566
12310
  }
9567
12311
  function resolveCore(config) {
9568
12312
  const env = config.env;
9569
- const explicitRoot = normalizeOptional(config.url);
9570
- const envRoot = readFirstEnv(env, ENV_URL_KEYS);
9571
- const root = explicitRoot ?? envRoot;
9572
- const explicitRootWinsOverEnvServices = explicitRoot !== void 0;
9573
- const resolveService = (explicit, envKeys, path) => normalizeOptional(explicit) ?? (explicitRootWinsOverEnvServices && root ? appendPath(root, path) : void 0) ?? readFirstEnv(env, envKeys) ?? (root ? appendPath(root, path) : void 0);
12313
+ const explicitRoot = normalizeOptional2(config.url);
12314
+ const envRoot = readFirstEnvHttpUrl(env, ENV_URL_KEYS);
12315
+ const root = explicitRoot && isAbsoluteHttpUrl(explicitRoot) ? explicitRoot : explicitRoot ? void 0 : envRoot;
12316
+ const explicitRootWinsOverEnvServices = Boolean(root && explicitRoot && isAbsoluteHttpUrl(explicitRoot));
12317
+ const resolveService = (explicit, envKeys, path) => normalizeOptional2(explicit) ?? (explicitRootWinsOverEnvServices && root ? appendPath(root, path) : void 0) ?? readFirstEnvHttpUrl(env, envKeys) ?? (root ? appendPath(root, path) : void 0);
9574
12318
  const dbUrl = resolveService(config.db?.url, ENV_DB_URL_KEYS, "db");
9575
12319
  const urls = {
9576
12320
  db: dbUrl,
@@ -9578,8 +12322,8 @@ function resolveCore(config) {
9578
12322
  chat: resolveService(config.chat?.url, ENV_CHAT_URL_KEYS, "chat"),
9579
12323
  storage: resolveService(config.storage?.url, ENV_STORAGE_URL_KEYS, "storage"),
9580
12324
  // Billing lives on the main Athena HTTP surface (same host as gateway/db).
9581
- billing: normalizeOptional(config.billing?.url) ?? dbUrl ?? root ?? void 0,
9582
- chatWs: normalizeOptional(config.chat?.wsUrl) ?? (explicitRootWinsOverEnvServices && root ? toWebSocketUrl(root) : void 0) ?? readFirstEnv(env, ENV_CHAT_WS_URL_KEYS) ?? (root ? toWebSocketUrl(root) : void 0)
12325
+ billing: normalizeOptional2(config.billing?.url) ?? dbUrl ?? root ?? void 0,
12326
+ chatWs: normalizeOptional2(config.chat?.wsUrl) ?? (explicitRootWinsOverEnvServices && root ? toWebSocketUrl(root) : void 0) ?? readFirstEnvHttpUrl(env, ENV_CHAT_WS_URL_KEYS) ?? (root ? toWebSocketUrl(root) : void 0)
9583
12327
  };
9584
12328
  if (!urls.db && !urls.auth && !urls.chat && !urls.storage && !urls.billing) {
9585
12329
  throw new AthenaConfigurationError(
@@ -9588,7 +12332,7 @@ function resolveCore(config) {
9588
12332
  "db"
9589
12333
  );
9590
12334
  }
9591
- const key = normalizeOptional(config.key) ?? readFirstEnv(env, ENV_KEY_KEYS);
12335
+ const key = normalizeOptional2(config.key) ?? readFirstEnv(env, ENV_KEY_KEYS);
9592
12336
  if (!key) {
9593
12337
  throw new AthenaConfigurationError(
9594
12338
  "ATHENA_API_KEY_REQUIRED",
@@ -9599,7 +12343,7 @@ function resolveCore(config) {
9599
12343
  config,
9600
12344
  urls,
9601
12345
  key,
9602
- client: normalizeOptional(config.client) ?? readFirstEnv(env, ENV_CLIENT_KEYS)
12346
+ client: normalizeOptional2(config.client) ?? readFirstEnv(env, ENV_CLIENT_KEYS)
9603
12347
  };
9604
12348
  return {
9605
12349
  ...base,
@@ -9614,7 +12358,20 @@ async function resolveConfiguredContext(core, viewContext) {
9614
12358
  function createInternalConfig(core) {
9615
12359
  const { config, urls } = core;
9616
12360
  const { url: _authUrl, ...authOptions } = config.auth ?? {};
9617
- const { url: _storageUrl, directUpload, ...storageOptions } = config.storage ?? {};
12361
+ const {
12362
+ url: _storageUrl,
12363
+ directUpload,
12364
+ r2: _r2,
12365
+ prefix: _r2Prefix,
12366
+ ...storageOptions
12367
+ } = config.storage ?? {};
12368
+ const diagnostics = resolveAthenaClientDiagnostics({
12369
+ diagnostics: config.diagnostics,
12370
+ debugAst: config.debugAst,
12371
+ findManyAst: config.findManyAst,
12372
+ traceQueries: config.traceQueries,
12373
+ env: config.env
12374
+ });
9618
12375
  return {
9619
12376
  baseUrl: urls.db ?? MISSING_DB_SENTINEL,
9620
12377
  apiKey: core.key,
@@ -9631,14 +12388,15 @@ function createInternalConfig(core) {
9631
12388
  models: config.models,
9632
12389
  behavior: {
9633
12390
  retryReads: config.retryReads,
9634
- traceQueries: config.traceQueries,
9635
- debugAst: config.debugAst,
9636
- findManyAst: config.findManyAst
12391
+ traceQueries: diagnostics.traceQueries,
12392
+ debugAst: diagnostics.debugAst,
12393
+ findManyAst: diagnostics.findManyAst
9637
12394
  },
9638
12395
  storage: {
9639
12396
  ...storageOptions,
9640
12397
  ...directUpload ? { directUpload } : {}
9641
- }
12398
+ },
12399
+ gatewayTransport: config.gatewayTransport
9642
12400
  };
9643
12401
  }
9644
12402
  function serviceGuard(urls, service) {
@@ -9661,6 +12419,232 @@ function createUnavailableNamespace(service, urls, path = []) {
9661
12419
  }
9662
12420
  });
9663
12421
  }
12422
+ function isD1Binding2(value) {
12423
+ return Boolean(
12424
+ value && typeof value === "object" && typeof value.prepare === "function"
12425
+ );
12426
+ }
12427
+ function isR2Binding(value) {
12428
+ return Boolean(
12429
+ value && typeof value === "object" && typeof value.put === "function" && typeof value.get === "function"
12430
+ );
12431
+ }
12432
+ function foldBindingAliases(config) {
12433
+ const d1 = config.db?.d1 ?? config.d1;
12434
+ const r2 = config.storage?.r2 ?? config.r2;
12435
+ const sessionMode = config.db?.sessionMode ?? config.sessionMode;
12436
+ const prefix = config.storage?.prefix ?? config.storagePrefix;
12437
+ let next = { ...config };
12438
+ if (d1 !== void 0 || sessionMode !== void 0) {
12439
+ next = {
12440
+ ...next,
12441
+ db: {
12442
+ ...next.db,
12443
+ ...d1 !== void 0 ? { d1 } : {},
12444
+ ...sessionMode !== void 0 ? { sessionMode } : {}
12445
+ }
12446
+ };
12447
+ }
12448
+ if (r2 !== void 0 || prefix !== void 0) {
12449
+ next = {
12450
+ ...next,
12451
+ storage: {
12452
+ ...next.storage,
12453
+ ...r2 !== void 0 ? { r2 } : {},
12454
+ ...prefix !== void 0 ? { prefix } : {}
12455
+ }
12456
+ };
12457
+ }
12458
+ const {
12459
+ d1: _d1,
12460
+ r2: _r2,
12461
+ storagePrefix: _storagePrefix,
12462
+ sessionMode: _sessionMode,
12463
+ ...rest
12464
+ } = next;
12465
+ return rest;
12466
+ }
12467
+ function applyExecutionMode(config) {
12468
+ const d1 = config.db?.d1;
12469
+ const hasD1 = isD1Binding2(d1);
12470
+ const hasUrl = Boolean(
12471
+ normalizeOptional2(config.url) ?? normalizeOptional2(config.db?.url) ?? (config.env ? normalizeOptional2(config.env.ATHENA_URL) ?? normalizeOptional2(config.env.NEXT_PUBLIC_ATHENA_URL) : void 0)
12472
+ );
12473
+ const hasModeHint = config.mode != null || config.prefer != null || Boolean(config.env?.ATHENA_EXECUTION_MODE) || Boolean(config.env?.ATHENA_EXECUTION_PREFER);
12474
+ if (!hasD1 && !hasModeHint) {
12475
+ return config;
12476
+ }
12477
+ if (hasD1 && !hasUrl && !hasModeHint) {
12478
+ return config;
12479
+ }
12480
+ let resolved;
12481
+ try {
12482
+ resolved = resolveAthenaExecutionMode({
12483
+ mode: config.mode,
12484
+ prefer: config.prefer,
12485
+ d1: hasD1 ? d1 : null,
12486
+ url: config.url ?? config.db?.url,
12487
+ env: config.env
12488
+ });
12489
+ } catch (error) {
12490
+ if (!hasModeHint) return config;
12491
+ throw error;
12492
+ }
12493
+ if (resolved === "gateway" && hasD1) {
12494
+ const { d1: _drop, sessionMode: _sm, ...dbRest } = config.db ?? {};
12495
+ return {
12496
+ ...config,
12497
+ db: Object.keys(dbRest).length > 0 ? dbRest : void 0,
12498
+ gatewayTransport: void 0
12499
+ };
12500
+ }
12501
+ return config;
12502
+ }
12503
+ function resolveUnifiedRemoteRoot(config) {
12504
+ return normalizeOptional2(config.url) ?? readFirstEnv(config.env, ENV_URL_KEYS);
12505
+ }
12506
+ function isEdgeLocalSentinelUrl(url) {
12507
+ if (!url) return false;
12508
+ return url === CLOUDFLARE_EDGE_BASE_URL || url.startsWith("https://athena.local/") || url.startsWith("http://athena.local/");
12509
+ }
12510
+ function hasRemoteDbGatewayUrl(config) {
12511
+ const dbUrl = normalizeOptional2(config.db?.url) ?? readFirstEnv(config.env, ENV_DB_URL_KEYS);
12512
+ return Boolean(dbUrl && !isEdgeLocalSentinelUrl(dbUrl));
12513
+ }
12514
+ function hasRemoteHttpServices(config) {
12515
+ return Boolean(
12516
+ 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)
12517
+ );
12518
+ }
12519
+ function hasRemoteHttpStorage(config) {
12520
+ return Boolean(
12521
+ normalizeOptional2(config.storage?.url) || readFirstEnv(config.env, ENV_STORAGE_URL_KEYS) || resolveUnifiedRemoteRoot(config)
12522
+ );
12523
+ }
12524
+ function hasRemoteAuthService(config) {
12525
+ return Boolean(
12526
+ normalizeOptional2(config.auth?.url) || readFirstEnv(config.env, ENV_AUTH_URL_KEYS) || resolveUnifiedRemoteRoot(config)
12527
+ );
12528
+ }
12529
+ function materializeEdgeBindings(config) {
12530
+ const d1 = config.db?.d1;
12531
+ const r2 = config.storage?.r2;
12532
+ const hasD1 = isD1Binding2(d1);
12533
+ const hasR2 = isR2Binding(r2);
12534
+ if (!hasD1 && !hasR2) {
12535
+ return config;
12536
+ }
12537
+ if (hasD1 && d1 && typeof d1.prepare !== "function") {
12538
+ throw new AthenaConfigurationError(
12539
+ "ATHENA_NO_SERVICE_CONFIGURED",
12540
+ "db.d1 must be a D1 binding with prepare().",
12541
+ "db"
12542
+ );
12543
+ }
12544
+ const remoteRoot = resolveUnifiedRemoteRoot(config);
12545
+ const remoteServices = hasRemoteHttpServices(config);
12546
+ const remoteStorage = hasRemoteHttpStorage(config);
12547
+ const remoteAuth = hasRemoteAuthService(config);
12548
+ const next = { ...config };
12549
+ if (hasD1 && d1) {
12550
+ if (!config.gatewayTransport) {
12551
+ next.gatewayTransport = createCloudflareD1GatewayTransport({
12552
+ d1,
12553
+ defaultSessionMode: config.db?.sessionMode
12554
+ });
12555
+ }
12556
+ const explicitDbUrl = normalizeOptional2(config.db?.url);
12557
+ const remoteDbGateway = hasRemoteDbGatewayUrl(config);
12558
+ next.db = {
12559
+ ...config.db,
12560
+ d1,
12561
+ url: explicitDbUrl ?? (remoteDbGateway ? void 0 : CLOUDFLARE_EDGE_BASE_URL)
12562
+ };
12563
+ const explicitKey = normalizeOptional2(config.key);
12564
+ if (explicitKey) {
12565
+ next.key = explicitKey;
12566
+ } else if (!remoteServices) {
12567
+ next.key = CLOUDFLARE_EDGE_API_KEY;
12568
+ } else {
12569
+ next.key = void 0;
12570
+ }
12571
+ if (remoteRoot) {
12572
+ next.billing = {
12573
+ ...config.billing ?? {},
12574
+ url: normalizeOptional2(config.billing?.url) ?? remoteRoot
12575
+ };
12576
+ }
12577
+ if (!config.capabilities) {
12578
+ next.capabilities = createCloudflareEdgeCapabilities({
12579
+ hasR2,
12580
+ // Explicit storage.url / env storage URL / unified remote root all count.
12581
+ hasRemoteStorage: remoteStorage,
12582
+ authRemote: remoteAuth,
12583
+ findManyAst: false
12584
+ });
12585
+ }
12586
+ } else if (hasR2 && r2) {
12587
+ if (!remoteRoot && !normalizeOptional2(config.db?.url) && !normalizeOptional2(config.storage?.url) && !readFirstEnv(config.env, ENV_STORAGE_URL_KEYS)) {
12588
+ next.storage = {
12589
+ ...config.storage,
12590
+ r2,
12591
+ // Local sentinel so resolveCore accepts a storage-only binding client.
12592
+ url: CLOUDFLARE_EDGE_BASE_URL
12593
+ };
12594
+ if (!remoteServices) {
12595
+ next.key = normalizeOptional2(config.key) ?? CLOUDFLARE_EDGE_API_KEY;
12596
+ } else if (normalizeOptional2(config.key)) {
12597
+ next.key = normalizeOptional2(config.key);
12598
+ } else {
12599
+ next.key = void 0;
12600
+ }
12601
+ }
12602
+ if (!config.capabilities) {
12603
+ if (remoteRoot || normalizeOptional2(config.db?.url) || readFirstEnv(config.env, ENV_DB_URL_KEYS)) {
12604
+ const base = createGatewayCapabilities({
12605
+ authRemote: remoteAuth,
12606
+ storageConfigured: true
12607
+ });
12608
+ next.capabilities = {
12609
+ ...base,
12610
+ storage: {
12611
+ ...base.storage,
12612
+ local: true,
12613
+ objects: true
12614
+ }
12615
+ };
12616
+ } else {
12617
+ next.capabilities = {
12618
+ mode: "cloudflare-edge",
12619
+ db: {
12620
+ engine: "unknown",
12621
+ local: false,
12622
+ layers: {
12623
+ query: false,
12624
+ flatCrud: false,
12625
+ findManyAst: false,
12626
+ rpc: false,
12627
+ relations: false
12628
+ }
12629
+ },
12630
+ storage: {
12631
+ local: true,
12632
+ objects: true,
12633
+ catalogs: false,
12634
+ backups: false
12635
+ },
12636
+ auth: {
12637
+ remote: remoteAuth
12638
+ }
12639
+ };
12640
+ }
12641
+ }
12642
+ }
12643
+ return next;
12644
+ }
12645
+ function normalizeCreateClientConfig(config) {
12646
+ return materializeEdgeBindings(applyExecutionMode(foldBindingAliases(config)));
12647
+ }
9664
12648
  function createClientView(core, viewContext) {
9665
12649
  const resolved = createInternalClientView(
9666
12650
  core.internalCore,
@@ -9678,12 +12662,23 @@ function createClientView(core, viewContext) {
9678
12662
  },
9679
12663
  ...billingOptions
9680
12664
  }) : createUnavailableNamespace("billing", core.urls);
12665
+ const capabilities = core.config.capabilities ?? createGatewayCapabilities({
12666
+ authRemote: Boolean(core.urls.auth),
12667
+ // Match unavailable storage proxy when no storage URL was resolved.
12668
+ storageConfigured: Boolean(core.urls.storage)
12669
+ });
12670
+ const r2 = core.config.storage?.r2;
12671
+ const storageModule = isR2Binding(r2) ? createCloudflareR2StorageModule({
12672
+ r2,
12673
+ prefix: core.config.storage?.prefix ?? void 0
12674
+ }) : core.urls.storage ? resolved.storage : createUnavailableNamespace("storage", core.urls);
9681
12675
  const client = {
9682
12676
  db: core.urls.db ? resolved.db : createUnavailableNamespace("db", core.urls),
9683
12677
  auth: core.urls.auth ? resolved.auth : createUnavailableNamespace("auth", core.urls),
9684
12678
  chat: core.urls.chat ? resolved.chat : createUnavailableNamespace("chat", core.urls),
9685
- storage: core.urls.storage ? resolved.storage : createUnavailableNamespace("storage", core.urls),
12679
+ storage: storageModule,
9686
12680
  billing: billingModule,
12681
+ capabilities,
9687
12682
  from: ((...args) => {
9688
12683
  requireDb();
9689
12684
  return Reflect.apply(resolved.from, resolved, args);
@@ -9707,13 +12702,34 @@ function createClientView(core, viewContext) {
9707
12702
  return resolved.verifyConnection(options);
9708
12703
  },
9709
12704
  withContext(context) {
12705
+ warnIfEmptyRequestContext(context);
9710
12706
  return createClientView(core, mergeAthenaRequestContexts(viewContext, context));
9711
12707
  }
9712
12708
  };
9713
12709
  return Object.freeze(client);
9714
12710
  }
12711
+ function isEmptyAthenaRequestContext(context) {
12712
+ if (!context) return true;
12713
+ const hasHeaders = context.headers != null && Object.keys(context.headers).length > 0;
12714
+ return context.userId == null && context.organizationId == null && !normalizeOptionalContextString(context.cookie) && !normalizeOptionalContextString(context.bearerToken) && !normalizeOptionalContextString(context.sessionToken) && !context.forceNoCache && !hasHeaders;
12715
+ }
12716
+ function normalizeOptionalContextString(value) {
12717
+ const trimmed = value?.trim();
12718
+ return trimmed || void 0;
12719
+ }
12720
+ function warnIfEmptyRequestContext(context) {
12721
+ if (!isEmptyAthenaRequestContext(context)) return;
12722
+ const nodeEnv = globalThis.process?.env?.NODE_ENV;
12723
+ if (nodeEnv === "production") {
12724
+ return;
12725
+ }
12726
+ console.warn(
12727
+ "[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 })."
12728
+ );
12729
+ }
9715
12730
  function createClient(config) {
9716
- return createClientView(resolveCore(config));
12731
+ const normalized = normalizeCreateClientConfig(config);
12732
+ return createClientView(resolveCore(normalized));
9717
12733
  }
9718
12734
 
9719
12735
  // src/next/session-bridge/constants.ts
@@ -10004,7 +13020,7 @@ function stripAthenaAuthPath(pathname) {
10004
13020
  }
10005
13021
  return normalizedPath;
10006
13022
  }
10007
- function readProcessEnv2() {
13023
+ function readProcessEnv3() {
10008
13024
  try {
10009
13025
  const maybeProcess = globalThis.process;
10010
13026
  return maybeProcess?.env;
@@ -10041,7 +13057,7 @@ function resolveConfiguredAthenaAuthUpstreamUrl(rawUpstreamUrl) {
10041
13057
  if (rawUpstreamUrl) {
10042
13058
  return readAthenaAuthUpstreamUrlFromEnv(rawUpstreamUrl);
10043
13059
  }
10044
- const processEnv = readProcessEnv2();
13060
+ const processEnv = readProcessEnv3();
10045
13061
  return processEnv ? readAthenaAuthUpstreamUrlFromEnv(processEnv) : void 0;
10046
13062
  }
10047
13063
  function normalizeAthenaAuthBaseUrl(urlOrPath) {