@layervai/qurl 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +259 -46
  2. package/dist/cjs/client-connectors.d.ts +44 -0
  3. package/dist/cjs/client-connectors.js +189 -0
  4. package/dist/cjs/client-delegated.d.ts +30 -0
  5. package/dist/cjs/client-delegated.js +312 -0
  6. package/dist/cjs/client-errors.d.ts +44 -0
  7. package/dist/cjs/client-errors.js +219 -0
  8. package/dist/cjs/client-http-types.d.ts +37 -0
  9. package/dist/cjs/client-http-types.js +2 -0
  10. package/dist/cjs/client-input-fields.d.ts +53 -0
  11. package/dist/cjs/client-input-fields.js +262 -0
  12. package/dist/cjs/client-limits.d.ts +36 -0
  13. package/dist/cjs/client-limits.js +61 -0
  14. package/dist/cjs/client-management.d.ts +12 -0
  15. package/dist/cjs/client-management.js +119 -0
  16. package/dist/cjs/client-paths.d.ts +21 -0
  17. package/dist/cjs/client-paths.js +143 -0
  18. package/dist/cjs/client-portals.d.ts +82 -0
  19. package/dist/cjs/client-portals.js +244 -0
  20. package/dist/cjs/client-resources.d.ts +29 -0
  21. package/dist/cjs/client-resources.js +331 -0
  22. package/dist/cjs/client-validation.d.ts +35 -0
  23. package/dist/cjs/client-validation.js +326 -0
  24. package/dist/cjs/client.d.ts +45 -75
  25. package/dist/cjs/client.js +621 -2448
  26. package/dist/cjs/errors.d.ts +9 -1
  27. package/dist/cjs/errors.js +10 -1
  28. package/dist/cjs/index.d.ts +4 -2
  29. package/dist/cjs/index.js +4 -1
  30. package/dist/cjs/response-metadata.d.ts +13 -0
  31. package/dist/cjs/response-metadata.js +38 -0
  32. package/dist/cjs/share.js +2 -0
  33. package/dist/cjs/target-path.d.ts +2 -0
  34. package/dist/cjs/target-path.js +34 -0
  35. package/dist/cjs/types.d.ts +83 -7
  36. package/dist/cjs/version.d.ts +1 -1
  37. package/dist/cjs/version.js +1 -1
  38. package/dist/esm/client-connectors.d.ts +44 -0
  39. package/dist/esm/client-connectors.js +180 -0
  40. package/dist/esm/client-delegated.d.ts +30 -0
  41. package/dist/esm/client-delegated.js +295 -0
  42. package/dist/esm/client-errors.d.ts +44 -0
  43. package/dist/esm/client-errors.js +206 -0
  44. package/dist/esm/client-http-types.d.ts +37 -0
  45. package/dist/esm/client-http-types.js +1 -0
  46. package/dist/esm/client-input-fields.d.ts +53 -0
  47. package/dist/esm/client-input-fields.js +258 -0
  48. package/dist/esm/client-limits.d.ts +36 -0
  49. package/dist/esm/client-limits.js +58 -0
  50. package/dist/esm/client-management.d.ts +12 -0
  51. package/dist/esm/client-management.js +113 -0
  52. package/dist/esm/client-paths.d.ts +21 -0
  53. package/dist/esm/client-paths.js +138 -0
  54. package/dist/esm/client-portals.d.ts +82 -0
  55. package/dist/esm/client-portals.js +236 -0
  56. package/dist/esm/client-resources.d.ts +29 -0
  57. package/dist/esm/client-resources.js +323 -0
  58. package/dist/esm/client-validation.d.ts +35 -0
  59. package/dist/esm/client-validation.js +302 -0
  60. package/dist/esm/client.d.ts +45 -76
  61. package/dist/esm/client.js +318 -2147
  62. package/dist/esm/crid.d.ts +0 -1
  63. package/dist/esm/crid.js +0 -1
  64. package/dist/esm/errors.d.ts +9 -2
  65. package/dist/esm/errors.js +9 -1
  66. package/dist/esm/index.d.ts +4 -3
  67. package/dist/esm/index.js +2 -2
  68. package/dist/esm/internal.d.ts +0 -1
  69. package/dist/esm/internal.js +0 -1
  70. package/dist/esm/node/agent-runtime.d.ts +0 -1
  71. package/dist/esm/node/agent-runtime.js +0 -1
  72. package/dist/esm/node/agent-state.d.ts +0 -1
  73. package/dist/esm/node/agent-state.js +0 -1
  74. package/dist/esm/node/agent-transport.d.ts +0 -1
  75. package/dist/esm/node/agent-transport.js +0 -1
  76. package/dist/esm/node/deployment.d.ts +0 -1
  77. package/dist/esm/node/deployment.js +0 -1
  78. package/dist/esm/node/file-agent-state.d.ts +0 -1
  79. package/dist/esm/node/file-agent-state.js +0 -1
  80. package/dist/esm/node/native-udp.d.ts +0 -1
  81. package/dist/esm/node/native-udp.js +0 -1
  82. package/dist/esm/node/nhp-wire.d.ts +0 -1
  83. package/dist/esm/node/nhp-wire.js +0 -1
  84. package/dist/esm/node/portal-opener.d.ts +0 -1
  85. package/dist/esm/node/portal-opener.js +0 -1
  86. package/dist/esm/node/provider.d.ts +0 -1
  87. package/dist/esm/node/provider.js +0 -1
  88. package/dist/esm/node/qv2.d.ts +0 -1
  89. package/dist/esm/node/qv2.js +0 -1
  90. package/dist/esm/node/relay.d.ts +0 -1
  91. package/dist/esm/node/relay.js +0 -1
  92. package/dist/esm/node/sealed-agent-state.d.ts +0 -1
  93. package/dist/esm/node/sealed-agent-state.js +0 -1
  94. package/dist/esm/node/strict-json.d.ts +0 -1
  95. package/dist/esm/node/strict-json.js +0 -1
  96. package/dist/esm/node.d.ts +0 -1
  97. package/dist/esm/node.js +0 -1
  98. package/dist/esm/response-metadata.d.ts +13 -0
  99. package/dist/esm/response-metadata.js +33 -0
  100. package/dist/esm/share.d.ts +0 -1
  101. package/dist/esm/share.js +2 -1
  102. package/dist/esm/target-path.d.ts +2 -0
  103. package/dist/esm/target-path.js +30 -0
  104. package/dist/esm/types.d.ts +83 -8
  105. package/dist/esm/types.js +0 -1
  106. package/dist/esm/version.d.ts +1 -2
  107. package/dist/esm/version.js +1 -2
  108. package/package.json +9 -7
  109. package/dist/esm/client.d.ts.map +0 -1
  110. package/dist/esm/client.js.map +0 -1
  111. package/dist/esm/crid.d.ts.map +0 -1
  112. package/dist/esm/crid.js.map +0 -1
  113. package/dist/esm/errors.d.ts.map +0 -1
  114. package/dist/esm/errors.js.map +0 -1
  115. package/dist/esm/index.d.ts.map +0 -1
  116. package/dist/esm/index.js.map +0 -1
  117. package/dist/esm/internal.d.ts.map +0 -1
  118. package/dist/esm/internal.js.map +0 -1
  119. package/dist/esm/node/agent-runtime.d.ts.map +0 -1
  120. package/dist/esm/node/agent-runtime.js.map +0 -1
  121. package/dist/esm/node/agent-state.d.ts.map +0 -1
  122. package/dist/esm/node/agent-state.js.map +0 -1
  123. package/dist/esm/node/agent-transport.d.ts.map +0 -1
  124. package/dist/esm/node/agent-transport.js.map +0 -1
  125. package/dist/esm/node/deployment.d.ts.map +0 -1
  126. package/dist/esm/node/deployment.js.map +0 -1
  127. package/dist/esm/node/file-agent-state.d.ts.map +0 -1
  128. package/dist/esm/node/file-agent-state.js.map +0 -1
  129. package/dist/esm/node/native-udp.d.ts.map +0 -1
  130. package/dist/esm/node/native-udp.js.map +0 -1
  131. package/dist/esm/node/nhp-wire.d.ts.map +0 -1
  132. package/dist/esm/node/nhp-wire.js.map +0 -1
  133. package/dist/esm/node/portal-opener.d.ts.map +0 -1
  134. package/dist/esm/node/portal-opener.js.map +0 -1
  135. package/dist/esm/node/provider.d.ts.map +0 -1
  136. package/dist/esm/node/provider.js.map +0 -1
  137. package/dist/esm/node/qv2.d.ts.map +0 -1
  138. package/dist/esm/node/qv2.js.map +0 -1
  139. package/dist/esm/node/relay.d.ts.map +0 -1
  140. package/dist/esm/node/relay.js.map +0 -1
  141. package/dist/esm/node/sealed-agent-state.d.ts.map +0 -1
  142. package/dist/esm/node/sealed-agent-state.js.map +0 -1
  143. package/dist/esm/node/strict-json.d.ts.map +0 -1
  144. package/dist/esm/node/strict-json.js.map +0 -1
  145. package/dist/esm/node.d.ts.map +0 -1
  146. package/dist/esm/node.js.map +0 -1
  147. package/dist/esm/share.d.ts.map +0 -1
  148. package/dist/esm/share.js.map +0 -1
  149. package/dist/esm/types.d.ts.map +0 -1
  150. package/dist/esm/types.js.map +0 -1
  151. package/dist/esm/version.d.ts.map +0 -1
  152. package/dist/esm/version.js.map +0 -1
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEXT_DECODER = exports.TEXT_ENCODER = void 0;
4
+ exports.clientValidationError = clientValidationError;
5
+ exports.unexpectedResponseError = unexpectedResponseError;
6
+ exports.withErrorCause = withErrorCause;
7
+ exports.isIndependentAbort = isIndependentAbort;
8
+ exports.isSdkTimeout = isSdkTimeout;
9
+ exports.boundedErrorSnippet = boundedErrorSnippet;
10
+ exports.boundedErrorIdentifier = boundedErrorIdentifier;
11
+ exports.boundedTombstone = boundedTombstone;
12
+ exports.boundedInvalidFields = boundedInvalidFields;
13
+ exports.boundedObjectKeys = boundedObjectKeys;
14
+ const errors_js_1 = require("./errors.js");
15
+ const client_limits_js_1 = require("./client-limits.js");
16
+ exports.TEXT_ENCODER = new TextEncoder();
17
+ const ERROR_SNIPPET_ELLIPSIS = "...";
18
+ const ERROR_SNIPPET_ELLIPSIS_BYTES = 3;
19
+ // RFC 8259 JSON exchanged between systems must be valid UTF-8. A non-fatal
20
+ // decoder would replace malformed bytes with U+FFFD before JSON.parse and hide
21
+ // the producer's exact contract violation.
22
+ exports.TEXT_DECODER = new TextDecoder("utf-8", { fatal: true });
23
+ /**
24
+ * Construct a {@link ValidationError} for a client-side pre-flight check.
25
+ * Uses `status: 0` (matching {@link NetworkError}/{@link TimeoutError}) and
26
+ * `code: "client_validation"` so catch-by-class still works and callers can
27
+ * tell the error originated inside the SDK rather than from the API.
28
+ */
29
+ function clientValidationError(detail) {
30
+ return new errors_js_1.ValidationError({
31
+ status: 0,
32
+ code: errors_js_1.ERROR_CODE_CLIENT_VALIDATION,
33
+ title: "Invalid Argument",
34
+ detail,
35
+ });
36
+ }
37
+ /**
38
+ * Construct a {@link ValidationError} for the case where the API returned
39
+ * a response that parsed as JSON but didn't match the expected schema
40
+ * shape (e.g. 400 with a body that isn't a {@link BatchCreateOutput}).
41
+ *
42
+ * Distinct from {@link clientValidationError} so callers can `.code`-branch
43
+ * between "I passed bad input locally" (`"client_validation"`) and "the
44
+ * server returned a body I can't interpret" (`"unexpected_response"`).
45
+ * Uses `status: 0` by default because a logical shape mismatch is not tied to
46
+ * the HTTP classification. Callers that enforce an observed HTTP contract
47
+ * pass that status explicitly.
48
+ *
49
+ * Threads `request_id` through to {@link QURLError.requestId} when the
50
+ * server-side correlation ID is available — operators debugging
51
+ * "unexpected response" tickets need it on the *error* path too, not
52
+ * just on success/passthrough returns.
53
+ */
54
+ function unexpectedResponseError(detail, options = {}) {
55
+ // Every detail passed here is an SDK-authored contract message whose dynamic
56
+ // inputs were validated by the caller-side shape guards. Do not pass raw
57
+ // server strings to this helper. Server diagnostics use boundedErrorSnippet.
58
+ const safeRequestId = boundedErrorIdentifier(options.requestId);
59
+ return new errors_js_1.ValidationError({
60
+ status: options.status ?? 0,
61
+ code: errors_js_1.ERROR_CODE_UNEXPECTED_RESPONSE,
62
+ title: "Unexpected Response",
63
+ detail,
64
+ request_id: safeRequestId,
65
+ });
66
+ }
67
+ function withErrorCause(error, cause) {
68
+ // Match the native Error `cause` descriptor. In particular, do not leak a
69
+ // transport object through Object.keys(), object spread, or JSON logging.
70
+ Object.defineProperty(error, "cause", {
71
+ value: cause,
72
+ writable: true,
73
+ configurable: true,
74
+ });
75
+ return error;
76
+ }
77
+ function isIndependentAbort(error, requestSignal) {
78
+ return (error instanceof Error &&
79
+ (error.name === "AbortError" || error.name === "TimeoutError") &&
80
+ !requestSignal.aborted);
81
+ }
82
+ function isSdkTimeout(error, requestSignal) {
83
+ return (error instanceof Error &&
84
+ requestSignal.aborted &&
85
+ (error.name === "TimeoutError" || error.name === "AbortError"));
86
+ }
87
+ /**
88
+ * Normalize a server-provided problem title/detail into a single-line,
89
+ * UTF-8-safe snippet. Error messages must stay bounded even when a proxy or
90
+ * compromised upstream returns very large structured problem fields.
91
+ */
92
+ function normalizedErrorSnippet(value) {
93
+ if (typeof value !== "string")
94
+ return undefined;
95
+ // Bound source work before the Unicode regular expressions allocate
96
+ // normalized copies. The response body cap is much larger than one retained
97
+ // diagnostic, so processing the full server string would waste memory.
98
+ const normalized = value
99
+ .slice(0, client_limits_js_1.MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS)
100
+ // Strip control characters plus bidi override/isolate controls that can
101
+ // visually reorder diagnostics. Preserve other formatting characters
102
+ // such as ZWJ/ZWNJ, which are required by legitimate scripts and emoji.
103
+ .replace(/[\p{Cc}\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/gu, " ")
104
+ .trim()
105
+ .replace(/\s+/g, " ");
106
+ return normalized === "" ? undefined : normalized;
107
+ }
108
+ function boundedErrorSnippet(value) {
109
+ const sourceTruncated = typeof value === "string" && value.length > client_limits_js_1.MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS;
110
+ const normalized = normalizedErrorSnippet(value);
111
+ if (normalized === undefined)
112
+ return undefined;
113
+ const contentLimit = sourceTruncated
114
+ ? client_limits_js_1.MAX_ERROR_SNIPPET_BYTES - ERROR_SNIPPET_ELLIPSIS_BYTES
115
+ : client_limits_js_1.MAX_ERROR_SNIPPET_BYTES;
116
+ // UTF-8 uses at most three bytes per UTF-16 code unit. Most diagnostics are
117
+ // short ASCII, so avoid an allocation only to prove they fit.
118
+ if (normalized.length * 3 <= contentLimit) {
119
+ return sourceTruncated ? `${normalized}${ERROR_SNIPPET_ELLIPSIS}` : normalized;
120
+ }
121
+ const encoded = exports.TEXT_ENCODER.encode(normalized);
122
+ if (encoded.byteLength <= contentLimit) {
123
+ return sourceTruncated ? `${normalized}${ERROR_SNIPPET_ELLIPSIS}` : normalized;
124
+ }
125
+ let end = client_limits_js_1.MAX_ERROR_SNIPPET_BYTES - ERROR_SNIPPET_ELLIPSIS_BYTES;
126
+ // Do not split a multi-byte UTF-8 sequence at the cap.
127
+ while (end > 0 && (encoded[end] & 0xc0) === 0x80)
128
+ end--;
129
+ return `${exports.TEXT_DECODER.decode(encoded.subarray(0, end))}${ERROR_SNIPPET_ELLIPSIS}`;
130
+ }
131
+ /** Keep server identifiers useful as exact machine-readable discriminants. */
132
+ function boundedErrorIdentifier(value) {
133
+ if (typeof value !== "string" || value.length > client_limits_js_1.MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS) {
134
+ return undefined;
135
+ }
136
+ const normalized = normalizedErrorSnippet(value);
137
+ if (normalized === undefined ||
138
+ normalized !== value ||
139
+ exports.TEXT_ENCODER.encode(value).byteLength > client_limits_js_1.MAX_ERROR_SNIPPET_BYTES) {
140
+ return undefined;
141
+ }
142
+ return value;
143
+ }
144
+ /** Keep only the documented retained metadata, with bounded wire values. */
145
+ function boundedTombstone(value) {
146
+ if (typeof value !== "object" || value === null || Array.isArray(value))
147
+ return undefined;
148
+ const raw = value;
149
+ const timestamp = boundedErrorIdentifier(raw.tombstoned_at);
150
+ if (timestamp === undefined ||
151
+ !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(timestamp) ||
152
+ !Number.isFinite(Date.parse(timestamp)))
153
+ return undefined;
154
+ const out = { tombstoned_at: timestamp };
155
+ const count = raw.final_access_count;
156
+ // The API omits zero: absence means no snapshot or a redacted count.
157
+ if (typeof count === "number" && Number.isSafeInteger(count) && count >= 1) {
158
+ out.final_access_count = count;
159
+ }
160
+ return out;
161
+ }
162
+ /** Collect at most the first N enumerable own string keys without a full key-array copy. */
163
+ function firstEnumerableOwnKeys(value, limit) {
164
+ const keys = [];
165
+ for (const key in value) {
166
+ if (!Object.prototype.hasOwnProperty.call(value, key))
167
+ continue;
168
+ keys.push(key);
169
+ if (keys.length === limit)
170
+ break;
171
+ }
172
+ return keys;
173
+ }
174
+ /** Bound the structured per-field diagnostics exposed on ValidationError. */
175
+ function boundedInvalidFields(value) {
176
+ if (typeof value !== "object" || value === null || Array.isArray(value))
177
+ return undefined;
178
+ const entries = [];
179
+ const retainedKeys = new Set();
180
+ let retainedBytes = 0;
181
+ // Bound inspected entries as well as retained entries. A hostile envelope
182
+ // whose values all have the wrong type must not make diagnostics scan every
183
+ // key in the response body.
184
+ for (const rawKey of firstEnumerableOwnKeys(value, client_limits_js_1.MAX_INVALID_FIELD_ENTRIES)) {
185
+ const rawValue = value[rawKey];
186
+ const key = boundedErrorSnippet(rawKey);
187
+ const fieldDetail = boundedErrorSnippet(rawValue);
188
+ if (key !== undefined && fieldDetail !== undefined && !retainedKeys.has(key)) {
189
+ const entryBytes = exports.TEXT_ENCODER.encode(key).byteLength + exports.TEXT_ENCODER.encode(fieldDetail).byteLength;
190
+ // A later, smaller entry can still fit even when this one cannot.
191
+ if (retainedBytes + entryBytes > client_limits_js_1.MAX_DIAGNOSTIC_COLLECTION_BYTES)
192
+ continue;
193
+ retainedKeys.add(key);
194
+ entries.push([key, fieldDetail]);
195
+ retainedBytes += entryBytes;
196
+ }
197
+ }
198
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
199
+ }
200
+ /** Bound server-controlled object keys before forwarding them to a debug sink. */
201
+ function boundedObjectKeys(value) {
202
+ // Stop before normalization so a hostile envelope cannot force work over
203
+ // every enumerable own key. Some early keys may normalize away; bounded
204
+ // diagnostics are more important here than filling every available slot.
205
+ const retained = [];
206
+ let retainedBytes = 0;
207
+ for (const rawKey of firstEnumerableOwnKeys(value, client_limits_js_1.MAX_DEBUG_BODY_KEYS)) {
208
+ const key = boundedErrorSnippet(rawKey);
209
+ if (key === undefined)
210
+ continue;
211
+ const keyBytes = exports.TEXT_ENCODER.encode(key).byteLength;
212
+ // A later, smaller key can still fit even when this one cannot.
213
+ if (retainedBytes + keyBytes > client_limits_js_1.MAX_DIAGNOSTIC_COLLECTION_BYTES)
214
+ continue;
215
+ retained.push(key);
216
+ retainedBytes += keyBytes;
217
+ }
218
+ return retained;
219
+ }
@@ -0,0 +1,37 @@
1
+ export interface ApiResponse<T> {
2
+ data: T;
3
+ meta?: {
4
+ found_existing?: unknown;
5
+ request_id?: string;
6
+ page_size?: number;
7
+ has_more?: boolean;
8
+ next_cursor?: string;
9
+ };
10
+ }
11
+ export interface HttpResponse<T> {
12
+ envelope: ApiResponse<T>;
13
+ status: number;
14
+ bodyEmpty: boolean;
15
+ headers?: Headers;
16
+ }
17
+ export interface ApiErrorEnvelope {
18
+ error?: {
19
+ type?: string;
20
+ title?: string;
21
+ status?: number;
22
+ detail?: string;
23
+ code?: string;
24
+ instance?: string;
25
+ invalid_fields?: Record<string, string>;
26
+ /**
27
+ * Legacy field from pre-RFC-7807 error shapes. Supported for backward
28
+ * compatibility when the API has been configured to return the older
29
+ * `{ error: { code, message } }` envelope.
30
+ */
31
+ message?: string;
32
+ };
33
+ meta?: {
34
+ request_id?: string;
35
+ tombstone?: unknown;
36
+ };
37
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,53 @@
1
+ /** Allowlist of known query-param keys for the `list()` endpoint. */
2
+ export declare const LIST_PARAM_KEYS: readonly ["limit", "cursor", "status", "q", "sort", "created_after", "created_before", "expires_before", "expires_after"];
3
+ export declare const REQUEST_OPTION_KEYS: readonly ["idempotencyKey"];
4
+ export declare const DELEGATED_BATCH_INPUT_KEYS: readonly ["mint_capability", "grants"];
5
+ export declare const DELEGATED_BATCH_GRANT_KEYS: readonly ["expires_in", "label", "one_time_use", "max_sessions", "session_duration", "access_policy"];
6
+ export declare const DELEGATED_BATCH_CREATE_OPTION_KEYS: readonly ["idempotencyKey"];
7
+ export declare const DELEGATED_BATCH_GET_OPTION_KEYS: readonly ["etag"];
8
+ export declare function assertExhaustive<T extends true>(_: T): void;
9
+ export declare const CREATE_FIELD_KEYS: readonly ["name", "private", "type", "target_url", "expires_in", "one_time_use", "max_sessions", "session_duration", "label", "access_policy", "custom_domain"];
10
+ /**
11
+ * Fields accepted by `update()`. The empty-input pre-flight check in
12
+ * {@link QURLClient.update} iterates this const — so adding a new field to
13
+ * {@link UpdateInput} without listing it here will fail the
14
+ * paired `assertExhaustive` witness at compile time rather than silently
15
+ * sneaking through an empty-input request.
16
+ */
17
+ export declare const UPDATE_FIELD_KEYS: readonly ["extend_by", "expires_at", "description", "tags"];
18
+ /**
19
+ * Fields accepted by `mintLink()`. Iterated by the null-stripping
20
+ * normalization loop in {@link QURLClient.mintLink} so unknown keys
21
+ * from untyped-JS callers don't leak through to the wire body.
22
+ * Symmetric with `LIST_PARAM_KEYS` / `UPDATE_FIELD_KEYS`.
23
+ */
24
+ export declare const MINT_FIELD_KEYS: readonly ["expires_in", "expires_at", "label", "one_time_use", "max_sessions", "session_duration", "access_policy"];
25
+ export declare const RESOURCE_LIST_PARAM_KEYS: readonly ["cursor", "limit", "alias", "slug", "status", "type"];
26
+ export declare const CREATE_RESOURCE_FIELD_KEYS: readonly ["name", "private", "consumer_access", "type", "target_url", "description", "tags", "custom_domain", "alias", "slug", "find_or_create"];
27
+ export declare const UPDATE_RESOURCE_FIELD_KEYS: readonly ["allowed_device_keys_add", "allowed_device_keys_remove", "consumer_access", "expected_consumer_access_version", "description", "tags", "custom_domain", "preserve_host", "alias"];
28
+ export declare const CREATE_QURL_FOR_RESOURCE_FIELD_KEYS: readonly ["expires_in", "one_time_use", "max_sessions", "session_duration", "label", "access_policy", "target_path"];
29
+ export declare const SHARE_RESOURCE_OPTION_KEYS: readonly ["ttlSeconds"];
30
+ /**
31
+ * Options accepted by the portal-verb `protectUrl` / `createPortal`
32
+ * surface. These are camelCase caller-facing options (the portal verbs are
33
+ * the idiomatic layer); the build helpers map them onto the same wire
34
+ * fields the REST-shaped methods send.
35
+ */
36
+ export declare const PROTECT_URL_OPTION_KEYS: readonly ["name", "private", "consumerAccess", "description", "tags", "customDomain", "alias"];
37
+ export declare const CREATE_PORTAL_OPTION_KEYS: readonly ["name", "validFor", "label", "oneTimeUse", "maxSessions", "sessionDuration", "targetPath"];
38
+ export declare const UPDATE_RESOURCE_QURL_FIELD_KEYS: readonly ["extend_by", "expires_at", "label", "access_policy", "max_sessions", "session_duration"];
39
+ export declare const UPDATE_CUSTOMER_FIELD_KEYS: readonly ["spending_cap_cents"];
40
+ export declare const CREATE_BILLING_CHECKOUT_FIELD_KEYS: readonly ["plan"];
41
+ export declare const REGISTER_DOMAIN_FIELD_KEYS: readonly ["domain"];
42
+ export declare const CREATE_WEBHOOK_FIELD_KEYS: readonly ["url", "events", "description"];
43
+ export declare const UPDATE_WEBHOOK_FIELD_KEYS: readonly ["url", "events", "description", "status"];
44
+ export declare const CREATE_API_KEY_FIELD_KEYS: readonly ["kind", "name", "scopes", "target", "claims", "expires_in"];
45
+ export declare const UPDATE_API_KEY_FIELD_KEYS: readonly ["name", "scopes"];
46
+ export declare const REDEEM_ACCESS_CODE_FIELD_KEYS: readonly ["code", "honeypot", "elapsed_ms"];
47
+ export declare const CREATE_ACCESS_CODE_FIELD_KEYS: readonly ["resource_id", "name", "max_uses", "expires_at"];
48
+ export declare const CONNECTOR_INSTALLATION_LIST_PARAM_KEYS: readonly ["cursor", "limit"];
49
+ export declare const BILLING_INVOICE_LIST_PARAM_KEYS: readonly ["limit", "cursor"];
50
+ export declare const DOMAIN_LIST_PARAM_KEYS: readonly ["limit", "cursor"];
51
+ export declare const WEBHOOK_LIST_PARAM_KEYS: readonly ["limit", "cursor"];
52
+ export declare const WEBHOOK_DELIVERY_LIST_PARAM_KEYS: readonly ["limit", "cursor"];
53
+ export declare const API_KEY_LIST_PARAM_KEYS: readonly ["limit", "cursor", "status"];
@@ -0,0 +1,262 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.API_KEY_LIST_PARAM_KEYS = exports.WEBHOOK_DELIVERY_LIST_PARAM_KEYS = exports.WEBHOOK_LIST_PARAM_KEYS = exports.DOMAIN_LIST_PARAM_KEYS = exports.BILLING_INVOICE_LIST_PARAM_KEYS = exports.CONNECTOR_INSTALLATION_LIST_PARAM_KEYS = exports.CREATE_ACCESS_CODE_FIELD_KEYS = exports.REDEEM_ACCESS_CODE_FIELD_KEYS = exports.UPDATE_API_KEY_FIELD_KEYS = exports.CREATE_API_KEY_FIELD_KEYS = exports.UPDATE_WEBHOOK_FIELD_KEYS = exports.CREATE_WEBHOOK_FIELD_KEYS = exports.REGISTER_DOMAIN_FIELD_KEYS = exports.CREATE_BILLING_CHECKOUT_FIELD_KEYS = exports.UPDATE_CUSTOMER_FIELD_KEYS = exports.UPDATE_RESOURCE_QURL_FIELD_KEYS = exports.CREATE_PORTAL_OPTION_KEYS = exports.PROTECT_URL_OPTION_KEYS = exports.SHARE_RESOURCE_OPTION_KEYS = exports.CREATE_QURL_FOR_RESOURCE_FIELD_KEYS = exports.UPDATE_RESOURCE_FIELD_KEYS = exports.CREATE_RESOURCE_FIELD_KEYS = exports.RESOURCE_LIST_PARAM_KEYS = exports.MINT_FIELD_KEYS = exports.UPDATE_FIELD_KEYS = exports.CREATE_FIELD_KEYS = exports.DELEGATED_BATCH_GET_OPTION_KEYS = exports.DELEGATED_BATCH_CREATE_OPTION_KEYS = exports.DELEGATED_BATCH_GRANT_KEYS = exports.DELEGATED_BATCH_INPUT_KEYS = exports.REQUEST_OPTION_KEYS = exports.LIST_PARAM_KEYS = void 0;
4
+ exports.assertExhaustive = assertExhaustive;
5
+ /** Allowlist of known query-param keys for the `list()` endpoint. */
6
+ exports.LIST_PARAM_KEYS = [
7
+ "limit",
8
+ "cursor",
9
+ "status",
10
+ "q",
11
+ "sort",
12
+ "created_after",
13
+ "created_before",
14
+ "expires_before",
15
+ "expires_after",
16
+ ];
17
+ exports.REQUEST_OPTION_KEYS = [
18
+ "idempotencyKey",
19
+ ];
20
+ exports.DELEGATED_BATCH_INPUT_KEYS = [
21
+ "mint_capability",
22
+ "grants",
23
+ ];
24
+ exports.DELEGATED_BATCH_GRANT_KEYS = [
25
+ "expires_in",
26
+ "label",
27
+ "one_time_use",
28
+ "max_sessions",
29
+ "session_duration",
30
+ "access_policy",
31
+ ];
32
+ exports.DELEGATED_BATCH_CREATE_OPTION_KEYS = [
33
+ "idempotencyKey",
34
+ ];
35
+ exports.DELEGATED_BATCH_GET_OPTION_KEYS = [
36
+ "etag",
37
+ ];
38
+ // Compile-time witness: `Exclude<keyof X, (typeof KEYS)[number]>` is
39
+ // `never` iff KEYS lists every key of X. Paired with the
40
+ // `satisfies readonly (keyof X)[]` clause on the array (which catches
41
+ // the other direction), this gives bidirectional drift detection on
42
+ // the *_KEYS allowlists at zero runtime cost.
43
+ function assertExhaustive(_) {
44
+ /* type-only check */
45
+ }
46
+ assertExhaustive(true);
47
+ assertExhaustive(true);
48
+ assertExhaustive(true);
49
+ assertExhaustive(true);
50
+ assertExhaustive(true);
51
+ assertExhaustive(true);
52
+ exports.CREATE_FIELD_KEYS = [
53
+ "name",
54
+ "private",
55
+ "type",
56
+ "target_url",
57
+ "expires_in",
58
+ "one_time_use",
59
+ "max_sessions",
60
+ "session_duration",
61
+ "label",
62
+ "access_policy",
63
+ "custom_domain",
64
+ ];
65
+ assertExhaustive(true);
66
+ /**
67
+ * Fields accepted by `update()`. The empty-input pre-flight check in
68
+ * {@link QURLClient.update} iterates this const — so adding a new field to
69
+ * {@link UpdateInput} without listing it here will fail the
70
+ * paired `assertExhaustive` witness at compile time rather than silently
71
+ * sneaking through an empty-input request.
72
+ */
73
+ exports.UPDATE_FIELD_KEYS = [
74
+ "extend_by",
75
+ "expires_at",
76
+ "description",
77
+ "tags",
78
+ ];
79
+ assertExhaustive(true);
80
+ /**
81
+ * Fields accepted by `mintLink()`. Iterated by the null-stripping
82
+ * normalization loop in {@link QURLClient.mintLink} so unknown keys
83
+ * from untyped-JS callers don't leak through to the wire body.
84
+ * Symmetric with `LIST_PARAM_KEYS` / `UPDATE_FIELD_KEYS`.
85
+ */
86
+ exports.MINT_FIELD_KEYS = [
87
+ "expires_in",
88
+ "expires_at",
89
+ "label",
90
+ "one_time_use",
91
+ "max_sessions",
92
+ "session_duration",
93
+ "access_policy",
94
+ ];
95
+ assertExhaustive(true);
96
+ exports.RESOURCE_LIST_PARAM_KEYS = [
97
+ "cursor",
98
+ "limit",
99
+ "alias",
100
+ "slug",
101
+ "status",
102
+ "type",
103
+ ];
104
+ assertExhaustive(true);
105
+ exports.CREATE_RESOURCE_FIELD_KEYS = [
106
+ "name",
107
+ "private",
108
+ "consumer_access",
109
+ "type",
110
+ "target_url",
111
+ "description",
112
+ "tags",
113
+ "custom_domain",
114
+ "alias",
115
+ "slug",
116
+ "find_or_create",
117
+ ];
118
+ assertExhaustive(true);
119
+ exports.UPDATE_RESOURCE_FIELD_KEYS = [
120
+ "allowed_device_keys_add",
121
+ "allowed_device_keys_remove",
122
+ "consumer_access",
123
+ "expected_consumer_access_version",
124
+ "description",
125
+ "tags",
126
+ "custom_domain",
127
+ "preserve_host",
128
+ "alias",
129
+ ];
130
+ assertExhaustive(true);
131
+ exports.CREATE_QURL_FOR_RESOURCE_FIELD_KEYS = [
132
+ "expires_in",
133
+ "one_time_use",
134
+ "max_sessions",
135
+ "session_duration",
136
+ "label",
137
+ "access_policy",
138
+ "target_path",
139
+ ];
140
+ exports.SHARE_RESOURCE_OPTION_KEYS = [
141
+ "ttlSeconds",
142
+ ];
143
+ assertExhaustive(true);
144
+ assertExhaustive(true);
145
+ /**
146
+ * Options accepted by the portal-verb `protectUrl` / `createPortal`
147
+ * surface. These are camelCase caller-facing options (the portal verbs are
148
+ * the idiomatic layer); the build helpers map them onto the same wire
149
+ * fields the REST-shaped methods send.
150
+ */
151
+ exports.PROTECT_URL_OPTION_KEYS = [
152
+ "name",
153
+ "private",
154
+ "consumerAccess",
155
+ "description",
156
+ "tags",
157
+ "customDomain",
158
+ "alias",
159
+ ];
160
+ assertExhaustive(true);
161
+ exports.CREATE_PORTAL_OPTION_KEYS = [
162
+ "name",
163
+ "validFor",
164
+ "label",
165
+ "oneTimeUse",
166
+ "maxSessions",
167
+ "sessionDuration",
168
+ "targetPath",
169
+ ];
170
+ assertExhaustive(true);
171
+ exports.UPDATE_RESOURCE_QURL_FIELD_KEYS = [
172
+ "extend_by",
173
+ "expires_at",
174
+ "label",
175
+ "access_policy",
176
+ "max_sessions",
177
+ "session_duration",
178
+ ];
179
+ assertExhaustive(true);
180
+ exports.UPDATE_CUSTOMER_FIELD_KEYS = [
181
+ "spending_cap_cents",
182
+ ];
183
+ assertExhaustive(true);
184
+ exports.CREATE_BILLING_CHECKOUT_FIELD_KEYS = [
185
+ "plan",
186
+ ];
187
+ assertExhaustive(true);
188
+ exports.REGISTER_DOMAIN_FIELD_KEYS = [
189
+ "domain",
190
+ ];
191
+ assertExhaustive(true);
192
+ exports.CREATE_WEBHOOK_FIELD_KEYS = [
193
+ "url",
194
+ "events",
195
+ "description",
196
+ ];
197
+ assertExhaustive(true);
198
+ exports.UPDATE_WEBHOOK_FIELD_KEYS = [
199
+ "url",
200
+ "events",
201
+ "description",
202
+ "status",
203
+ ];
204
+ assertExhaustive(true);
205
+ exports.CREATE_API_KEY_FIELD_KEYS = [
206
+ "kind",
207
+ "name",
208
+ "scopes",
209
+ "target",
210
+ "claims",
211
+ "expires_in",
212
+ ];
213
+ assertExhaustive(true);
214
+ exports.UPDATE_API_KEY_FIELD_KEYS = [
215
+ "name",
216
+ "scopes",
217
+ ];
218
+ assertExhaustive(true);
219
+ exports.REDEEM_ACCESS_CODE_FIELD_KEYS = [
220
+ "code",
221
+ "honeypot",
222
+ "elapsed_ms",
223
+ ];
224
+ assertExhaustive(true);
225
+ exports.CREATE_ACCESS_CODE_FIELD_KEYS = [
226
+ "resource_id",
227
+ "name",
228
+ "max_uses",
229
+ "expires_at",
230
+ ];
231
+ assertExhaustive(true);
232
+ exports.CONNECTOR_INSTALLATION_LIST_PARAM_KEYS = [
233
+ "cursor",
234
+ "limit",
235
+ ];
236
+ assertExhaustive(true);
237
+ exports.BILLING_INVOICE_LIST_PARAM_KEYS = [
238
+ "limit",
239
+ "cursor",
240
+ ];
241
+ assertExhaustive(true);
242
+ exports.DOMAIN_LIST_PARAM_KEYS = [
243
+ "limit",
244
+ "cursor",
245
+ ];
246
+ assertExhaustive(true);
247
+ exports.WEBHOOK_LIST_PARAM_KEYS = [
248
+ "limit",
249
+ "cursor",
250
+ ];
251
+ assertExhaustive(true);
252
+ exports.WEBHOOK_DELIVERY_LIST_PARAM_KEYS = [
253
+ "limit",
254
+ "cursor",
255
+ ];
256
+ assertExhaustive(true);
257
+ exports.API_KEY_LIST_PARAM_KEYS = [
258
+ "limit",
259
+ "cursor",
260
+ "status",
261
+ ];
262
+ assertExhaustive(true);
@@ -0,0 +1,36 @@
1
+ export declare const MAX_RESPONSE_BODY_BYTES: number;
2
+ export declare const MAX_CONFIGURABLE_RESPONSE_BODY_BYTES: number;
3
+ export declare const MAX_ERROR_SNIPPET_BYTES = 512;
4
+ export declare const MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS = 512;
5
+ export declare const MAX_INVALID_FIELD_ENTRIES = 100;
6
+ export declare const MAX_DEBUG_BODY_KEYS = 100;
7
+ export declare const MAX_DIAGNOSTIC_COLLECTION_BYTES: number;
8
+ export declare const RETRY_BASE_DELAY_MS = 500;
9
+ export declare const RETRY_MAX_DELAY_MS = 30000;
10
+ export declare const RETRY_AFTER_HARD_CAP_MS: number;
11
+ export declare const RETRY_AFTER_PARSE_LIMIT_S: number;
12
+ export declare const MAX_IDEMPOTENCY_KEY = 256;
13
+ export declare const MAX_TARGET_URL = 2048;
14
+ export declare const MAX_LABEL = 500;
15
+ export declare const MAX_BATCH_ITEMS = 100;
16
+ export declare const MAX_DESCRIPTION = 500;
17
+ /** Code points, matching qurl-service ValidatePreviewName. */
18
+ export declare const MAX_RESOURCE_NAME = 100;
19
+ export declare const MAX_CUSTOM_DOMAIN = 253;
20
+ export declare const MAX_MAX_SESSIONS = 1000;
21
+ export declare const MAX_API_KEY_NAME = 100;
22
+ export declare const MAX_ENROLLMENT_TOKEN_TTL_SECONDS = 86400n;
23
+ export declare const MAX_ALIAS = 64;
24
+ export declare const MAX_SLUG = 64;
25
+ export declare const MAX_TARGET_PATH = 2048;
26
+ export declare const MAX_TAGS = 10;
27
+ export declare const MAX_TAG_LENGTH = 50;
28
+ export declare const MAX_AUTO_PAGINATION_PAGES = 10000;
29
+ export declare const MAX_DELEGATED_MINT_CAPABILITY = 8192;
30
+ export declare const MAX_DELEGATED_ETAG = 96;
31
+ export declare const MAX_DELEGATED_BATCH_ITEMS = 100;
32
+ export declare const MAX_PATH_ID_DECODE_PASSES = 3;
33
+ export declare const MAX_PATH_ID_LENGTH = 4096;
34
+ export declare const MAX_ALLOWED_DEVICE_KEYS = 256;
35
+ export declare const MAX_LIST_LIMIT = 100;
36
+ export declare const MAX_CONSUMER_CONTRACT_ID_BYTES = 128;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_CONSUMER_CONTRACT_ID_BYTES = exports.MAX_LIST_LIMIT = exports.MAX_ALLOWED_DEVICE_KEYS = exports.MAX_PATH_ID_LENGTH = exports.MAX_PATH_ID_DECODE_PASSES = exports.MAX_DELEGATED_BATCH_ITEMS = exports.MAX_DELEGATED_ETAG = exports.MAX_DELEGATED_MINT_CAPABILITY = exports.MAX_AUTO_PAGINATION_PAGES = exports.MAX_TAG_LENGTH = exports.MAX_TAGS = exports.MAX_TARGET_PATH = exports.MAX_SLUG = exports.MAX_ALIAS = exports.MAX_ENROLLMENT_TOKEN_TTL_SECONDS = exports.MAX_API_KEY_NAME = exports.MAX_MAX_SESSIONS = exports.MAX_CUSTOM_DOMAIN = exports.MAX_RESOURCE_NAME = exports.MAX_DESCRIPTION = exports.MAX_BATCH_ITEMS = exports.MAX_LABEL = exports.MAX_TARGET_URL = exports.MAX_IDEMPOTENCY_KEY = exports.RETRY_AFTER_PARSE_LIMIT_S = exports.RETRY_AFTER_HARD_CAP_MS = exports.RETRY_MAX_DELAY_MS = exports.RETRY_BASE_DELAY_MS = exports.MAX_DIAGNOSTIC_COLLECTION_BYTES = exports.MAX_DEBUG_BODY_KEYS = exports.MAX_INVALID_FIELD_ENTRIES = exports.MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS = exports.MAX_ERROR_SNIPPET_BYTES = exports.MAX_CONFIGURABLE_RESPONSE_BODY_BYTES = exports.MAX_RESPONSE_BODY_BYTES = void 0;
4
+ // Joint Go/TypeScript policy: docs/api-response-limits.md.
5
+ // Keep the 1 MiB default and bounded opt-in ceiling aligned across both SDKs.
6
+ // Decoded streaming bytes remain authoritative when length hints are unusable.
7
+ exports.MAX_RESPONSE_BODY_BYTES = 1 << 20;
8
+ exports.MAX_CONFIGURABLE_RESPONSE_BODY_BYTES = 16 << 20;
9
+ exports.MAX_ERROR_SNIPPET_BYTES = 512;
10
+ // UTF-8 uses at least one byte per UTF-16 code unit. Reading more source units
11
+ // cannot add a byte that fits in a 512-byte retained diagnostic.
12
+ exports.MAX_ERROR_SNIPPET_SOURCE_CODE_UNITS = exports.MAX_ERROR_SNIPPET_BYTES;
13
+ exports.MAX_INVALID_FIELD_ENTRIES = 100;
14
+ exports.MAX_DEBUG_BODY_KEYS = 100;
15
+ // Bound each retained diagnostic collection as well as each string. Without
16
+ // this aggregate cap, 100 valid 512-byte keys and values could turn a small
17
+ // server error into a large caller-visible object. This is a diagnostic budget,
18
+ // not part of the API wire contract.
19
+ exports.MAX_DIAGNOSTIC_COLLECTION_BYTES = 8 << 10;
20
+ exports.RETRY_BASE_DELAY_MS = 500;
21
+ // Bounds local exponential backoff (NOT server-asserted Retry-After —
22
+ // see `RETRY_AFTER_HARD_CAP_MS` for that).
23
+ exports.RETRY_MAX_DELAY_MS = 30_000;
24
+ // Hard cap on server-asserted Retry-After. Guards against `Retry-After`
25
+ // values >2^31-1 ms overflowing Node's setTimeout (silently truncated to
26
+ // 1ms — turns a "wait a month" directive into a hot retry loop).
27
+ exports.RETRY_AFTER_HARD_CAP_MS = 60 * 60 * 1000;
28
+ exports.RETRY_AFTER_PARSE_LIMIT_S = exports.RETRY_AFTER_HARD_CAP_MS / 1000;
29
+ exports.MAX_IDEMPOTENCY_KEY = 256;
30
+ // ---- Spec-derived validation helpers ------------------------------------
31
+ // These mirror constraints documented on each request schema in
32
+ // `openapi.yaml` so obvious mistakes fail fast instead of round-tripping
33
+ // to the API and coming back as a generic 400.
34
+ // CI checks every MAX_* constant against contract/validation-bounds.json; the
35
+ // weekly published-spec check detects upstream changes. Local safety budgets
36
+ // are classified separately and must not be raised to bypass a service cap.
37
+ exports.MAX_TARGET_URL = 2048;
38
+ exports.MAX_LABEL = 500;
39
+ exports.MAX_BATCH_ITEMS = 100;
40
+ exports.MAX_DESCRIPTION = 500;
41
+ /** Code points, matching qurl-service ValidatePreviewName. */
42
+ exports.MAX_RESOURCE_NAME = 100;
43
+ exports.MAX_CUSTOM_DOMAIN = 253;
44
+ exports.MAX_MAX_SESSIONS = 1000;
45
+ exports.MAX_API_KEY_NAME = 100;
46
+ exports.MAX_ENROLLMENT_TOKEN_TTL_SECONDS = 86400n;
47
+ exports.MAX_ALIAS = 64;
48
+ exports.MAX_SLUG = 64;
49
+ exports.MAX_TARGET_PATH = 2048;
50
+ exports.MAX_TAGS = 10;
51
+ exports.MAX_TAG_LENGTH = 50;
52
+ exports.MAX_AUTO_PAGINATION_PAGES = 10_000;
53
+ exports.MAX_DELEGATED_MINT_CAPABILITY = 8192;
54
+ exports.MAX_DELEGATED_ETAG = 96;
55
+ exports.MAX_DELEGATED_BATCH_ITEMS = 100;
56
+ exports.MAX_PATH_ID_DECODE_PASSES = 3;
57
+ exports.MAX_PATH_ID_LENGTH = 4096;
58
+ exports.MAX_ALLOWED_DEVICE_KEYS = 256;
59
+ exports.MAX_LIST_LIMIT = 100;
60
+ // Local UTF-8 budget; OpenAPI maxLength counts characters, not bytes.
61
+ exports.MAX_CONSUMER_CONTRACT_ID_BYTES = 128;