@adcp/sdk 16.0.0-beta.2 → 16.0.0-beta.4

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 (248) hide show
  1. package/README.md +54 -0
  2. package/dist/lib/auth/oauth/diagnose.js +3 -11
  3. package/dist/lib/auth/oauth/diagnose.mjs +4 -12
  4. package/dist/lib/auth/oauth/diagnostics.d.mts +2 -1
  5. package/dist/lib/auth/oauth/diagnostics.d.ts +2 -1
  6. package/dist/lib/auth/oauth/diagnostics.js +8 -10
  7. package/dist/lib/auth/oauth/diagnostics.mjs +7 -10
  8. package/dist/lib/core/ConversationTypes.d.mts +8 -3
  9. package/dist/lib/core/ConversationTypes.d.ts +8 -3
  10. package/dist/lib/core/SingleAgentClient.d.mts +5 -3
  11. package/dist/lib/core/SingleAgentClient.d.ts +5 -3
  12. package/dist/lib/core/TaskExecutor.js +5 -1
  13. package/dist/lib/core/TaskExecutor.mjs +5 -1
  14. package/dist/lib/errors/index.d.mts +9 -4
  15. package/dist/lib/errors/index.d.ts +9 -4
  16. package/dist/lib/index.d.mts +3 -3
  17. package/dist/lib/index.d.ts +3 -3
  18. package/dist/lib/index.js +8 -0
  19. package/dist/lib/index.mjs +14 -2
  20. package/dist/lib/negotiation/types.d.mts +20 -39
  21. package/dist/lib/negotiation/types.d.ts +20 -39
  22. package/dist/lib/protocols/index.d.mts +60 -24
  23. package/dist/lib/protocols/index.d.ts +60 -24
  24. package/dist/lib/protocols/index.js +9 -4
  25. package/dist/lib/protocols/index.mjs +3 -0
  26. package/dist/lib/protocols/mcp-modern.js +1 -0
  27. package/dist/lib/protocols/mcp-modern.mjs +2 -1
  28. package/dist/lib/protocols/mcp.js +1 -0
  29. package/dist/lib/protocols/mcp.mjs +2 -1
  30. package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
  31. package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
  32. package/dist/lib/protocols/responseSizeLimit.js +195 -31
  33. package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
  34. package/dist/lib/reporting/consumer-runtime.js +2 -1
  35. package/dist/lib/reporting/consumer-runtime.mjs +2 -1
  36. package/dist/lib/reporting/ledger/handler.js +50 -11
  37. package/dist/lib/reporting/ledger/handler.mjs +50 -12
  38. package/dist/lib/reporting/ledger/index.d.mts +17 -14
  39. package/dist/lib/reporting/ledger/index.d.ts +17 -14
  40. package/dist/lib/reporting/ledger/index.js +32 -20
  41. package/dist/lib/reporting/ledger/index.mjs +21 -10
  42. package/dist/lib/reporting/ledger/offering-validation.d.mts +9 -0
  43. package/dist/lib/reporting/ledger/offering-validation.d.ts +9 -0
  44. package/dist/lib/reporting/{gcs/bucket-policy.js → ledger/offering-validation.js} +9 -8
  45. package/dist/lib/reporting/ledger/offering-validation.mjs +8 -0
  46. package/dist/lib/reporting/ledger/receipts.d.mts +48 -0
  47. package/dist/lib/reporting/ledger/receipts.d.ts +48 -0
  48. package/dist/lib/reporting/ledger/receipts.js +186 -0
  49. package/dist/lib/reporting/ledger/receipts.mjs +161 -0
  50. package/dist/lib/reporting/ledger/status-ingest.js +3 -3
  51. package/dist/lib/reporting/ledger/status-ingest.mjs +4 -5
  52. package/dist/lib/reporting/ledger/types.d.mts +43 -0
  53. package/dist/lib/reporting/ledger/types.d.ts +43 -0
  54. package/dist/lib/reporting/ledger/types.js +31 -2
  55. package/dist/lib/reporting/ledger/types.mjs +26 -1
  56. package/dist/lib/reporting/pagination.d.mts +6 -0
  57. package/dist/lib/reporting/pagination.d.ts +6 -0
  58. package/dist/lib/reporting/{gcs/errors.js → pagination.js} +12 -17
  59. package/dist/lib/reporting/pagination.mjs +12 -0
  60. package/dist/lib/reporting/reconciliation.d.mts +1 -0
  61. package/dist/lib/reporting/reconciliation.d.ts +1 -0
  62. package/dist/lib/reporting/reconciliation.js +3 -2
  63. package/dist/lib/reporting/reconciliation.mjs +3 -2
  64. package/dist/lib/reporting/service/index.d.mts +79 -153
  65. package/dist/lib/reporting/service/index.d.ts +79 -153
  66. package/dist/lib/reporting/service/index.js +34 -491
  67. package/dist/lib/reporting/service/index.mjs +36 -510
  68. package/dist/lib/reporting/service/scheduler-support.d.mts +43 -0
  69. package/dist/lib/reporting/service/scheduler-support.d.ts +43 -0
  70. package/dist/lib/reporting/service/scheduler-support.js +125 -0
  71. package/dist/lib/reporting/service/scheduler-support.mjs +96 -0
  72. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  73. package/dist/lib/signing/canonicalize.d.mts +4 -0
  74. package/dist/lib/signing/canonicalize.d.ts +4 -0
  75. package/dist/lib/signing/canonicalize.js +14 -8
  76. package/dist/lib/signing/canonicalize.mjs +14 -8
  77. package/dist/lib/signing/content-digest.d.mts +8 -0
  78. package/dist/lib/signing/content-digest.d.ts +8 -0
  79. package/dist/lib/signing/content-digest.js +11 -5
  80. package/dist/lib/signing/content-digest.mjs +10 -5
  81. package/dist/lib/signing/crypto.d.mts +15 -0
  82. package/dist/lib/signing/crypto.d.ts +15 -0
  83. package/dist/lib/signing/crypto.js +75 -3
  84. package/dist/lib/signing/crypto.mjs +78 -3
  85. package/dist/lib/signing/server.d.mts +1 -1
  86. package/dist/lib/signing/server.d.ts +1 -1
  87. package/dist/lib/signing/server.js +2 -0
  88. package/dist/lib/signing/server.mjs +2 -1
  89. package/dist/lib/signing/signer.js +11 -14
  90. package/dist/lib/signing/signer.mjs +13 -16
  91. package/dist/lib/signing/testing.js +2 -6
  92. package/dist/lib/signing/testing.mjs +3 -7
  93. package/dist/lib/signing/verifier.js +2 -2
  94. package/dist/lib/signing/verifier.mjs +3 -3
  95. package/dist/lib/signing/web-bot-auth.js +122 -43
  96. package/dist/lib/signing/web-bot-auth.mjs +128 -44
  97. package/dist/lib/signing/webhook-verifier.js +2 -2
  98. package/dist/lib/signing/webhook-verifier.mjs +3 -3
  99. package/dist/lib/substitution/compile.js +2 -1
  100. package/dist/lib/substitution/compile.mjs +2 -1
  101. package/dist/lib/substitution/consent-macros.d.mts +4 -0
  102. package/dist/lib/substitution/consent-macros.d.ts +4 -0
  103. package/dist/lib/substitution/consent-macros.js +45 -0
  104. package/dist/lib/substitution/consent-macros.mjs +20 -0
  105. package/dist/lib/substitution/index.d.mts +1 -1
  106. package/dist/lib/substitution/index.d.ts +1 -1
  107. package/dist/lib/substitution/index.js +2 -0
  108. package/dist/lib/substitution/index.mjs +2 -1
  109. package/dist/lib/substitution/translate.d.mts +15 -2
  110. package/dist/lib/substitution/translate.d.ts +15 -2
  111. package/dist/lib/substitution/translate.js +148 -26
  112. package/dist/lib/substitution/translate.mjs +147 -26
  113. package/dist/lib/testing/client.js +2 -1
  114. package/dist/lib/testing/client.mjs +2 -1
  115. package/dist/lib/testing/scenarios/capabilities.js +1 -1
  116. package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
  117. package/dist/lib/testing/storyboard/junit.js +16 -3
  118. package/dist/lib/testing/storyboard/junit.mjs +16 -3
  119. package/dist/lib/testing/storyboard/request-signing/builder.js +12 -14
  120. package/dist/lib/testing/storyboard/request-signing/builder.mjs +13 -15
  121. package/dist/lib/testing/storyboard/runner.js +94 -25
  122. package/dist/lib/testing/storyboard/runner.mjs +94 -25
  123. package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
  124. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
  125. package/dist/lib/testing/storyboard/types.d.mts +6 -0
  126. package/dist/lib/testing/storyboard/types.d.ts +6 -0
  127. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  128. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  129. package/dist/lib/types/enums.generated.d.mts +3 -0
  130. package/dist/lib/types/enums.generated.d.ts +3 -0
  131. package/dist/lib/types/enums.generated.js +9 -0
  132. package/dist/lib/types/enums.generated.mjs +6 -0
  133. package/dist/lib/validation/schema-loader.js +25 -0
  134. package/dist/lib/validation/schema-loader.mjs +24 -0
  135. package/dist/lib/version.d.mts +3 -3
  136. package/dist/lib/version.d.ts +3 -3
  137. package/dist/lib/version.js +3 -3
  138. package/dist/lib/version.mjs +3 -3
  139. package/docs/TYPE-SUMMARY.md +28 -5
  140. package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
  141. package/docs/guides/REPORTING-GCS-FENCE.md +3 -3
  142. package/docs/guides/REPORTING-GCS-MANAGED.md +4 -4
  143. package/docs/guides/REPORTING-LEDGER-CUTOVER.md +7 -7
  144. package/docs/guides/REPORTING-LEDGER.md +107 -51
  145. package/docs/guides/REPORTING-OPERATIONS.md +66 -5
  146. package/docs/guides/REPORTING-STABILITY.md +36 -32
  147. package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
  148. package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
  149. package/docs/llms.txt +4 -3
  150. package/docs/migration-14.x-rc-worksheet.md +4 -7
  151. package/docs/migration-reporting-storage-package.md +186 -0
  152. package/examples/README.md +1 -1
  153. package/package.json +14 -78
  154. package/dist/lib/reporting/azure/index.d.mts +0 -31
  155. package/dist/lib/reporting/azure/index.d.ts +0 -31
  156. package/dist/lib/reporting/azure/index.js +0 -266
  157. package/dist/lib/reporting/azure/index.mjs +0 -249
  158. package/dist/lib/reporting/bigquery/index.d.mts +0 -246
  159. package/dist/lib/reporting/bigquery/index.d.ts +0 -246
  160. package/dist/lib/reporting/bigquery/index.js +0 -633
  161. package/dist/lib/reporting/bigquery/index.mjs +0 -594
  162. package/dist/lib/reporting/gcs/adapter.d.mts +0 -38
  163. package/dist/lib/reporting/gcs/adapter.d.ts +0 -38
  164. package/dist/lib/reporting/gcs/adapter.js +0 -342
  165. package/dist/lib/reporting/gcs/adapter.mjs +0 -325
  166. package/dist/lib/reporting/gcs/bucket-policy.d.mts +0 -3
  167. package/dist/lib/reporting/gcs/bucket-policy.d.ts +0 -3
  168. package/dist/lib/reporting/gcs/bucket-policy.mjs +0 -7
  169. package/dist/lib/reporting/gcs/errors.d.mts +0 -11
  170. package/dist/lib/reporting/gcs/errors.d.ts +0 -11
  171. package/dist/lib/reporting/gcs/errors.mjs +0 -16
  172. package/dist/lib/reporting/gcs/fence.d.mts +0 -41
  173. package/dist/lib/reporting/gcs/fence.d.ts +0 -41
  174. package/dist/lib/reporting/gcs/fence.js +0 -250
  175. package/dist/lib/reporting/gcs/fence.mjs +0 -230
  176. package/dist/lib/reporting/gcs/index.d.mts +0 -18
  177. package/dist/lib/reporting/gcs/index.d.ts +0 -18
  178. package/dist/lib/reporting/gcs/index.js +0 -44
  179. package/dist/lib/reporting/gcs/index.mjs +0 -14
  180. package/dist/lib/reporting/gcs/io.d.mts +0 -7
  181. package/dist/lib/reporting/gcs/io.d.ts +0 -7
  182. package/dist/lib/reporting/gcs/io.js +0 -95
  183. package/dist/lib/reporting/gcs/io.mjs +0 -69
  184. package/dist/lib/reporting/gcs/reader.d.mts +0 -67
  185. package/dist/lib/reporting/gcs/reader.d.ts +0 -67
  186. package/dist/lib/reporting/gcs/reader.js +0 -193
  187. package/dist/lib/reporting/gcs/reader.mjs +0 -169
  188. package/dist/lib/reporting/gcs/row-provider.d.mts +0 -39
  189. package/dist/lib/reporting/gcs/row-provider.d.ts +0 -39
  190. package/dist/lib/reporting/gcs/row-provider.js +0 -225
  191. package/dist/lib/reporting/gcs/row-provider.mjs +0 -208
  192. package/dist/lib/reporting/gcs/validation.d.mts +0 -5
  193. package/dist/lib/reporting/gcs/validation.d.ts +0 -5
  194. package/dist/lib/reporting/gcs/validation.js +0 -49
  195. package/dist/lib/reporting/gcs/validation.mjs +0 -25
  196. package/dist/lib/reporting/ledger/change-feed.d.mts +0 -69
  197. package/dist/lib/reporting/ledger/change-feed.d.ts +0 -69
  198. package/dist/lib/reporting/ledger/change-feed.js +0 -107
  199. package/dist/lib/reporting/ledger/change-feed.mjs +0 -80
  200. package/dist/lib/reporting/ledger/managed-postgres.d.mts +0 -293
  201. package/dist/lib/reporting/ledger/managed-postgres.d.ts +0 -293
  202. package/dist/lib/reporting/ledger/managed-postgres.js +0 -2346
  203. package/dist/lib/reporting/ledger/managed-postgres.mjs +0 -2332
  204. package/dist/lib/reporting/ledger/managed-router.d.mts +0 -148
  205. package/dist/lib/reporting/ledger/managed-router.d.ts +0 -148
  206. package/dist/lib/reporting/ledger/managed-router.js +0 -280
  207. package/dist/lib/reporting/ledger/managed-router.mjs +0 -258
  208. package/dist/lib/reporting/ledger/managed.d.mts +0 -535
  209. package/dist/lib/reporting/ledger/managed.d.ts +0 -535
  210. package/dist/lib/reporting/ledger/managed.js +0 -761
  211. package/dist/lib/reporting/ledger/managed.mjs +0 -729
  212. package/dist/lib/reporting/ledger/notification-activity.d.mts +0 -332
  213. package/dist/lib/reporting/ledger/notification-activity.d.ts +0 -332
  214. package/dist/lib/reporting/ledger/notification-activity.js +0 -1366
  215. package/dist/lib/reporting/ledger/notification-activity.mjs +0 -1337
  216. package/dist/lib/reporting/ledger/object-writes.d.mts +0 -128
  217. package/dist/lib/reporting/ledger/object-writes.d.ts +0 -128
  218. package/dist/lib/reporting/ledger/object-writes.js +0 -147
  219. package/dist/lib/reporting/ledger/object-writes.mjs +0 -114
  220. package/dist/lib/reporting/ledger/postgres.d.mts +0 -689
  221. package/dist/lib/reporting/ledger/postgres.d.ts +0 -689
  222. package/dist/lib/reporting/ledger/postgres.js +0 -4462
  223. package/dist/lib/reporting/ledger/postgres.mjs +0 -4462
  224. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +0 -59
  225. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +0 -59
  226. package/dist/lib/reporting/ledger/row-storage-migration.js +0 -365
  227. package/dist/lib/reporting/ledger/row-storage-migration.mjs +0 -339
  228. package/dist/lib/reporting/ledger/row-storage-object.d.mts +0 -203
  229. package/dist/lib/reporting/ledger/row-storage-object.d.ts +0 -203
  230. package/dist/lib/reporting/ledger/row-storage-object.js +0 -379
  231. package/dist/lib/reporting/ledger/row-storage-object.mjs +0 -335
  232. package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +0 -44
  233. package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +0 -44
  234. package/dist/lib/reporting/ledger/row-storage-provider-io.js +0 -142
  235. package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +0 -111
  236. package/dist/lib/reporting/ledger/row-storage.d.mts +0 -316
  237. package/dist/lib/reporting/ledger/row-storage.d.ts +0 -316
  238. package/dist/lib/reporting/ledger/row-storage.js +0 -812
  239. package/dist/lib/reporting/ledger/row-storage.mjs +0 -802
  240. package/dist/lib/reporting/s3/index.d.mts +0 -34
  241. package/dist/lib/reporting/s3/index.d.ts +0 -34
  242. package/dist/lib/reporting/s3/index.js +0 -347
  243. package/dist/lib/reporting/s3/index.mjs +0 -340
  244. package/dist/lib/reporting/service/maintenance.d.mts +0 -148
  245. package/dist/lib/reporting/service/maintenance.d.ts +0 -148
  246. package/dist/lib/reporting/service/maintenance.js +0 -185
  247. package/dist/lib/reporting/service/maintenance.mjs +0 -159
  248. package/examples/reliable-reporting-service/README.md +0 -169
