@the-open-engine/zeroshot 6.28.0 → 6.29.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 (283) hide show
  1. package/README.md +3 -3
  2. package/cli/index.js +20 -224
  3. package/docker/zeroshot-cluster/Dockerfile +2 -3
  4. package/lib/cluster/client.cjs +30 -7
  5. package/lib/cluster/client.d.cts +52 -0
  6. package/lib/cluster/client.d.mts +52 -0
  7. package/lib/cluster/client.d.ts +4 -6
  8. package/lib/cluster/client.mjs +32 -9
  9. package/lib/cluster/connection-state.cjs +25 -0
  10. package/lib/cluster/connection-state.d.cts +13 -0
  11. package/lib/cluster/connection-state.d.mts +13 -0
  12. package/lib/cluster/connection-state.d.ts +13 -0
  13. package/lib/cluster/connection-state.mjs +21 -0
  14. package/lib/cluster/connection-types.cjs +2 -0
  15. package/lib/cluster/connection-types.d.cts +33 -0
  16. package/lib/cluster/connection-types.d.mts +33 -0
  17. package/lib/cluster/connection-types.d.ts +33 -0
  18. package/lib/cluster/connection-types.mjs +1 -0
  19. package/lib/cluster/connection.cjs +18 -46
  20. package/lib/cluster/connection.d.cts +26 -0
  21. package/lib/cluster/connection.d.mts +26 -0
  22. package/lib/cluster/connection.d.ts +7 -25
  23. package/lib/cluster/connection.mjs +12 -42
  24. package/lib/cluster/errors.cjs +9 -1
  25. package/lib/cluster/errors.d.cts +29 -0
  26. package/lib/cluster/errors.d.mts +29 -0
  27. package/lib/cluster/errors.d.ts +4 -0
  28. package/lib/cluster/errors.mjs +7 -0
  29. package/lib/cluster/frames.d.cts +12 -0
  30. package/lib/cluster/frames.d.mts +12 -0
  31. package/lib/cluster/generated/protocol-schema.d.cts +1 -0
  32. package/lib/cluster/generated/protocol-schema.d.mts +1 -0
  33. package/lib/cluster/generated/protocol.d.cts +781 -0
  34. package/lib/cluster/generated/protocol.d.mts +781 -0
  35. package/lib/cluster/index.cjs +2 -2
  36. package/lib/cluster/index.d.cts +13 -0
  37. package/lib/cluster/index.d.mts +13 -0
  38. package/lib/cluster/index.d.ts +3 -3
  39. package/lib/cluster/index.mjs +2 -2
  40. package/lib/cluster/json-source.cjs +1 -0
  41. package/lib/cluster/json-source.d.cts +5 -0
  42. package/lib/cluster/json-source.d.mts +5 -0
  43. package/lib/cluster/json-source.d.ts +1 -0
  44. package/lib/cluster/json-source.mjs +1 -0
  45. package/lib/cluster/payload-value.cjs +1 -0
  46. package/lib/cluster/payload-value.d.cts +8 -0
  47. package/lib/cluster/payload-value.d.mts +8 -0
  48. package/lib/cluster/payload-value.d.ts +1 -0
  49. package/lib/cluster/payload-value.mjs +1 -0
  50. package/lib/cluster/queue.d.cts +15 -0
  51. package/lib/cluster/queue.d.mts +15 -0
  52. package/lib/cluster/socket.cjs +8 -0
  53. package/lib/cluster/socket.d.cts +13 -0
  54. package/lib/cluster/socket.d.mts +13 -0
  55. package/lib/cluster/socket.d.ts +2 -0
  56. package/lib/cluster/socket.mjs +7 -0
  57. package/lib/cluster/subscriptions.d.cts +73 -0
  58. package/lib/cluster/subscriptions.d.mts +73 -0
  59. package/lib/cluster/subscriptions.d.ts +5 -1
  60. package/lib/cluster/validators.cjs +1 -0
  61. package/lib/cluster/validators.d.cts +7 -0
  62. package/lib/cluster/validators.d.mts +7 -0
  63. package/lib/cluster/validators.d.ts +1 -0
  64. package/lib/cluster/validators.mjs +1 -0
  65. package/lib/cluster-worker/engine-adapter.js +1 -11
  66. package/lib/cluster-worker/engine-input.js +14 -0
  67. package/lib/hosted-session/authority.cjs +61 -0
  68. package/lib/hosted-session/authority.d.cts +3 -0
  69. package/lib/hosted-session/authority.d.mts +3 -0
  70. package/lib/hosted-session/authority.d.ts +3 -0
  71. package/lib/hosted-session/authority.mjs +57 -0
  72. package/lib/hosted-session/coordinator.cjs +78 -51
  73. package/lib/hosted-session/coordinator.d.cts +11 -0
  74. package/lib/hosted-session/coordinator.d.mts +11 -0
  75. package/lib/hosted-session/coordinator.d.ts +4 -2
  76. package/lib/hosted-session/coordinator.mjs +75 -51
  77. package/lib/hosted-session/errors.cjs +25 -0
  78. package/lib/hosted-session/errors.d.cts +10 -0
  79. package/lib/hosted-session/errors.d.mts +10 -0
  80. package/lib/hosted-session/errors.d.ts +10 -0
  81. package/lib/hosted-session/errors.mjs +19 -0
  82. package/lib/hosted-session/index.cjs +4 -1
  83. package/lib/hosted-session/index.d.cts +2 -0
  84. package/lib/hosted-session/index.d.mts +2 -0
  85. package/lib/hosted-session/index.d.ts +2 -2
  86. package/lib/hosted-session/index.mjs +1 -1
  87. package/lib/hosted-session/reconnecting-watch.cjs +131 -0
  88. package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
  89. package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
  90. package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
  91. package/lib/hosted-session/reconnecting-watch.mjs +127 -0
  92. package/lib/hosted-session/types.d.cts +32 -0
  93. package/lib/hosted-session/types.d.mts +32 -0
  94. package/lib/hosted-session/types.d.ts +19 -7
  95. package/lib/hosted-target/access-url.cjs +44 -0
  96. package/lib/hosted-target/access-url.d.cts +2 -0
  97. package/lib/hosted-target/access-url.d.mts +2 -0
  98. package/lib/hosted-target/access-url.d.ts +2 -0
  99. package/lib/hosted-target/access-url.mjs +41 -0
  100. package/lib/hosted-target/adapter-request.cjs +12 -0
  101. package/lib/hosted-target/adapter-request.d.cts +17 -0
  102. package/lib/hosted-target/adapter-request.d.mts +17 -0
  103. package/lib/hosted-target/adapter-request.d.ts +17 -0
  104. package/lib/hosted-target/adapter-request.mjs +9 -0
  105. package/lib/hosted-target/adapter-types.cjs +2 -0
  106. package/lib/hosted-target/adapter-types.d.cts +27 -0
  107. package/lib/hosted-target/adapter-types.d.mts +27 -0
  108. package/lib/hosted-target/adapter-types.d.ts +27 -0
  109. package/lib/hosted-target/adapter-types.mjs +1 -0
  110. package/lib/hosted-target/bounds.cjs +10 -0
  111. package/lib/hosted-target/bounds.d.cts +7 -0
  112. package/lib/hosted-target/bounds.d.mts +7 -0
  113. package/lib/hosted-target/bounds.d.ts +7 -0
  114. package/lib/hosted-target/bounds.mjs +7 -0
  115. package/lib/hosted-target/capsule-error-response.cjs +76 -0
  116. package/lib/hosted-target/capsule-error-response.d.cts +2 -0
  117. package/lib/hosted-target/capsule-error-response.d.mts +2 -0
  118. package/lib/hosted-target/capsule-error-response.d.ts +2 -0
  119. package/lib/hosted-target/capsule-error-response.mjs +73 -0
  120. package/lib/hosted-target/errors.cjs +88 -0
  121. package/lib/hosted-target/errors.d.cts +36 -0
  122. package/lib/hosted-target/errors.d.mts +36 -0
  123. package/lib/hosted-target/errors.d.ts +36 -0
  124. package/lib/hosted-target/errors.mjs +75 -0
  125. package/lib/hosted-target/index.cjs +16 -0
  126. package/lib/hosted-target/index.d.cts +3 -0
  127. package/lib/hosted-target/index.d.mts +3 -0
  128. package/lib/hosted-target/index.d.ts +3 -0
  129. package/lib/hosted-target/index.mjs +2 -0
  130. package/lib/hosted-target/response-validation.cjs +169 -0
  131. package/lib/hosted-target/response-validation.d.cts +5 -0
  132. package/lib/hosted-target/response-validation.d.mts +5 -0
  133. package/lib/hosted-target/response-validation.d.ts +5 -0
  134. package/lib/hosted-target/response-validation.mjs +163 -0
  135. package/lib/hosted-target/retry-executor.cjs +51 -0
  136. package/lib/hosted-target/retry-executor.d.cts +8 -0
  137. package/lib/hosted-target/retry-executor.d.mts +8 -0
  138. package/lib/hosted-target/retry-executor.d.ts +8 -0
  139. package/lib/hosted-target/retry-executor.mjs +48 -0
  140. package/lib/hosted-target/retry.cjs +78 -0
  141. package/lib/hosted-target/retry.d.cts +9 -0
  142. package/lib/hosted-target/retry.d.mts +9 -0
  143. package/lib/hosted-target/retry.d.ts +9 -0
  144. package/lib/hosted-target/retry.mjs +73 -0
  145. package/lib/hosted-target/target-adapter.cjs +10 -0
  146. package/lib/hosted-target/target-adapter.d.cts +3 -0
  147. package/lib/hosted-target/target-adapter.d.mts +3 -0
  148. package/lib/hosted-target/target-adapter.d.ts +3 -0
  149. package/lib/hosted-target/target-adapter.mjs +7 -0
  150. package/lib/hosted-target/types.cjs +4 -0
  151. package/lib/hosted-target/types.d.cts +50 -0
  152. package/lib/hosted-target/types.d.mts +50 -0
  153. package/lib/hosted-target/types.d.ts +50 -0
  154. package/lib/hosted-target/types.mjs +1 -0
  155. package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
  156. package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
  157. package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
  158. package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
  159. package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
  160. package/lib/target/bounded-response.cjs +51 -0
  161. package/lib/target/bounded-response.d.cts +1 -0
  162. package/lib/target/bounded-response.d.mts +1 -0
  163. package/lib/target/bounded-response.d.ts +1 -0
  164. package/lib/target/bounded-response.js +51 -0
  165. package/lib/target/bounded-response.mjs +48 -0
  166. package/lib/target/credential-lock.js +1 -3
  167. package/lib/target/credential-store.js +9 -4
  168. package/lib/target/device-flow.cjs +213 -0
  169. package/lib/target/device-flow.d.cts +54 -0
  170. package/lib/target/device-flow.d.mts +54 -0
  171. package/lib/target/device-flow.d.ts +26 -10
  172. package/lib/target/device-flow.js +162 -53
  173. package/lib/target/device-flow.mjs +203 -0
  174. package/lib/target/discovery-errors.cjs +10 -0
  175. package/lib/target/discovery-errors.d.cts +3 -0
  176. package/lib/target/discovery-errors.d.mts +3 -0
  177. package/lib/target/discovery-errors.d.ts +3 -0
  178. package/lib/target/discovery-errors.js +10 -0
  179. package/lib/target/discovery-errors.mjs +6 -0
  180. package/lib/target/discovery-sections.cjs +191 -0
  181. package/lib/target/discovery-sections.d.cts +52 -0
  182. package/lib/target/discovery-sections.d.mts +52 -0
  183. package/lib/target/discovery-sections.d.ts +52 -0
  184. package/lib/target/discovery-sections.js +191 -0
  185. package/lib/target/discovery-sections.mjs +179 -0
  186. package/lib/target/discovery-validation.cjs +109 -0
  187. package/lib/target/discovery-validation.d.cts +28 -0
  188. package/lib/target/discovery-validation.d.mts +28 -0
  189. package/lib/target/discovery-validation.d.ts +28 -0
  190. package/lib/target/discovery-validation.js +109 -0
  191. package/lib/target/discovery-validation.mjs +99 -0
  192. package/lib/target/discovery.cjs +112 -0
  193. package/lib/target/discovery.d.cts +74 -0
  194. package/lib/target/discovery.d.mts +74 -0
  195. package/lib/target/discovery.d.ts +68 -5
  196. package/lib/target/discovery.js +93 -101
  197. package/lib/target/discovery.mjs +105 -0
  198. package/lib/target/index.d.ts +6 -6
  199. package/lib/target/index.js +36 -36
  200. package/lib/target/oauth-http.d.ts +2 -0
  201. package/lib/target/oauth-http.js +25 -0
  202. package/lib/target/refresh-exchange.d.ts +11 -0
  203. package/lib/target/refresh-exchange.js +24 -0
  204. package/lib/target/refresh-revocation.d.ts +8 -0
  205. package/lib/target/refresh-revocation.js +19 -0
  206. package/lib/target/route-template.cjs +85 -0
  207. package/lib/target/route-template.d.cts +7 -0
  208. package/lib/target/route-template.d.mts +7 -0
  209. package/lib/target/route-template.d.ts +7 -0
  210. package/lib/target/route-template.js +85 -0
  211. package/lib/target/route-template.mjs +81 -0
  212. package/lib/target/session-errors.d.ts +4 -0
  213. package/lib/target/session-errors.js +12 -0
  214. package/lib/target/session-verification.d.ts +10 -0
  215. package/lib/target/session-verification.js +42 -0
  216. package/lib/target/target-registry.d.ts +7 -3
  217. package/lib/target/target-registry.js +41 -10
  218. package/lib/target/target-session-manager.d.ts +48 -0
  219. package/lib/target/target-session-manager.js +226 -0
  220. package/lib/target/target-session.d.ts +39 -31
  221. package/lib/target/target-session.js +63 -150
  222. package/lib/target/token-response.cjs +51 -0
  223. package/lib/target/token-response.d.cts +7 -0
  224. package/lib/target/token-response.d.mts +7 -0
  225. package/lib/target/token-response.d.ts +7 -0
  226. package/lib/target/token-response.js +51 -0
  227. package/lib/target/token-response.mjs +48 -0
  228. package/package.json +16 -6
  229. package/scripts/audit-production-dependencies.js +150 -0
  230. package/scripts/build-cluster.js +23 -3
  231. package/scripts/opcore-agent-gate.js +159 -0
  232. package/scripts/opcore-agent-tool-overlays.js +154 -0
  233. package/scripts/opcore-introduced-check.js +288 -0
  234. package/src/cluster/client.ts +42 -15
  235. package/src/cluster/connection-state.ts +33 -0
  236. package/src/cluster/connection-types.ts +28 -0
  237. package/src/cluster/connection.ts +37 -68
  238. package/src/cluster/errors.ts +5 -0
  239. package/src/cluster/index.ts +3 -1
  240. package/src/cluster/json-source.ts +1 -0
  241. package/src/cluster/payload-value.ts +1 -0
  242. package/src/cluster/socket.ts +13 -0
  243. package/src/cluster/subscriptions.ts +7 -2
  244. package/src/cluster/validators.ts +1 -0
  245. package/src/cluster/ws.d.ts +1 -1
  246. package/src/hosted-session/authority.ts +77 -0
  247. package/src/hosted-session/coordinator.ts +113 -56
  248. package/src/hosted-session/errors.ts +21 -0
  249. package/src/hosted-session/index.ts +14 -2
  250. package/src/hosted-session/reconnecting-watch.ts +148 -0
  251. package/src/hosted-session/types.ts +22 -8
  252. package/src/hosted-target/access-url.ts +46 -0
  253. package/src/hosted-target/adapter-request.ts +28 -0
  254. package/src/hosted-target/adapter-types.ts +39 -0
  255. package/src/hosted-target/bounds.ts +1 -0
  256. package/src/hosted-target/capsule-error-response.ts +107 -0
  257. package/src/hosted-target/errors.ts +36 -35
  258. package/src/hosted-target/index.ts +10 -23
  259. package/src/hosted-target/response-validation.ts +170 -62
  260. package/src/hosted-target/retry-executor.ts +62 -0
  261. package/src/hosted-target/retry.ts +47 -11
  262. package/src/hosted-target/target-adapter.ts +12 -8
  263. package/src/hosted-target/types.ts +19 -18
  264. package/src/hosted-target/zero-cloud-v1-adapter.ts +229 -316
  265. package/src/target/bounded-response.ts +68 -0
  266. package/src/target/credential-lock.ts +1 -3
  267. package/src/target/credential-store.ts +14 -10
  268. package/src/target/device-flow.ts +206 -71
  269. package/src/target/discovery-errors.ts +6 -0
  270. package/src/target/discovery-sections.ts +251 -0
  271. package/src/target/discovery-validation.ts +144 -0
  272. package/src/target/discovery.ts +163 -115
  273. package/src/target/index.ts +15 -11
  274. package/src/target/oauth-http.ts +27 -0
  275. package/src/target/refresh-exchange.ts +36 -0
  276. package/src/target/refresh-revocation.ts +29 -0
  277. package/src/target/route-template.ts +105 -0
  278. package/src/target/session-errors.ts +9 -0
  279. package/src/target/session-verification.ts +51 -0
  280. package/src/target/target-registry.ts +60 -27
  281. package/src/target/target-session-manager.ts +285 -0
  282. package/src/target/target-session.ts +105 -222
  283. package/src/target/token-response.ts +62 -0
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTargetAdapter = createTargetAdapter;
4
+ const zero_cloud_v1_adapter_js_1 = require("./zero-cloud-v1-adapter.cjs");
5
+ function createTargetAdapter(options) {
6
+ if (options.descriptor.adapter.majorVersion !== 1) {
7
+ throw new Error('Unsupported hosted target adapter version');
8
+ }
9
+ return new zero_cloud_v1_adapter_js_1.ZeroCloudV1TargetAdapter(options);
10
+ }
@@ -0,0 +1,3 @@
1
+ import type { CreateTargetAdapterOptions, TargetAdapter } from './adapter-types.js';
2
+ export type { CreateTargetAdapterOptions, CredentialInstallCapability, TargetAdapter, } from './adapter-types.js';
3
+ export declare function createTargetAdapter(options: CreateTargetAdapterOptions): TargetAdapter;
@@ -0,0 +1,3 @@
1
+ import type { CreateTargetAdapterOptions, TargetAdapter } from './adapter-types.js';
2
+ export type { CreateTargetAdapterOptions, CredentialInstallCapability, TargetAdapter, } from './adapter-types.js';
3
+ export declare function createTargetAdapter(options: CreateTargetAdapterOptions): TargetAdapter;
@@ -0,0 +1,3 @@
1
+ import type { CreateTargetAdapterOptions, TargetAdapter } from './adapter-types.js';
2
+ export type { CreateTargetAdapterOptions, CredentialInstallCapability, TargetAdapter, } from './adapter-types.js';
3
+ export declare function createTargetAdapter(options: CreateTargetAdapterOptions): TargetAdapter;
@@ -0,0 +1,7 @@
1
+ import { ZeroCloudV1TargetAdapter } from './zero-cloud-v1-adapter.mjs';
2
+ export function createTargetAdapter(options) {
3
+ if (options.descriptor.adapter.majorVersion !== 1) {
4
+ throw new Error('Unsupported hosted target adapter version');
5
+ }
6
+ return new ZeroCloudV1TargetAdapter(options);
7
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KNOWN_CAPSULE_STATES = void 0;
4
+ exports.KNOWN_CAPSULE_STATES = ['provisioning', 'ready', 'terminating', 'terminated', 'failed'];
@@ -0,0 +1,50 @@
1
+ import type { TargetAdapterError } from './errors.js';
2
+ export interface TargetAccessTokenProvider {
3
+ getAccessToken(signal?: AbortSignal): Promise<string>;
4
+ }
5
+ export type CapsuleState = 'provisioning' | 'ready' | 'terminating' | 'terminated' | 'failed';
6
+ export declare const KNOWN_CAPSULE_STATES: readonly ["provisioning", "ready", "terminating", "terminated", "failed"];
7
+ export interface Capsule {
8
+ readonly id: string;
9
+ readonly state: CapsuleState;
10
+ readonly label: string | null;
11
+ readonly createdAt: string;
12
+ }
13
+ export interface CapsuleAccess {
14
+ readonly protocol: 'openengine.cluster/v1';
15
+ readonly websocketUrl: string;
16
+ readonly accessToken: string;
17
+ readonly tokenType: 'Bearer';
18
+ readonly expiresAt: string;
19
+ }
20
+ export interface CapsuleListPage {
21
+ readonly capsules: readonly Capsule[];
22
+ readonly nextCursor: string | null;
23
+ }
24
+ export interface CapsuleLimits {
25
+ readonly activeCapsules: number;
26
+ readonly maxActiveCapsules: number | null;
27
+ }
28
+ export interface AllocateRequest {
29
+ readonly idempotencyKey: string;
30
+ readonly label?: string;
31
+ readonly size?: 'tiny' | 'small' | 'standard' | 'large';
32
+ }
33
+ export interface ListRequest {
34
+ readonly cursor?: string;
35
+ readonly limit?: number;
36
+ }
37
+ export interface HttpTransport {
38
+ fetch(url: string, init: RequestInit & {
39
+ redirect: 'manual';
40
+ }): Promise<Response>;
41
+ }
42
+ export interface Clock {
43
+ now(): number;
44
+ }
45
+ export interface RetryPolicy {
46
+ shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
47
+ retry: boolean;
48
+ delayMs: number;
49
+ };
50
+ }
@@ -0,0 +1,50 @@
1
+ import type { TargetAdapterError } from './errors.js';
2
+ export interface TargetAccessTokenProvider {
3
+ getAccessToken(signal?: AbortSignal): Promise<string>;
4
+ }
5
+ export type CapsuleState = 'provisioning' | 'ready' | 'terminating' | 'terminated' | 'failed';
6
+ export declare const KNOWN_CAPSULE_STATES: readonly ["provisioning", "ready", "terminating", "terminated", "failed"];
7
+ export interface Capsule {
8
+ readonly id: string;
9
+ readonly state: CapsuleState;
10
+ readonly label: string | null;
11
+ readonly createdAt: string;
12
+ }
13
+ export interface CapsuleAccess {
14
+ readonly protocol: 'openengine.cluster/v1';
15
+ readonly websocketUrl: string;
16
+ readonly accessToken: string;
17
+ readonly tokenType: 'Bearer';
18
+ readonly expiresAt: string;
19
+ }
20
+ export interface CapsuleListPage {
21
+ readonly capsules: readonly Capsule[];
22
+ readonly nextCursor: string | null;
23
+ }
24
+ export interface CapsuleLimits {
25
+ readonly activeCapsules: number;
26
+ readonly maxActiveCapsules: number | null;
27
+ }
28
+ export interface AllocateRequest {
29
+ readonly idempotencyKey: string;
30
+ readonly label?: string;
31
+ readonly size?: 'tiny' | 'small' | 'standard' | 'large';
32
+ }
33
+ export interface ListRequest {
34
+ readonly cursor?: string;
35
+ readonly limit?: number;
36
+ }
37
+ export interface HttpTransport {
38
+ fetch(url: string, init: RequestInit & {
39
+ redirect: 'manual';
40
+ }): Promise<Response>;
41
+ }
42
+ export interface Clock {
43
+ now(): number;
44
+ }
45
+ export interface RetryPolicy {
46
+ shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
47
+ retry: boolean;
48
+ delayMs: number;
49
+ };
50
+ }
@@ -0,0 +1,50 @@
1
+ import type { TargetAdapterError } from './errors.js';
2
+ export interface TargetAccessTokenProvider {
3
+ getAccessToken(signal?: AbortSignal): Promise<string>;
4
+ }
5
+ export type CapsuleState = 'provisioning' | 'ready' | 'terminating' | 'terminated' | 'failed';
6
+ export declare const KNOWN_CAPSULE_STATES: readonly ["provisioning", "ready", "terminating", "terminated", "failed"];
7
+ export interface Capsule {
8
+ readonly id: string;
9
+ readonly state: CapsuleState;
10
+ readonly label: string | null;
11
+ readonly createdAt: string;
12
+ }
13
+ export interface CapsuleAccess {
14
+ readonly protocol: 'openengine.cluster/v1';
15
+ readonly websocketUrl: string;
16
+ readonly accessToken: string;
17
+ readonly tokenType: 'Bearer';
18
+ readonly expiresAt: string;
19
+ }
20
+ export interface CapsuleListPage {
21
+ readonly capsules: readonly Capsule[];
22
+ readonly nextCursor: string | null;
23
+ }
24
+ export interface CapsuleLimits {
25
+ readonly activeCapsules: number;
26
+ readonly maxActiveCapsules: number | null;
27
+ }
28
+ export interface AllocateRequest {
29
+ readonly idempotencyKey: string;
30
+ readonly label?: string;
31
+ readonly size?: 'tiny' | 'small' | 'standard' | 'large';
32
+ }
33
+ export interface ListRequest {
34
+ readonly cursor?: string;
35
+ readonly limit?: number;
36
+ }
37
+ export interface HttpTransport {
38
+ fetch(url: string, init: RequestInit & {
39
+ redirect: 'manual';
40
+ }): Promise<Response>;
41
+ }
42
+ export interface Clock {
43
+ now(): number;
44
+ }
45
+ export interface RetryPolicy {
46
+ shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
47
+ retry: boolean;
48
+ delayMs: number;
49
+ };
50
+ }
@@ -0,0 +1 @@
1
+ export const KNOWN_CAPSULE_STATES = ['provisioning', 'ready', 'terminating', 'terminated', 'failed'];
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZeroCloudV1TargetAdapter = void 0;
4
+ const bounds_js_1 = require("./bounds.cjs");
5
+ const errors_js_1 = require("./errors.cjs");
6
+ const retry_js_1 = require("./retry.cjs");
7
+ const response_validation_js_1 = require("./response-validation.cjs");
8
+ const bounded_response_js_1 = require("../target/bounded-response.cjs");
9
+ const capsule_error_response_js_1 = require("./capsule-error-response.cjs");
10
+ const access_url_js_1 = require("./access-url.cjs");
11
+ const retry_executor_js_1 = require("./retry-executor.cjs");
12
+ const adapter_request_js_1 = require("./adapter-request.cjs");
13
+ const DEFAULT_TRANSPORT = {
14
+ fetch(url, init) {
15
+ return globalThis.fetch(url, init);
16
+ },
17
+ };
18
+ const DEFAULT_CLOCK = { now: () => Date.now() };
19
+ function throwIfAborted(signal) {
20
+ if (signal?.aborted)
21
+ throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
22
+ }
23
+ function validOpaque(value, field) {
24
+ if (value.length === 0 || value.length > 1024)
25
+ throw new errors_js_1.TargetProtocolError(`${field} is invalid`);
26
+ }
27
+ function jsonRequest(body) {
28
+ return JSON.stringify(body);
29
+ }
30
+ class ZeroCloudV1TargetAdapter {
31
+ #descriptor;
32
+ #organizationId;
33
+ #tokenProvider;
34
+ #transport;
35
+ #clock;
36
+ #retryPolicy;
37
+ constructor(options) {
38
+ this.#descriptor = options.descriptor;
39
+ this.#organizationId = options.organization.id;
40
+ validOpaque(this.#organizationId, 'organization id');
41
+ this.#tokenProvider = options.tokenProvider;
42
+ this.#transport = options.transport ?? DEFAULT_TRANSPORT;
43
+ this.#clock = options.clock ?? DEFAULT_CLOCK;
44
+ this.#retryPolicy = options.retryPolicy ?? new retry_js_1.DefaultRetryPolicy();
45
+ }
46
+ get credentialInstall() {
47
+ const descriptor = this.#descriptor.credentialInstall;
48
+ return descriptor === null
49
+ ? Object.freeze({ supported: false })
50
+ : Object.freeze({ supported: true, descriptor });
51
+ }
52
+ allocate(request, signal) {
53
+ try {
54
+ if (!bounds_js_1.IDEMPOTENCY_KEY_PATTERN.test(request.idempotencyKey))
55
+ throw new errors_js_1.TargetProtocolError('Idempotency key is invalid');
56
+ if (request.label !== undefined && (request.label.length < 1 || request.label.length > 100)) {
57
+ throw new errors_js_1.TargetProtocolError('Capsule label is outside the supported bounds');
58
+ }
59
+ if (request.size !== undefined && !this.#descriptor.sizes.catalog.includes(request.size)) {
60
+ throw new errors_js_1.TargetProtocolError('Capsule size is not advertised by the target');
61
+ }
62
+ const body = {
63
+ ...(request.label === undefined ? {} : { label: request.label }),
64
+ ...(request.size === undefined ? {} : { size: request.size }),
65
+ };
66
+ return this.#execute('allocate', 'POST', this.#descriptor.capsule.routes.allocate, { org_id: this.#organizationId }, 201, response_validation_js_1.assertCapsule, signal, {
67
+ body: jsonRequest(body),
68
+ headers: { 'Idempotency-Key': request.idempotencyKey },
69
+ });
70
+ }
71
+ catch (error) {
72
+ return Promise.reject(error);
73
+ }
74
+ }
75
+ async list(request = {}, signal) {
76
+ if (request.cursor !== undefined)
77
+ validOpaque(request.cursor, 'cursor');
78
+ if (request.limit !== undefined &&
79
+ (!Number.isSafeInteger(request.limit) ||
80
+ request.limit < 1 ||
81
+ request.limit > this.#descriptor.pagination.maxPageSize)) {
82
+ throw new errors_js_1.TargetProtocolError('Pagination limit is outside the advertised bounds');
83
+ }
84
+ const page = await this.#execute('list', 'GET', this.#descriptor.capsule.routes.list, {
85
+ org_id: this.#organizationId,
86
+ cursor: request.cursor,
87
+ limit: request.limit,
88
+ }, 200, response_validation_js_1.assertCapsuleListPage, signal);
89
+ if (request.cursor !== undefined && page.nextCursor === request.cursor)
90
+ throw new errors_js_1.TargetProtocolError('Target returned a pagination loop');
91
+ return page;
92
+ }
93
+ inspect(capsuleId, signal) {
94
+ validOpaque(capsuleId, 'capsule id');
95
+ return this.#execute('inspect', 'GET', this.#descriptor.capsule.routes.inspect, { org_id: this.#organizationId, capsule_id: capsuleId }, 200, response_validation_js_1.assertCapsule, signal);
96
+ }
97
+ terminate(capsuleId, signal) {
98
+ validOpaque(capsuleId, 'capsule id');
99
+ return this.#execute('terminate', 'DELETE', this.#descriptor.capsule.routes.terminate, { org_id: this.#organizationId, capsule_id: capsuleId }, 202, response_validation_js_1.assertCapsule, signal);
100
+ }
101
+ limits(signal) {
102
+ return this.#execute('limits', 'GET', this.#descriptor.capsule.routes.limits, { org_id: this.#organizationId }, 200, response_validation_js_1.assertCapsuleLimits, signal);
103
+ }
104
+ async access(capsuleId, signal) {
105
+ validOpaque(capsuleId, 'capsule id');
106
+ const result = await this.#execute('access', 'POST', this.#descriptor.capsule.routes.access, { capsule_id: capsuleId }, 200, response_validation_js_1.assertCapsuleAccess, signal, {
107
+ body: jsonRequest({ protocol: 'openengine.cluster/v1' }),
108
+ });
109
+ (0, access_url_js_1.validateAccessUrl)(result.websocketUrl, capsuleId, this.#descriptor);
110
+ return result;
111
+ }
112
+ #execute(...args) {
113
+ return Promise.resolve().then(() => this.#executeExpanded(args));
114
+ }
115
+ #executeExpanded(args) {
116
+ const [operation, method, template, values, expectedStatus, validate, signal, request = {},] = args;
117
+ let path;
118
+ try {
119
+ path = template.expand(values);
120
+ }
121
+ catch {
122
+ throw new errors_js_1.TargetProtocolError('Capsule route expansion is unsafe');
123
+ }
124
+ return (0, retry_executor_js_1.withTargetRetry)(operation, async () => {
125
+ const response = await this.#request(method, path, signal, request);
126
+ if (response.status >= 300 && response.status < 400) {
127
+ await response.body?.cancel().catch(() => undefined);
128
+ throw new errors_js_1.TargetProtocolError('Capsule redirects are forbidden');
129
+ }
130
+ if (response.status !== expectedStatus) {
131
+ if (response.status >= 200 && response.status < 300) {
132
+ await response.body?.cancel().catch(() => undefined);
133
+ throw new errors_js_1.TargetProtocolError('Target returned an unexpected success status');
134
+ }
135
+ await (0, capsule_error_response_js_1.throwCapsuleServerError)(response, (errorResponse) => this.#readJson(errorResponse), this.#clock);
136
+ }
137
+ return validate(await this.#readJson(response));
138
+ }, signal, { clock: this.#clock, policy: this.#retryPolicy });
139
+ }
140
+ async #request(method, path, signal, request) {
141
+ throwIfAborted(signal);
142
+ const url = (0, adapter_request_js_1.requestUrl)(path, this.#descriptor);
143
+ let token;
144
+ try {
145
+ token = await this.#tokenProvider.getAccessToken(signal);
146
+ }
147
+ catch {
148
+ throw new errors_js_1.TargetAuthError('Target access authorization failed');
149
+ }
150
+ const init = {
151
+ method,
152
+ headers: {
153
+ Accept: 'application/json',
154
+ Authorization: `Bearer ${token}`,
155
+ ...(request.body === undefined ? {} : { 'Content-Type': 'application/json' }),
156
+ ...request.headers,
157
+ },
158
+ redirect: 'manual',
159
+ };
160
+ if (request.body !== undefined)
161
+ init.body = request.body;
162
+ if (signal !== undefined)
163
+ init.signal = signal;
164
+ try {
165
+ const response = await this.#transport.fetch(url.href, init);
166
+ if (response.url && new globalThis.URL(response.url).href !== url.href) {
167
+ await response.body?.cancel().catch(() => undefined);
168
+ throw new errors_js_1.TargetProtocolError('Capsule response changed target route');
169
+ }
170
+ return response;
171
+ }
172
+ catch (error) {
173
+ if (error instanceof errors_js_1.TargetAdapterError)
174
+ throw error;
175
+ throwIfAborted(signal);
176
+ throw new errors_js_1.TargetTransportError('Capsule transport failed');
177
+ }
178
+ }
179
+ #readJson(response) {
180
+ return (0, bounded_response_js_1.readBoundedResponseJson)(response, bounds_js_1.MAX_RESPONSE_BYTES, (kind) => new errors_js_1.TargetProtocolError(kind === 'size'
181
+ ? 'Capsule response exceeds the size limit'
182
+ : 'Capsule response is not valid UTF-8 JSON'));
183
+ }
184
+ }
185
+ exports.ZeroCloudV1TargetAdapter = ZeroCloudV1TargetAdapter;
@@ -0,0 +1,13 @@
1
+ import type { TargetAdapter, CreateTargetAdapterOptions } from './adapter-types.js';
2
+ import type { AllocateRequest, Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage, ListRequest } from './types.js';
3
+ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
4
+ #private;
5
+ constructor(options: CreateTargetAdapterOptions);
6
+ get credentialInstall(): TargetAdapter['credentialInstall'];
7
+ allocate(request: AllocateRequest, signal?: AbortSignal): Promise<Capsule>;
8
+ list(request?: ListRequest, signal?: AbortSignal): Promise<CapsuleListPage>;
9
+ inspect(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
10
+ terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
11
+ limits(signal?: AbortSignal): Promise<CapsuleLimits>;
12
+ access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
13
+ }
@@ -0,0 +1,13 @@
1
+ import type { TargetAdapter, CreateTargetAdapterOptions } from './adapter-types.js';
2
+ import type { AllocateRequest, Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage, ListRequest } from './types.js';
3
+ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
4
+ #private;
5
+ constructor(options: CreateTargetAdapterOptions);
6
+ get credentialInstall(): TargetAdapter['credentialInstall'];
7
+ allocate(request: AllocateRequest, signal?: AbortSignal): Promise<Capsule>;
8
+ list(request?: ListRequest, signal?: AbortSignal): Promise<CapsuleListPage>;
9
+ inspect(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
10
+ terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
11
+ limits(signal?: AbortSignal): Promise<CapsuleLimits>;
12
+ access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
13
+ }
@@ -0,0 +1,13 @@
1
+ import type { TargetAdapter, CreateTargetAdapterOptions } from './adapter-types.js';
2
+ import type { AllocateRequest, Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage, ListRequest } from './types.js';
3
+ export declare class ZeroCloudV1TargetAdapter implements TargetAdapter {
4
+ #private;
5
+ constructor(options: CreateTargetAdapterOptions);
6
+ get credentialInstall(): TargetAdapter['credentialInstall'];
7
+ allocate(request: AllocateRequest, signal?: AbortSignal): Promise<Capsule>;
8
+ list(request?: ListRequest, signal?: AbortSignal): Promise<CapsuleListPage>;
9
+ inspect(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
10
+ terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
11
+ limits(signal?: AbortSignal): Promise<CapsuleLimits>;
12
+ access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
13
+ }
@@ -0,0 +1,181 @@
1
+ import { IDEMPOTENCY_KEY_PATTERN, MAX_RESPONSE_BYTES } from './bounds.mjs';
2
+ import { TargetAdapterError, TargetAuthError, TargetProtocolError, TargetTransportError, } from './errors.mjs';
3
+ import { DefaultRetryPolicy } from './retry.mjs';
4
+ import { assertCapsule, assertCapsuleAccess, assertCapsuleLimits, assertCapsuleListPage, } from './response-validation.mjs';
5
+ import { readBoundedResponseJson } from '../target/bounded-response.mjs';
6
+ import { throwCapsuleServerError } from './capsule-error-response.mjs';
7
+ import { validateAccessUrl } from './access-url.mjs';
8
+ import { withTargetRetry } from './retry-executor.mjs';
9
+ import { requestUrl, } from './adapter-request.mjs';
10
+ const DEFAULT_TRANSPORT = {
11
+ fetch(url, init) {
12
+ return globalThis.fetch(url, init);
13
+ },
14
+ };
15
+ const DEFAULT_CLOCK = { now: () => Date.now() };
16
+ function throwIfAborted(signal) {
17
+ if (signal?.aborted)
18
+ throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
19
+ }
20
+ function validOpaque(value, field) {
21
+ if (value.length === 0 || value.length > 1024)
22
+ throw new TargetProtocolError(`${field} is invalid`);
23
+ }
24
+ function jsonRequest(body) {
25
+ return JSON.stringify(body);
26
+ }
27
+ export class ZeroCloudV1TargetAdapter {
28
+ #descriptor;
29
+ #organizationId;
30
+ #tokenProvider;
31
+ #transport;
32
+ #clock;
33
+ #retryPolicy;
34
+ constructor(options) {
35
+ this.#descriptor = options.descriptor;
36
+ this.#organizationId = options.organization.id;
37
+ validOpaque(this.#organizationId, 'organization id');
38
+ this.#tokenProvider = options.tokenProvider;
39
+ this.#transport = options.transport ?? DEFAULT_TRANSPORT;
40
+ this.#clock = options.clock ?? DEFAULT_CLOCK;
41
+ this.#retryPolicy = options.retryPolicy ?? new DefaultRetryPolicy();
42
+ }
43
+ get credentialInstall() {
44
+ const descriptor = this.#descriptor.credentialInstall;
45
+ return descriptor === null
46
+ ? Object.freeze({ supported: false })
47
+ : Object.freeze({ supported: true, descriptor });
48
+ }
49
+ allocate(request, signal) {
50
+ try {
51
+ if (!IDEMPOTENCY_KEY_PATTERN.test(request.idempotencyKey))
52
+ throw new TargetProtocolError('Idempotency key is invalid');
53
+ if (request.label !== undefined && (request.label.length < 1 || request.label.length > 100)) {
54
+ throw new TargetProtocolError('Capsule label is outside the supported bounds');
55
+ }
56
+ if (request.size !== undefined && !this.#descriptor.sizes.catalog.includes(request.size)) {
57
+ throw new TargetProtocolError('Capsule size is not advertised by the target');
58
+ }
59
+ const body = {
60
+ ...(request.label === undefined ? {} : { label: request.label }),
61
+ ...(request.size === undefined ? {} : { size: request.size }),
62
+ };
63
+ return this.#execute('allocate', 'POST', this.#descriptor.capsule.routes.allocate, { org_id: this.#organizationId }, 201, assertCapsule, signal, {
64
+ body: jsonRequest(body),
65
+ headers: { 'Idempotency-Key': request.idempotencyKey },
66
+ });
67
+ }
68
+ catch (error) {
69
+ return Promise.reject(error);
70
+ }
71
+ }
72
+ async list(request = {}, signal) {
73
+ if (request.cursor !== undefined)
74
+ validOpaque(request.cursor, 'cursor');
75
+ if (request.limit !== undefined &&
76
+ (!Number.isSafeInteger(request.limit) ||
77
+ request.limit < 1 ||
78
+ request.limit > this.#descriptor.pagination.maxPageSize)) {
79
+ throw new TargetProtocolError('Pagination limit is outside the advertised bounds');
80
+ }
81
+ const page = await this.#execute('list', 'GET', this.#descriptor.capsule.routes.list, {
82
+ org_id: this.#organizationId,
83
+ cursor: request.cursor,
84
+ limit: request.limit,
85
+ }, 200, assertCapsuleListPage, signal);
86
+ if (request.cursor !== undefined && page.nextCursor === request.cursor)
87
+ throw new TargetProtocolError('Target returned a pagination loop');
88
+ return page;
89
+ }
90
+ inspect(capsuleId, signal) {
91
+ validOpaque(capsuleId, 'capsule id');
92
+ return this.#execute('inspect', 'GET', this.#descriptor.capsule.routes.inspect, { org_id: this.#organizationId, capsule_id: capsuleId }, 200, assertCapsule, signal);
93
+ }
94
+ terminate(capsuleId, signal) {
95
+ validOpaque(capsuleId, 'capsule id');
96
+ return this.#execute('terminate', 'DELETE', this.#descriptor.capsule.routes.terminate, { org_id: this.#organizationId, capsule_id: capsuleId }, 202, assertCapsule, signal);
97
+ }
98
+ limits(signal) {
99
+ return this.#execute('limits', 'GET', this.#descriptor.capsule.routes.limits, { org_id: this.#organizationId }, 200, assertCapsuleLimits, signal);
100
+ }
101
+ async access(capsuleId, signal) {
102
+ validOpaque(capsuleId, 'capsule id');
103
+ const result = await this.#execute('access', 'POST', this.#descriptor.capsule.routes.access, { capsule_id: capsuleId }, 200, assertCapsuleAccess, signal, {
104
+ body: jsonRequest({ protocol: 'openengine.cluster/v1' }),
105
+ });
106
+ validateAccessUrl(result.websocketUrl, capsuleId, this.#descriptor);
107
+ return result;
108
+ }
109
+ #execute(...args) {
110
+ return Promise.resolve().then(() => this.#executeExpanded(args));
111
+ }
112
+ #executeExpanded(args) {
113
+ const [operation, method, template, values, expectedStatus, validate, signal, request = {},] = args;
114
+ let path;
115
+ try {
116
+ path = template.expand(values);
117
+ }
118
+ catch {
119
+ throw new TargetProtocolError('Capsule route expansion is unsafe');
120
+ }
121
+ return withTargetRetry(operation, async () => {
122
+ const response = await this.#request(method, path, signal, request);
123
+ if (response.status >= 300 && response.status < 400) {
124
+ await response.body?.cancel().catch(() => undefined);
125
+ throw new TargetProtocolError('Capsule redirects are forbidden');
126
+ }
127
+ if (response.status !== expectedStatus) {
128
+ if (response.status >= 200 && response.status < 300) {
129
+ await response.body?.cancel().catch(() => undefined);
130
+ throw new TargetProtocolError('Target returned an unexpected success status');
131
+ }
132
+ await throwCapsuleServerError(response, (errorResponse) => this.#readJson(errorResponse), this.#clock);
133
+ }
134
+ return validate(await this.#readJson(response));
135
+ }, signal, { clock: this.#clock, policy: this.#retryPolicy });
136
+ }
137
+ async #request(method, path, signal, request) {
138
+ throwIfAborted(signal);
139
+ const url = requestUrl(path, this.#descriptor);
140
+ let token;
141
+ try {
142
+ token = await this.#tokenProvider.getAccessToken(signal);
143
+ }
144
+ catch {
145
+ throw new TargetAuthError('Target access authorization failed');
146
+ }
147
+ const init = {
148
+ method,
149
+ headers: {
150
+ Accept: 'application/json',
151
+ Authorization: `Bearer ${token}`,
152
+ ...(request.body === undefined ? {} : { 'Content-Type': 'application/json' }),
153
+ ...request.headers,
154
+ },
155
+ redirect: 'manual',
156
+ };
157
+ if (request.body !== undefined)
158
+ init.body = request.body;
159
+ if (signal !== undefined)
160
+ init.signal = signal;
161
+ try {
162
+ const response = await this.#transport.fetch(url.href, init);
163
+ if (response.url && new globalThis.URL(response.url).href !== url.href) {
164
+ await response.body?.cancel().catch(() => undefined);
165
+ throw new TargetProtocolError('Capsule response changed target route');
166
+ }
167
+ return response;
168
+ }
169
+ catch (error) {
170
+ if (error instanceof TargetAdapterError)
171
+ throw error;
172
+ throwIfAborted(signal);
173
+ throw new TargetTransportError('Capsule transport failed');
174
+ }
175
+ }
176
+ #readJson(response) {
177
+ return readBoundedResponseJson(response, MAX_RESPONSE_BYTES, (kind) => new TargetProtocolError(kind === 'size'
178
+ ? 'Capsule response exceeds the size limit'
179
+ : 'Capsule response is not valid UTF-8 JSON'));
180
+ }
181
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readBoundedResponseJson = readBoundedResponseJson;
4
+ async function declaredResponseBytes(response, maxBytes, error) {
5
+ const declared = response.headers.get('content-length');
6
+ if (declared === null)
7
+ return 0;
8
+ if (!/^\d+$/.test(declared) || Number(declared) > maxBytes) {
9
+ await response.body?.cancel().catch(() => undefined);
10
+ throw error('size');
11
+ }
12
+ return Number(declared);
13
+ }
14
+ function growBuffer(bytes, required, used, maxBytes) {
15
+ const capacity = Math.min(maxBytes, Math.max(required, Math.max(bytes.byteLength * 2, 8 * 1024)));
16
+ const grown = new Uint8Array(capacity);
17
+ grown.set(bytes.subarray(0, used));
18
+ return grown;
19
+ }
20
+ function decodeJson(bytes, error) {
21
+ try {
22
+ return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
23
+ }
24
+ catch {
25
+ throw error('json');
26
+ }
27
+ }
28
+ async function readBoundedResponseJson(response, maxBytes, error) {
29
+ const declaredBytes = await declaredResponseBytes(response, maxBytes, error);
30
+ const reader = response.body?.getReader();
31
+ if (reader === undefined)
32
+ return decodeJson(new Uint8Array(), error);
33
+ let bytes = new Uint8Array(Math.min(maxBytes, Math.max(declaredBytes, 8 * 1024)));
34
+ let total = 0;
35
+ while (true) {
36
+ const { done, value } = await reader.read();
37
+ if (done)
38
+ break;
39
+ const nextTotal = total + value.byteLength;
40
+ if (nextTotal > maxBytes) {
41
+ await reader.cancel().catch(() => undefined);
42
+ throw error('size');
43
+ }
44
+ if (nextTotal > bytes.byteLength) {
45
+ bytes = growBuffer(bytes, nextTotal, total, maxBytes);
46
+ }
47
+ bytes.set(value, total);
48
+ total = nextTotal;
49
+ }
50
+ return decodeJson(bytes.subarray(0, total), error);
51
+ }
@@ -0,0 +1 @@
1
+ export declare function readBoundedResponseJson(response: Response, maxBytes: number, error: (kind: 'size' | 'json') => Error): Promise<unknown>;
@@ -0,0 +1 @@
1
+ export declare function readBoundedResponseJson(response: Response, maxBytes: number, error: (kind: 'size' | 'json') => Error): Promise<unknown>;