@@ -1,335 +0,0 @@
1
- import { createHash, randomInt, randomUUID } from "crypto";
2
- import { promises as fs } from "fs";
3
- import * as path from "path";
4
- import { canonicalize } from "../../utils/jcs.mjs";
5
- import { ReportingRowStoreError } from "./row-storage-errors.mjs";
6
- import { reportingPeriodDate } from "./schedule.mjs";
7
- const REPORTING_ROW_OBJECT_REF_MAX_LENGTH = 1024;
8
- const REPORTING_ROW_NATIVE_VERSION_REF_MAX_LENGTH = 1024;
9
- const REPORTING_ROW_KEY_PLACEHOLDERS = Object.freeze([
10
- "prefix",
11
- "namespace_key",
12
- "account_key",
13
- "period_date",
14
- "finality",
15
- "revision_key",
16
- "content_sha256",
17
- "chunk_index"
18
- ]);
19
- const REPORTING_ROW_DEFAULT_KEY_TEMPLATE = "{prefix}/{namespace_key}/{account_key}/{period_date}/{finality}/{revision_key}/{content_sha256}/{chunk_index}";
20
- const PREFIX = /^[A-Za-z0-9_.=-]+(?:\/[A-Za-z0-9_.=-]+)*$/;
21
- const KEY = /^[A-Za-z0-9_.=-]+(?:\/[A-Za-z0-9_.=-]+)*$/;
22
- const PLACEHOLDER = /\{([a-z0-9_]+)\}/g;
23
- function assertReportingRowKeyTemplateV1(template, options = {}) {
24
- if (!template.startsWith("{prefix}/{namespace_key}/")) {
25
- throw new ReportingRowStoreError("INVALID_INPUT", "key templates must begin with {prefix}/{namespace_key}/");
26
- }
27
- const requiredPlaceholders = ["{content_sha256}", "{chunk_index}"];
28
- if (options.requireRevisionKey ?? true) requiredPlaceholders.push("{revision_key}");
29
- for (const required of requiredPlaceholders) {
30
- if (!template.includes(required)) {
31
- throw new ReportingRowStoreError(
32
- "INVALID_INPUT",
33
- required === "{revision_key}" ? "key templates must include {revision_key} so every row set has unique object keys. A binding identity includes its template, so add it under a NEW binding ID and keep the old definition configured with `readOnly: true` while rows reference it (rows already written stay readable at their recorded object_ref)" : `key templates must include ${required}`
34
- );
35
- }
36
- }
37
- const unknown = [...template.matchAll(PLACEHOLDER)].map((match) => match[1]).filter((name) => !REPORTING_ROW_KEY_PLACEHOLDERS.includes(name));
38
- if (unknown.length > 0) {
39
- throw new ReportingRowStoreError("INVALID_INPUT", `unknown key template placeholders: ${unknown.join(", ")}`);
40
- }
41
- const literal = template.replace(PLACEHOLDER, "x");
42
- if (!KEY.test(literal) || literal.split("/").some((segment) => segment === "." || segment === "..")) {
43
- throw new ReportingRowStoreError("INVALID_INPUT", "key template contains unsafe characters or segments");
44
- }
45
- }
46
- function assertReportingRowPrefixV1(prefix) {
47
- if (!PREFIX.test(prefix) || prefix.length > 512 || prefix.split("/").some((segment) => segment === "." || segment === "..")) {
48
- throw new ReportingRowStoreError("INVALID_INPUT", "row binding prefix is invalid");
49
- }
50
- }
51
- function reportingRowAccountKeyV1(namespaceKey, accountId) {
52
- return sha256Hex(canonicalize(["adcp.account_key.v1", namespaceKey, accountId]));
53
- }
54
- function reportingRowRevisionKeyV1(rowSetId) {
55
- return sha256Hex(canonicalize(["adcp.revision_key.v1", rowSetId]));
56
- }
57
- function renderReportingRowObjectKeyV1(input) {
58
- const values = {
59
- prefix: input.prefix,
60
- namespace_key: input.namespaceKey,
61
- account_key: reportingRowAccountKeyV1(input.namespaceKey, input.accountId),
62
- // Rendered only when the template uses it, so a template without {period_date} needs no timezone.
63
- period_date: input.template.includes("{period_date}") ? renderedPeriodDate(input.periodStart, input.sourceTimezone) : "",
64
- finality: input.finality ?? "adjustment",
65
- revision_key: reportingRowRevisionKeyV1(input.rowSetId),
66
- content_sha256: input.contentSha256,
67
- chunk_index: String(input.chunkIndex).padStart(6, "0")
68
- };
69
- const key = input.template.replace(PLACEHOLDER, (_, name) => values[name]) + (input.compression === "gzip" ? ".jsonl.gz" : ".jsonl");
70
- if (!KEY.test(key) || key.split("/").some((segment) => segment === "." || segment === "..") || !key.startsWith(`${input.prefix}/${input.namespaceKey}/`)) {
71
- throw new ReportingRowStoreError("INVALID_INPUT", "rendered object key escapes the binding prefix");
72
- }
73
- if (key.length > REPORTING_ROW_OBJECT_REF_MAX_LENGTH) {
74
- throw new ReportingRowStoreError(
75
- "INVALID_INPUT",
76
- `rendered object key exceeds ${REPORTING_ROW_OBJECT_REF_MAX_LENGTH} characters (AdCP object_ref bound)`
77
- );
78
- }
79
- return key;
80
- }
81
- function renderedPeriodDate(periodStart, sourceTimezone) {
82
- if (!periodStart) return "undated";
83
- if (!sourceTimezone) {
84
- throw new ReportingRowStoreError(
85
- "INVALID_INPUT",
86
- "a period start needs its source_timezone to render {period_date}"
87
- );
88
- }
89
- try {
90
- return reportingPeriodDate(periodStart, sourceTimezone);
91
- } catch {
92
- throw new ReportingRowStoreError(
93
- "INVALID_INPUT",
94
- "period start or source_timezone is invalid; cannot render {period_date}"
95
- );
96
- }
97
- }
98
- function createFilesystemReportingRowObjectProviderV1(options) {
99
- const roots = /* @__PURE__ */ new Map();
100
- for (const [name, directory] of Object.entries(options.roots)) {
101
- if (!/^[A-Za-z0-9_.-]{1,64}$/.test(name) || !path.isAbsolute(directory)) {
102
- throw new ReportingRowStoreError("INVALID_INPUT", "filesystem roots need a simple name and an absolute path");
103
- }
104
- roots.set(name, path.resolve(directory));
105
- }
106
- const resolve = (location, key) => {
107
- const root = roots.get(location.root ?? "");
108
- if (!root) throw new ReportingRowStoreError("UNSAFE_BINDING", "filesystem root is not configured");
109
- const target = path.resolve(root, key);
110
- if (!target.startsWith(root + path.sep)) {
111
- throw new ReportingRowStoreError("INVALID_INPUT", "object key escapes the filesystem root");
112
- }
113
- return target;
114
- };
115
- const versionOf = (stat) => `${stat.ino}:${stat.birthtimeNs}:${stat.mtimeNs}:${stat.size}`;
116
- const version = async (target) => versionOf(await fs.stat(target, { bigint: true }));
117
- return {
118
- name: "filesystem",
119
- rangedReads: true,
120
- validateLocation(location) {
121
- const keys = Object.keys(location);
122
- if (keys.length !== 1 || keys[0] !== "root" || !roots.has(location.root)) {
123
- throw new ReportingRowStoreError("INVALID_INPUT", "filesystem locations name exactly one configured root");
124
- }
125
- },
126
- async probe(input) {
127
- const root = roots.get(input.location.root ?? "");
128
- if (!root) throw new ReportingRowStoreError("UNSAFE_BINDING", "filesystem root is not configured");
129
- await fs.mkdir(root, { recursive: true });
130
- },
131
- async putIfAbsent(input, context) {
132
- context.signal.throwIfAborted();
133
- const target = resolve(input.location, input.objectRef);
134
- await fs.mkdir(path.dirname(target), { recursive: true });
135
- const temporary = `${target}.${randomUUID()}.tmp`;
136
- const handle = await fs.open(temporary, "wx");
137
- try {
138
- await handle.writeFile(input.bytes);
139
- const mtime = Date.now() / 1e3 + randomInt(0, 1e3) / 1e6;
140
- await handle.utimes(mtime, mtime);
141
- await handle.sync();
142
- } finally {
143
- await handle.close();
144
- }
145
- try {
146
- await fs.link(temporary, target);
147
- return { created: true, nativeVersionRef: await version(target) };
148
- } catch (error) {
149
- if (error.code === "EEXIST") {
150
- return { created: false, nativeVersionRef: await version(target) };
151
- }
152
- throw new ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem write failed");
153
- } finally {
154
- await fs.rm(temporary, { force: true });
155
- }
156
- },
157
- async get(input, context) {
158
- context.signal.throwIfAborted();
159
- const target = resolve(input.location, input.objectRef);
160
- let handle;
161
- try {
162
- handle = await fs.open(target, "r");
163
- } catch (error) {
164
- if (error.code === "ENOENT") return null;
165
- throw new ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem read failed");
166
- }
167
- try {
168
- const stat = await handle.stat({ bigint: true });
169
- if (versionOf(stat) !== input.nativeVersionRef) return null;
170
- const size = Number(stat.size);
171
- const offset = input.range?.offset ?? 0;
172
- const length = input.range?.length ?? size - offset;
173
- if (offset < 0 || length < 0 || offset + length > size) {
174
- throw new ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "requested range exceeds the stored object");
175
- }
176
- if (length > input.maxBytes) {
177
- throw new ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "stored object exceeds its recorded size");
178
- }
179
- const buffer = Buffer.alloc(length);
180
- await handle.read(buffer, 0, length, offset);
181
- return buffer;
182
- } finally {
183
- await handle.close();
184
- }
185
- },
186
- async stat(input, context) {
187
- context.signal.throwIfAborted();
188
- const target = resolve(input.location, input.objectRef);
189
- try {
190
- const stat = await fs.stat(target, { bigint: true });
191
- return versionOf(stat) === input.nativeVersionRef ? { nativeVersionRef: input.nativeVersionRef, sizeBytes: Number(stat.size) } : null;
192
- } catch (error) {
193
- if (error.code === "ENOENT") return null;
194
- throw new ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem stat failed");
195
- }
196
- },
197
- async delete(input, context) {
198
- context.signal.throwIfAborted();
199
- const target = resolve(input.location, input.objectRef);
200
- try {
201
- if (await version(target) !== input.nativeVersionRef) return "absent";
202
- await fs.unlink(target);
203
- return "deleted";
204
- } catch (error) {
205
- if (error.code === "ENOENT") return "absent";
206
- throw new ReportingRowStoreError("PROVIDER_UNAVAILABLE", "filesystem delete failed");
207
- }
208
- }
209
- };
210
- }
211
- async function runReportingRowObjectProviderConformanceV1(provider, input) {
212
- assertReportingRowPrefixV1(input.prefix);
213
- provider.validateLocation(input.location);
214
- const context = { signal: AbortSignal.timeout(6e4) };
215
- const passed = [];
216
- const key = `${input.prefix}/conformance/${randomUUID()}.jsonl`;
217
- const first = Buffer.from('{"a":1}\n{"b":2}\n');
218
- const metadata = { "adcp-installation": "conformance", "adcp-intent": "conformance" };
219
- const base = { location: input.location, ...input.credentialRef ? { credentialRef: input.credentialRef } : {} };
220
- await provider.probe(input, context);
221
- passed.push("probe");
222
- const created = await provider.putIfAbsent(
223
- { ...base, objectRef: key, bytes: first, contentType: "application/x-ndjson", metadata },
224
- context
225
- );
226
- if (!created.created || !created.nativeVersionRef) throw new Error("putIfAbsent did not create a new object");
227
- passed.push("create");
228
- const conflict = await provider.putIfAbsent(
229
- { ...base, objectRef: key, bytes: Buffer.from('{"c":3}\n'), contentType: "application/x-ndjson", metadata },
230
- context
231
- );
232
- if (conflict.created || conflict.nativeVersionRef !== created.nativeVersionRef) {
233
- throw new Error("putIfAbsent replaced or re-versioned an existing object");
234
- }
235
- const stored = await provider.get(
236
- { ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef, maxBytes: 1024 },
237
- context
238
- );
239
- if (!stored || !Buffer.from(stored).equals(first))
240
- throw new Error("create-only write did not preserve the first bytes");
241
- passed.push("create-only");
242
- if (provider.rangedReads) {
243
- const ranged = await provider.get(
244
- {
245
- ...base,
246
- objectRef: key,
247
- nativeVersionRef: created.nativeVersionRef,
248
- range: { offset: 8, length: 8 },
249
- maxBytes: 1024
250
- },
251
- context
252
- );
253
- if (!ranged || Buffer.from(ranged).toString("utf8") !== '{"b":2}\n')
254
- throw new Error("ranged read returned wrong bytes");
255
- passed.push("ranged-read");
256
- }
257
- if (await provider.get({ ...base, objectRef: key, nativeVersionRef: "not-a-version", maxBytes: 1024 }, context) !== null) {
258
- throw new Error("get returned bytes for a version that does not exist");
259
- }
260
- passed.push("version-pinned-read");
261
- if (provider.stat) {
262
- const stat = await provider.stat({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context);
263
- if (!stat || stat.sizeBytes !== first.byteLength) throw new Error("stat did not report the stored object size");
264
- if (stat.nativeVersionRef !== created.nativeVersionRef) throw new Error("stat did not echo the version it checked");
265
- if (await provider.stat({ ...base, objectRef: key, nativeVersionRef: "not-a-version" }, context) !== null) {
266
- throw new Error("stat returned metadata for a version that does not exist");
267
- }
268
- passed.push("version-pinned-stat");
269
- }
270
- if (await provider.delete({ ...base, objectRef: key, nativeVersionRef: "not-a-version" }, context) !== "absent") {
271
- throw new Error("delete removed an object at a different version");
272
- }
273
- if (await provider.delete({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context) !== "deleted") {
274
- throw new Error("delete did not remove the exact version");
275
- }
276
- if (await provider.delete({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context) !== "absent") {
277
- throw new Error("repeated delete was not idempotent");
278
- }
279
- passed.push("exact-version-delete");
280
- if (provider.stat && await provider.stat({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context) !== null) {
281
- throw new Error("stat returned metadata for a deleted version");
282
- }
283
- const recreated = await provider.putIfAbsent(
284
- { ...base, objectRef: key, bytes: first, contentType: "application/x-ndjson", metadata },
285
- context
286
- );
287
- if (!recreated.created || !recreated.nativeVersionRef)
288
- throw new Error("putIfAbsent did not re-create a deleted object");
289
- if (recreated.nativeVersionRef === created.nativeVersionRef) {
290
- throw new Error("re-creating identical bytes produced the same native version; versions must be write-unique");
291
- }
292
- if (await provider.delete({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context) !== "absent") {
293
- throw new Error("delete of a stale version removed or reported a later write");
294
- }
295
- if (provider.stat) {
296
- if (await provider.stat({ ...base, objectRef: key, nativeVersionRef: created.nativeVersionRef }, context) !== null) {
297
- throw new Error("stat of a stale version reported a later write at the same key");
298
- }
299
- const current = await provider.stat(
300
- { ...base, objectRef: key, nativeVersionRef: recreated.nativeVersionRef },
301
- context
302
- );
303
- if (!current || current.sizeBytes !== first.byteLength || current.nativeVersionRef !== recreated.nativeVersionRef) {
304
- throw new Error("stat did not report the re-created object");
305
- }
306
- }
307
- const survivor = await provider.get(
308
- { ...base, objectRef: key, nativeVersionRef: recreated.nativeVersionRef, maxBytes: 1024 },
309
- context
310
- );
311
- if (!survivor || !Buffer.from(survivor).equals(first)) {
312
- throw new Error("delete of a stale version removed a later write with identical bytes");
313
- }
314
- if (await provider.delete({ ...base, objectRef: key, nativeVersionRef: recreated.nativeVersionRef }, context) !== "deleted") {
315
- throw new Error("delete did not remove the re-created version");
316
- }
317
- passed.push("write-unique-version");
318
- return passed;
319
- }
320
- function sha256Hex(value) {
321
- return createHash("sha256").update(value).digest("hex");
322
- }
323
- export {
324
- REPORTING_ROW_DEFAULT_KEY_TEMPLATE,
325
- REPORTING_ROW_KEY_PLACEHOLDERS,
326
- REPORTING_ROW_NATIVE_VERSION_REF_MAX_LENGTH,
327
- REPORTING_ROW_OBJECT_REF_MAX_LENGTH,
328
- assertReportingRowKeyTemplateV1,
329
- assertReportingRowPrefixV1,
330
- createFilesystemReportingRowObjectProviderV1,
331
- renderReportingRowObjectKeyV1,
332
- reportingRowAccountKeyV1,
333
- reportingRowRevisionKeyV1,
334
- runReportingRowObjectProviderConformanceV1
335
- };
@@ -1,44 +0,0 @@
1
- import { ReportingRowStoreError } from './row-storage-errors.mjs';
2
- /**
3
- * Internal helpers shared by the bundled cloud row-object providers (GCS, S3,
4
- * Azure Blob). Not part of the public `reporting/ledger` surface.
5
- */
6
- /** Stable code for an aborted operation: deadline expiry versus caller cancellation. */
7
- export declare function reportingRowAbortError(signal: AbortSignal): ReportingRowStoreError;
8
- /**
9
- * Run one provider operation under the caller's signal. Settles as soon as the
10
- * signal aborts, even when the official client ignores cancellation. Raw
11
- * provider errors never escape: anything that is not already a
12
- * `ReportingRowStoreError` becomes `PROVIDER_UNAVAILABLE`.
13
- */
14
- export declare function runReportingRowProviderOperation<T>(signal: AbortSignal, work: () => Promise<T>): Promise<T>;
15
- /**
16
- * Drain a byte stream, aborting once it exceeds `maxBytes`
17
- * (`ROWS_INTEGRITY_FAILED`) or the signal fires. The stream is always destroyed.
18
- */
19
- export declare function readReportingRowStream(stream: AsyncIterable<unknown> & {
20
- destroy?: (error?: Error) => unknown;
21
- }, maxBytes: number, signal: AbortSignal): Promise<Buffer>;
22
- /** Validate a get request's range and cap before any provider I/O. */
23
- export declare function assertReportingRowReadBounds(input: {
24
- range?: {
25
- offset: number;
26
- length: number;
27
- };
28
- maxBytes: number;
29
- }): void;
30
- /**
31
- * Pick the host-injected client for a binding. `credentialRef` selects from a
32
- * closed map; without one, the default client is used. Unknown references fail
33
- * closed with `UNSAFE_BINDING` and never echo the reference.
34
- */
35
- export declare function selectReportingRowClient<T>(defaultClient: T | undefined, clients: ReadonlyMap<string, T>, credentialRef: string | undefined): T;
36
- /** Copy a host client map into a closed, frozen lookup. */
37
- export declare function reportingRowClientMap<T>(clients: Readonly<Record<string, T>> | undefined): ReadonlyMap<string, T>;
38
- /** Throw `INVALID_INPUT` unless `location` has exactly the allowed keys (and every required one). */
39
- export declare function assertReportingRowLocationKeys(location: Readonly<Record<string, string>>, required: readonly string[], optional?: readonly string[]): void;
40
- /**
41
- * Whether an object-store prefix filter can match keys under the binding's
42
- * owned prefix. An absent or empty filter matches everything.
43
- */
44
- export declare function reportingRowPrefixFilterOverlaps(filter: string | undefined, bindingPrefix: string): boolean;
@@ -1,44 +0,0 @@
1
- import { ReportingRowStoreError } from './row-storage-errors';
2
- /**
3
- * Internal helpers shared by the bundled cloud row-object providers (GCS, S3,
4
- * Azure Blob). Not part of the public `reporting/ledger` surface.
5
- */
6
- /** Stable code for an aborted operation: deadline expiry versus caller cancellation. */
7
- export declare function reportingRowAbortError(signal: AbortSignal): ReportingRowStoreError;
8
- /**
9
- * Run one provider operation under the caller's signal. Settles as soon as the
10
- * signal aborts, even when the official client ignores cancellation. Raw
11
- * provider errors never escape: anything that is not already a
12
- * `ReportingRowStoreError` becomes `PROVIDER_UNAVAILABLE`.
13
- */
14
- export declare function runReportingRowProviderOperation<T>(signal: AbortSignal, work: () => Promise<T>): Promise<T>;
15
- /**
16
- * Drain a byte stream, aborting once it exceeds `maxBytes`
17
- * (`ROWS_INTEGRITY_FAILED`) or the signal fires. The stream is always destroyed.
18
- */
19
- export declare function readReportingRowStream(stream: AsyncIterable<unknown> & {
20
- destroy?: (error?: Error) => unknown;
21
- }, maxBytes: number, signal: AbortSignal): Promise<Buffer>;
22
- /** Validate a get request's range and cap before any provider I/O. */
23
- export declare function assertReportingRowReadBounds(input: {
24
- range?: {
25
- offset: number;
26
- length: number;
27
- };
28
- maxBytes: number;
29
- }): void;
30
- /**
31
- * Pick the host-injected client for a binding. `credentialRef` selects from a
32
- * closed map; without one, the default client is used. Unknown references fail
33
- * closed with `UNSAFE_BINDING` and never echo the reference.
34
- */
35
- export declare function selectReportingRowClient<T>(defaultClient: T | undefined, clients: ReadonlyMap<string, T>, credentialRef: string | undefined): T;
36
- /** Copy a host client map into a closed, frozen lookup. */
37
- export declare function reportingRowClientMap<T>(clients: Readonly<Record<string, T>> | undefined): ReadonlyMap<string, T>;
38
- /** Throw `INVALID_INPUT` unless `location` has exactly the allowed keys (and every required one). */
39
- export declare function assertReportingRowLocationKeys(location: Readonly<Record<string, string>>, required: readonly string[], optional?: readonly string[]): void;
40
- /**
41
- * Whether an object-store prefix filter can match keys under the binding's
42
- * owned prefix. An absent or empty filter matches everything.
43
- */
44
- export declare function reportingRowPrefixFilterOverlaps(filter: string | undefined, bindingPrefix: string): boolean;
@@ -1,142 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var row_storage_provider_io_exports = {};
20
- __export(row_storage_provider_io_exports, {
21
- assertReportingRowLocationKeys: () => assertReportingRowLocationKeys,
22
- assertReportingRowReadBounds: () => assertReportingRowReadBounds,
23
- readReportingRowStream: () => readReportingRowStream,
24
- reportingRowAbortError: () => reportingRowAbortError,
25
- reportingRowClientMap: () => reportingRowClientMap,
26
- reportingRowPrefixFilterOverlaps: () => reportingRowPrefixFilterOverlaps,
27
- runReportingRowProviderOperation: () => runReportingRowProviderOperation,
28
- selectReportingRowClient: () => selectReportingRowClient
29
- });
30
- module.exports = __toCommonJS(row_storage_provider_io_exports);
31
- var import_row_storage_errors = require('./row-storage-errors.js');
32
- function reportingRowAbortError(signal) {
33
- const reason = signal.reason;
34
- if ((0, import_row_storage_errors.isReportingRowStoreError)(reason)) return reason;
35
- return new import_row_storage_errors.ReportingRowStoreError(reason?.name === "TimeoutError" ? "DEADLINE_EXCEEDED" : "ABORTED");
36
- }
37
- async function runReportingRowProviderOperation(signal, work) {
38
- if (!(signal instanceof AbortSignal)) throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "a signal is required");
39
- if (signal.aborted) throw reportingRowAbortError(signal);
40
- let onAbort;
41
- try {
42
- return await Promise.race([
43
- work(),
44
- new Promise((_, reject) => {
45
- onAbort = () => reject(reportingRowAbortError(signal));
46
- signal.addEventListener("abort", onAbort, { once: true });
47
- })
48
- ]);
49
- } catch (error) {
50
- if (signal.aborted) throw reportingRowAbortError(signal);
51
- if ((0, import_row_storage_errors.isReportingRowStoreError)(error)) throw error;
52
- throw new import_row_storage_errors.ReportingRowStoreError("PROVIDER_UNAVAILABLE");
53
- } finally {
54
- if (onAbort) signal.removeEventListener("abort", onAbort);
55
- }
56
- }
57
- async function readReportingRowStream(stream, maxBytes, signal) {
58
- const abort = () => stream.destroy?.(reportingRowAbortError(signal));
59
- signal.addEventListener("abort", abort, { once: true });
60
- const chunks = [];
61
- let count = 0;
62
- try {
63
- if (signal.aborted) throw reportingRowAbortError(signal);
64
- for await (const chunk of stream) {
65
- if (signal.aborted) throw reportingRowAbortError(signal);
66
- const bytes = typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk);
67
- count += bytes.byteLength;
68
- if (count > maxBytes) {
69
- throw new import_row_storage_errors.ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "stored object exceeds its recorded size");
70
- }
71
- chunks.push(bytes);
72
- }
73
- if (signal.aborted) throw reportingRowAbortError(signal);
74
- return Buffer.concat(chunks);
75
- } finally {
76
- signal.removeEventListener("abort", abort);
77
- stream.destroy?.();
78
- }
79
- }
80
- function assertReportingRowReadBounds(input) {
81
- if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes < 0) {
82
- throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "maxBytes must be a non-negative integer");
83
- }
84
- if (input.range === void 0) return;
85
- const { offset, length } = input.range;
86
- if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length) || offset < 0 || length < 0) {
87
- throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "range must use non-negative integers");
88
- }
89
- if (length > input.maxBytes) {
90
- throw new import_row_storage_errors.ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "requested range exceeds the read cap");
91
- }
92
- }
93
- function selectReportingRowClient(defaultClient, clients, credentialRef) {
94
- const client = credentialRef === void 0 ? defaultClient : clients.get(credentialRef);
95
- if (client === void 0) {
96
- throw new import_row_storage_errors.ReportingRowStoreError("UNSAFE_BINDING", "no client is configured for this binding");
97
- }
98
- return client;
99
- }
100
- function reportingRowClientMap(clients) {
101
- const map = /* @__PURE__ */ new Map();
102
- if (clients === void 0) return map;
103
- if (!clients || typeof clients !== "object") {
104
- throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "clients must map credential references to clients");
105
- }
106
- for (const [ref, client] of Object.entries(clients)) {
107
- if (!/^[A-Za-z0-9_.:-]{1,128}$/.test(ref) || !client) {
108
- throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "clients must map credential references to clients");
109
- }
110
- map.set(ref, client);
111
- }
112
- return map;
113
- }
114
- function assertReportingRowLocationKeys(location, required, optional = []) {
115
- if (!location || typeof location !== "object" || Array.isArray(location)) {
116
- throw new import_row_storage_errors.ReportingRowStoreError("INVALID_INPUT", "location must be an object");
117
- }
118
- const keys = Object.keys(location);
119
- const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
120
- if (keys.some((key) => !allowed.has(key) || typeof location[key] !== "string") || required.some((key) => !keys.includes(key))) {
121
- throw new import_row_storage_errors.ReportingRowStoreError(
122
- "INVALID_INPUT",
123
- `location accepts only ${[...required, ...optional.map((key) => `${key}?`)].join(", ")}`
124
- );
125
- }
126
- }
127
- function reportingRowPrefixFilterOverlaps(filter, bindingPrefix) {
128
- if (!filter) return true;
129
- const owned = `${bindingPrefix}/`;
130
- return owned.startsWith(filter) || filter.startsWith(owned);
131
- }
132
- // Annotate the CommonJS export names for ESM import in node:
133
- 0 && (module.exports = {
134
- assertReportingRowLocationKeys,
135
- assertReportingRowReadBounds,
136
- readReportingRowStream,
137
- reportingRowAbortError,
138
- reportingRowClientMap,
139
- reportingRowPrefixFilterOverlaps,
140
- runReportingRowProviderOperation,
141
- selectReportingRowClient
142
- });
@@ -1,111 +0,0 @@
1
- import { ReportingRowStoreError, isReportingRowStoreError } from "./row-storage-errors.mjs";
2
- function reportingRowAbortError(signal) {
3
- const reason = signal.reason;
4
- if (isReportingRowStoreError(reason)) return reason;
5
- return new ReportingRowStoreError(reason?.name === "TimeoutError" ? "DEADLINE_EXCEEDED" : "ABORTED");
6
- }
7
- async function runReportingRowProviderOperation(signal, work) {
8
- if (!(signal instanceof AbortSignal)) throw new ReportingRowStoreError("INVALID_INPUT", "a signal is required");
9
- if (signal.aborted) throw reportingRowAbortError(signal);
10
- let onAbort;
11
- try {
12
- return await Promise.race([
13
- work(),
14
- new Promise((_, reject) => {
15
- onAbort = () => reject(reportingRowAbortError(signal));
16
- signal.addEventListener("abort", onAbort, { once: true });
17
- })
18
- ]);
19
- } catch (error) {
20
- if (signal.aborted) throw reportingRowAbortError(signal);
21
- if (isReportingRowStoreError(error)) throw error;
22
- throw new ReportingRowStoreError("PROVIDER_UNAVAILABLE");
23
- } finally {
24
- if (onAbort) signal.removeEventListener("abort", onAbort);
25
- }
26
- }
27
- async function readReportingRowStream(stream, maxBytes, signal) {
28
- const abort = () => stream.destroy?.(reportingRowAbortError(signal));
29
- signal.addEventListener("abort", abort, { once: true });
30
- const chunks = [];
31
- let count = 0;
32
- try {
33
- if (signal.aborted) throw reportingRowAbortError(signal);
34
- for await (const chunk of stream) {
35
- if (signal.aborted) throw reportingRowAbortError(signal);
36
- const bytes = typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk);
37
- count += bytes.byteLength;
38
- if (count > maxBytes) {
39
- throw new ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "stored object exceeds its recorded size");
40
- }
41
- chunks.push(bytes);
42
- }
43
- if (signal.aborted) throw reportingRowAbortError(signal);
44
- return Buffer.concat(chunks);
45
- } finally {
46
- signal.removeEventListener("abort", abort);
47
- stream.destroy?.();
48
- }
49
- }
50
- function assertReportingRowReadBounds(input) {
51
- if (!Number.isSafeInteger(input.maxBytes) || input.maxBytes < 0) {
52
- throw new ReportingRowStoreError("INVALID_INPUT", "maxBytes must be a non-negative integer");
53
- }
54
- if (input.range === void 0) return;
55
- const { offset, length } = input.range;
56
- if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(length) || offset < 0 || length < 0) {
57
- throw new ReportingRowStoreError("INVALID_INPUT", "range must use non-negative integers");
58
- }
59
- if (length > input.maxBytes) {
60
- throw new ReportingRowStoreError("ROWS_INTEGRITY_FAILED", "requested range exceeds the read cap");
61
- }
62
- }
63
- function selectReportingRowClient(defaultClient, clients, credentialRef) {
64
- const client = credentialRef === void 0 ? defaultClient : clients.get(credentialRef);
65
- if (client === void 0) {
66
- throw new ReportingRowStoreError("UNSAFE_BINDING", "no client is configured for this binding");
67
- }
68
- return client;
69
- }
70
- function reportingRowClientMap(clients) {
71
- const map = /* @__PURE__ */ new Map();
72
- if (clients === void 0) return map;
73
- if (!clients || typeof clients !== "object") {
74
- throw new ReportingRowStoreError("INVALID_INPUT", "clients must map credential references to clients");
75
- }
76
- for (const [ref, client] of Object.entries(clients)) {
77
- if (!/^[A-Za-z0-9_.:-]{1,128}$/.test(ref) || !client) {
78
- throw new ReportingRowStoreError("INVALID_INPUT", "clients must map credential references to clients");
79
- }
80
- map.set(ref, client);
81
- }
82
- return map;
83
- }
84
- function assertReportingRowLocationKeys(location, required, optional = []) {
85
- if (!location || typeof location !== "object" || Array.isArray(location)) {
86
- throw new ReportingRowStoreError("INVALID_INPUT", "location must be an object");
87
- }
88
- const keys = Object.keys(location);
89
- const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
90
- if (keys.some((key) => !allowed.has(key) || typeof location[key] !== "string") || required.some((key) => !keys.includes(key))) {
91
- throw new ReportingRowStoreError(
92
- "INVALID_INPUT",
93
- `location accepts only ${[...required, ...optional.map((key) => `${key}?`)].join(", ")}`
94
- );
95
- }
96
- }
97
- function reportingRowPrefixFilterOverlaps(filter, bindingPrefix) {
98
- if (!filter) return true;
99
- const owned = `${bindingPrefix}/`;
100
- return owned.startsWith(filter) || filter.startsWith(owned);
101
- }
102
- export {
103
- assertReportingRowLocationKeys,
104
- assertReportingRowReadBounds,
105
- readReportingRowStream,
106
- reportingRowAbortError,
107
- reportingRowClientMap,
108
- reportingRowPrefixFilterOverlaps,
109
- runReportingRowProviderOperation,
110
- selectReportingRowClient
111
- };