@hypequery/deployment 0.0.0-canary-20260719200737 → 0.2.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.
- package/README.md +2 -95
- package/dist/activation.d.ts +0 -11
- package/dist/activation.d.ts.map +1 -1
- package/dist/activation.js +19 -100
- package/dist/index.d.ts +2 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -7
- package/package.json +3 -3
- package/dist/control-plane-adapters.d.ts +0 -7
- package/dist/control-plane-adapters.d.ts.map +0 -1
- package/dist/control-plane-adapters.js +0 -163
- package/dist/control-plane-limits.d.ts +0 -7
- package/dist/control-plane-limits.d.ts.map +0 -1
- package/dist/control-plane-limits.js +0 -18
- package/dist/control-plane.d.ts +0 -35
- package/dist/control-plane.d.ts.map +0 -1
- package/dist/control-plane.js +0 -362
- package/dist/node-runtime-factory.d.ts +0 -16
- package/dist/node-runtime-factory.d.ts.map +0 -1
- package/dist/node-runtime-factory.js +0 -274
- package/dist/runtime-materialization.d.ts +0 -58
- package/dist/runtime-materialization.d.ts.map +0 -1
- package/dist/runtime-materialization.js +0 -187
- package/dist/runtime-supervisor.d.ts +0 -70
- package/dist/runtime-supervisor.d.ts.map +0 -1
- package/dist/runtime-supervisor.js +0 -254
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @hypequery/deployment
|
|
2
2
|
|
|
3
|
-
Provider-neutral verification
|
|
4
|
-
|
|
3
|
+
Provider-neutral verification and receiving-side intake for Hypequery deployment
|
|
4
|
+
bundles.
|
|
5
5
|
|
|
6
6
|
The package accepts the authenticated multipart transport emitted by
|
|
7
7
|
`hypequery deploy`, reconstructs only manifest-declared files in temporary
|
|
@@ -152,97 +152,4 @@ append-only chain. It has no mutable pointer file or persistent lock to become
|
|
|
152
152
|
stale after a crash. Activation does not load runtime code, route traffic,
|
|
153
153
|
perform health checks, or authorize callers; those remain provider concerns.
|
|
154
154
|
|
|
155
|
-
## HTTP control plane
|
|
156
|
-
|
|
157
|
-
`createDeploymentControlPlane` combines intake and activation behind closed v1
|
|
158
|
-
routes. Activation reads and writes use a separate target-scoped authorizer;
|
|
159
|
-
write authorization completes before the small JSON request body is consumed.
|
|
160
|
-
The Fetch and Node adapters preserve streaming multipart submission bodies.
|
|
161
|
-
|
|
162
|
-
```ts
|
|
163
|
-
import {
|
|
164
|
-
createDeploymentControlPlane,
|
|
165
|
-
createDeploymentControlPlaneNodeHandler,
|
|
166
|
-
} from '@hypequery/deployment';
|
|
167
|
-
|
|
168
|
-
const controlPlane = createDeploymentControlPlane({
|
|
169
|
-
intake,
|
|
170
|
-
activations,
|
|
171
|
-
authenticator,
|
|
172
|
-
authorizer: {
|
|
173
|
-
async authorize({ principal, action, target }) {
|
|
174
|
-
return canControlDeployment(principal, action, target);
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const nodeHandler = createDeploymentControlPlaneNodeHandler(controlPlane);
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
The control plane exposes release submission, compare-and-swap activation,
|
|
183
|
-
current state, and bounded cursor history. It returns stable, bounded JSON error
|
|
184
|
-
codes and suppresses internal provider and filesystem details. The HTTP
|
|
185
|
-
contract is specified in `specs/deployment/0003-control-plane-http.md`.
|
|
186
|
-
|
|
187
|
-
## Runtime materialization
|
|
188
|
-
|
|
189
|
-
`createDeploymentRuntimeMaterializer` converts the current target activation
|
|
190
|
-
into a private runtime snapshot. It revalidates the accepted release and closed
|
|
191
|
-
bundle, copies and hashes each runtime artifact without following symbolic
|
|
192
|
-
links, and confirms the activation revision again before returning.
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
import { createDeploymentRuntimeMaterializer } from '@hypequery/deployment';
|
|
196
|
-
|
|
197
|
-
const materializer = createDeploymentRuntimeMaterializer({
|
|
198
|
-
activations,
|
|
199
|
-
releases: store,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const snapshot = await materializer.current({
|
|
203
|
-
project: 'analytics',
|
|
204
|
-
environment: 'production',
|
|
205
|
-
});
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
Artifact `read()` methods return fresh byte copies, so neither callers nor later
|
|
209
|
-
changes to durable storage can alter a materialized snapshot. Runtime imports,
|
|
210
|
-
process lifecycle, readiness, and traffic switching remain separate concerns.
|
|
211
|
-
|
|
212
|
-
## Runtime supervision
|
|
213
|
-
|
|
214
|
-
`createDeploymentRuntimeSupervisor` starts materialized snapshots through a
|
|
215
|
-
runtime factory, checks candidate readiness, confirms activation again, and
|
|
216
|
-
atomically changes the generation used for new named-query invocations. Failed
|
|
217
|
-
or superseded candidates never displace a healthy generation.
|
|
218
|
-
|
|
219
|
-
```ts
|
|
220
|
-
import {
|
|
221
|
-
createDeploymentRuntimeSupervisor,
|
|
222
|
-
createNodeWorkerDeploymentRuntimeFactory,
|
|
223
|
-
} from '@hypequery/deployment';
|
|
224
|
-
|
|
225
|
-
const supervisor = createDeploymentRuntimeSupervisor({
|
|
226
|
-
materializer,
|
|
227
|
-
factory: createNodeWorkerDeploymentRuntimeFactory(),
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
await supervisor.reconcile({ project: 'analytics', environment: 'production' });
|
|
231
|
-
const result = await supervisor.invoke({
|
|
232
|
-
target: { project: 'analytics', environment: 'production' },
|
|
233
|
-
query: 'orders',
|
|
234
|
-
argument: { input, ctx: { tenantId } },
|
|
235
|
-
});
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Calls already assigned to an old generation may finish after cutover. That
|
|
239
|
-
generation receives no new calls and closes when its in-flight work reaches
|
|
240
|
-
zero or the drain deadline expires. The reference Node factory loads exact
|
|
241
|
-
materialized bytes in worker threads and removes their temporary files on
|
|
242
|
-
shutdown. Provider factories can implement Python, process, container, or
|
|
243
|
-
remote-sandbox isolation behind the same lifecycle interface.
|
|
244
|
-
|
|
245
|
-
The reference worker is a lifecycle boundary, not a hostile-code security
|
|
246
|
-
sandbox. Only trusted deployment code should use it directly.
|
|
247
|
-
|
|
248
155
|
The package is ESM-only and requires Node.js 20 or newer.
|
package/dist/activation.d.ts
CHANGED
|
@@ -29,14 +29,6 @@ export type DeploymentActivationResult = {
|
|
|
29
29
|
readonly status: 'conflict';
|
|
30
30
|
readonly current: DeploymentActivationRecord | null;
|
|
31
31
|
};
|
|
32
|
-
export interface DeploymentActivationHistoryQuery {
|
|
33
|
-
readonly limit: number;
|
|
34
|
-
readonly before?: string;
|
|
35
|
-
}
|
|
36
|
-
export interface DeploymentActivationHistoryPage {
|
|
37
|
-
readonly activations: readonly DeploymentActivationRecord[];
|
|
38
|
-
readonly nextBefore: string | null;
|
|
39
|
-
}
|
|
40
32
|
export interface DeploymentActivationRelease {
|
|
41
33
|
readonly release: ProtocolDeploymentReleaseEnvelope;
|
|
42
34
|
readonly releaseIdentity: string;
|
|
@@ -54,9 +46,6 @@ export interface DeploymentActivationRegistry {
|
|
|
54
46
|
activate(request: DeploymentActivationRequest): Promise<DeploymentActivationResult>;
|
|
55
47
|
current(target: ProtocolDeploymentReleaseTarget): Promise<DeploymentActivationRecord | undefined>;
|
|
56
48
|
history(target: ProtocolDeploymentReleaseTarget): Promise<readonly DeploymentActivationRecord[]>;
|
|
57
|
-
historyPage(target: ProtocolDeploymentReleaseTarget, query: DeploymentActivationHistoryQuery): Promise<DeploymentActivationHistoryPage>;
|
|
58
49
|
}
|
|
59
|
-
/** Validate and recompute an immutable deployment activation record. */
|
|
60
|
-
export declare function validateDeploymentActivationRecord(input: unknown): DeploymentActivationRecord;
|
|
61
50
|
export declare function createFileSystemDeploymentActivationRegistry(options: FileSystemDeploymentActivationRegistryOptions): DeploymentActivationRegistry;
|
|
62
51
|
//# sourceMappingURL=activation.d.ts.map
|
package/dist/activation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../src/activation.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAe7B,MAAM,MAAM,6BAA6B,GACrC,wCAAwC,GACxC,0CAA0C,GAC1C,4CAA4C,GAC5C,8CAA8C,GAC9C,0CAA0C,GAC1C,wCAAwC,GACxC,6BAA6B,CAAC;AAElC,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;gBAG3C,IAAI,EAAE,6BAA6B,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAM7C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,MAAM,0BAA0B,GAClC;IACA,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,0BAA0B,CAAC;CACjD,GACC;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAAC;CACrD,CAAC;AAEJ,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../src/activation.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAe7B,MAAM,MAAM,6BAA6B,GACrC,wCAAwC,GACxC,0CAA0C,GAC1C,4CAA4C,GAC5C,8CAA8C,GAC9C,0CAA0C,GAC1C,wCAAwC,GACxC,6BAA6B,CAAC;AAElC,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;gBAG3C,IAAI,EAAE,6BAA6B,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAM7C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,MAAM,0BAA0B,GAClC;IACA,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,0BAA0B,CAAC;CACjD,GACC;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAAC;CACrD,CAAC;AAEJ,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;IACpD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,6FAA6F;IAC7F,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,6CAA6C;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACpF,OAAO,CACL,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;IACnD,OAAO,CACL,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,SAAS,0BAA0B,EAAE,CAAC,CAAC;CACnD;AAqdD,wBAAgB,4CAA4C,CAC1D,OAAO,EAAE,6CAA6C,GACrD,4BAA4B,CAqM9B"}
|
package/dist/activation.js
CHANGED
|
@@ -128,16 +128,21 @@ function requireRecord(input) {
|
|
|
128
128
|
}
|
|
129
129
|
return value;
|
|
130
130
|
}
|
|
131
|
-
function
|
|
131
|
+
function validateStoredActivation(input, expectedTarget, expectedPreviousRevision, expectedPreviousReleaseIdentity) {
|
|
132
132
|
const value = requireRecord(input);
|
|
133
133
|
if (value.kind !== 'hypequery-deployment-activation' || value.version !== 1) {
|
|
134
134
|
throw new Error('Activation record kind or version is invalid.');
|
|
135
135
|
}
|
|
136
136
|
const target = validateTarget(value.target, 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
|
|
137
|
+
if (!targetsEqual(target, expectedTarget)) {
|
|
138
|
+
throw new Error('Activation record target is inconsistent.');
|
|
139
|
+
}
|
|
137
140
|
const releaseIdentity = requireIdentity(value.releaseIdentity, 'Stored release identity', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
|
|
138
141
|
const previousRevision = requireNullableIdentity(value.previousRevision, 'Stored previous revision', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
|
|
139
142
|
const previousReleaseIdentity = requireNullableIdentity(value.previousReleaseIdentity, 'Stored previous release identity', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
|
|
140
|
-
if (
|
|
143
|
+
if (previousRevision !== expectedPreviousRevision
|
|
144
|
+
|| previousReleaseIdentity !== expectedPreviousReleaseIdentity
|
|
145
|
+
|| (previousRevision === null) !== (previousReleaseIdentity === null)) {
|
|
141
146
|
throw new Error('Activation record predecessor is inconsistent.');
|
|
142
147
|
}
|
|
143
148
|
if (typeof value.activatedAt !== 'string') {
|
|
@@ -159,21 +164,6 @@ function prepareValidatedActivation(input) {
|
|
|
159
164
|
}
|
|
160
165
|
return prepared;
|
|
161
166
|
}
|
|
162
|
-
/** Validate and recompute an immutable deployment activation record. */
|
|
163
|
-
export function validateDeploymentActivationRecord(input) {
|
|
164
|
-
return prepareValidatedActivation(input).record;
|
|
165
|
-
}
|
|
166
|
-
function validateStoredActivation(input, expectedTarget, expectedPreviousRevision, expectedPreviousReleaseIdentity) {
|
|
167
|
-
const prepared = prepareValidatedActivation(input);
|
|
168
|
-
if (!targetsEqual(prepared.record.target, expectedTarget)) {
|
|
169
|
-
throw new Error('Activation record target is inconsistent.');
|
|
170
|
-
}
|
|
171
|
-
if (prepared.record.previousRevision !== expectedPreviousRevision
|
|
172
|
-
|| prepared.record.previousReleaseIdentity !== expectedPreviousReleaseIdentity) {
|
|
173
|
-
throw new Error('Activation record predecessor is inconsistent.');
|
|
174
|
-
}
|
|
175
|
-
return prepared;
|
|
176
|
-
}
|
|
177
167
|
async function pathExists(filePath) {
|
|
178
168
|
try {
|
|
179
169
|
await lstat(filePath);
|
|
@@ -345,7 +335,7 @@ async function readStoredActivation(claimDirectory, target, previousRevision, pr
|
|
|
345
335
|
}
|
|
346
336
|
return prepared;
|
|
347
337
|
}
|
|
348
|
-
async function
|
|
338
|
+
async function resolveHistory(targetDirectory, target) {
|
|
349
339
|
try {
|
|
350
340
|
await readCanonicalTarget(targetDirectory, target);
|
|
351
341
|
const claimsDirectory = path.join(targetDirectory, CLAIMS_DIRECTORY);
|
|
@@ -357,6 +347,7 @@ async function visitHistory(targetDirectory, target, visitor) {
|
|
|
357
347
|
}
|
|
358
348
|
const remaining = new Set(claimNames);
|
|
359
349
|
const revisions = new Set();
|
|
350
|
+
const history = [];
|
|
360
351
|
let previousRevision = null;
|
|
361
352
|
let previousReleaseIdentity = null;
|
|
362
353
|
// Following predecessor-named claims derives the head without trusting a
|
|
@@ -370,13 +361,14 @@ async function visitHistory(targetDirectory, target, visitor) {
|
|
|
370
361
|
throw new Error('Deployment activation history contains a cycle.');
|
|
371
362
|
}
|
|
372
363
|
revisions.add(prepared.record.revision);
|
|
373
|
-
|
|
364
|
+
history.push(prepared.record);
|
|
374
365
|
previousRevision = prepared.record.revision;
|
|
375
366
|
previousReleaseIdentity = prepared.record.releaseIdentity;
|
|
376
367
|
}
|
|
377
368
|
if (remaining.size > 0) {
|
|
378
369
|
throw new Error('Deployment activation history contains unreachable claims.');
|
|
379
370
|
}
|
|
371
|
+
return Object.freeze(history);
|
|
380
372
|
}
|
|
381
373
|
catch (error) {
|
|
382
374
|
if (error instanceof DeploymentActivationError)
|
|
@@ -386,53 +378,8 @@ async function visitHistory(targetDirectory, target, visitor) {
|
|
|
386
378
|
throw activationError('HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE', 'Stored deployment activation history is invalid.', error);
|
|
387
379
|
}
|
|
388
380
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
await visitHistory(targetDirectory, target, record => { history.push(record); });
|
|
392
|
-
return Object.freeze(history);
|
|
393
|
-
}
|
|
394
|
-
async function resolveCurrent(targetDirectory, target) {
|
|
395
|
-
let current;
|
|
396
|
-
await visitHistory(targetDirectory, target, record => { current = record; });
|
|
397
|
-
return current;
|
|
398
|
-
}
|
|
399
|
-
function validateHistoryQuery(input) {
|
|
400
|
-
if (!Number.isSafeInteger(input?.limit) || input.limit < 1
|
|
401
|
-
|| (input.before !== undefined && !IDENTITY_PATTERN.test(input.before))) {
|
|
402
|
-
throw activationError('HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST', 'Deployment activation history query is invalid.');
|
|
403
|
-
}
|
|
404
|
-
return Object.freeze({
|
|
405
|
-
limit: input.limit,
|
|
406
|
-
...(input.before === undefined ? {} : { before: input.before }),
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
async function resolveHistoryPage(targetDirectory, target, query) {
|
|
410
|
-
const retained = [];
|
|
411
|
-
let beforeFound = query.before === undefined;
|
|
412
|
-
let beforeReached = false;
|
|
413
|
-
await visitHistory(targetDirectory, target, record => {
|
|
414
|
-
if (record.revision === query.before) {
|
|
415
|
-
beforeFound = true;
|
|
416
|
-
beforeReached = true;
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
if (beforeReached)
|
|
420
|
-
return;
|
|
421
|
-
retained.push(record);
|
|
422
|
-
if (retained.length > query.limit + 1)
|
|
423
|
-
retained.shift();
|
|
424
|
-
});
|
|
425
|
-
if (!beforeFound) {
|
|
426
|
-
throw activationError('HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST', 'Deployment activation history cursor was not found.');
|
|
427
|
-
}
|
|
428
|
-
const hasOlder = retained.length > query.limit;
|
|
429
|
-
if (hasOlder)
|
|
430
|
-
retained.shift();
|
|
431
|
-
const activations = Object.freeze(retained);
|
|
432
|
-
return Object.freeze({
|
|
433
|
-
activations,
|
|
434
|
-
nextBefore: hasOlder ? activations[0].revision : null,
|
|
435
|
-
});
|
|
381
|
+
function currentActivation(history) {
|
|
382
|
+
return history[history.length - 1];
|
|
436
383
|
}
|
|
437
384
|
export function createFileSystemDeploymentActivationRegistry(options) {
|
|
438
385
|
if (typeof options.directory !== 'string' || options.directory.length < 1) {
|
|
@@ -486,37 +433,8 @@ export function createFileSystemDeploymentActivationRegistry(options) {
|
|
|
486
433
|
throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read deployment activation history.', error);
|
|
487
434
|
}
|
|
488
435
|
}
|
|
489
|
-
async function current(
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
const key = sha256(TARGET_IDENTITY_DOMAIN, targetCanonical(target));
|
|
493
|
-
const targetDirectory = path.join(await activationRoot(), key);
|
|
494
|
-
if (!await pathExists(targetDirectory))
|
|
495
|
-
return undefined;
|
|
496
|
-
return await resolveCurrent(targetDirectory, target);
|
|
497
|
-
}
|
|
498
|
-
catch (error) {
|
|
499
|
-
if (error instanceof DeploymentActivationError)
|
|
500
|
-
throw error;
|
|
501
|
-
throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read the current deployment activation.', error);
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
async function historyPage(targetInput, queryInput) {
|
|
505
|
-
const target = validateTarget(targetInput, 'HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST');
|
|
506
|
-
const query = validateHistoryQuery(queryInput);
|
|
507
|
-
try {
|
|
508
|
-
const key = sha256(TARGET_IDENTITY_DOMAIN, targetCanonical(target));
|
|
509
|
-
const targetDirectory = path.join(await activationRoot(), key);
|
|
510
|
-
if (!await pathExists(targetDirectory)) {
|
|
511
|
-
return Object.freeze({ activations: Object.freeze([]), nextBefore: null });
|
|
512
|
-
}
|
|
513
|
-
return await resolveHistoryPage(targetDirectory, target, query);
|
|
514
|
-
}
|
|
515
|
-
catch (error) {
|
|
516
|
-
if (error instanceof DeploymentActivationError)
|
|
517
|
-
throw error;
|
|
518
|
-
throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read deployment activation history.', error);
|
|
519
|
-
}
|
|
436
|
+
async function current(target) {
|
|
437
|
+
return currentActivation(await history(target));
|
|
520
438
|
}
|
|
521
439
|
async function activate(request) {
|
|
522
440
|
const target = validateTarget(request.target, 'HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST');
|
|
@@ -549,7 +467,8 @@ export function createFileSystemDeploymentActivationRegistry(options) {
|
|
|
549
467
|
try {
|
|
550
468
|
const activations = await activationRoot();
|
|
551
469
|
const targetDirectory = await ensureTargetDirectory(activations, target);
|
|
552
|
-
const
|
|
470
|
+
const existingHistory = await resolveHistory(targetDirectory, target);
|
|
471
|
+
const existing = currentActivation(existingHistory);
|
|
553
472
|
if (existing?.releaseIdentity === releaseIdentity) {
|
|
554
473
|
return Object.freeze({ status: 'already-active', activation: existing });
|
|
555
474
|
}
|
|
@@ -595,7 +514,7 @@ export function createFileSystemDeploymentActivationRegistry(options) {
|
|
|
595
514
|
if (published) {
|
|
596
515
|
return Object.freeze({ status: 'activated', activation: prepared.record });
|
|
597
516
|
}
|
|
598
|
-
const resolved = await
|
|
517
|
+
const resolved = currentActivation(await resolveHistory(targetDirectory, target));
|
|
599
518
|
if (resolved?.releaseIdentity === releaseIdentity) {
|
|
600
519
|
return Object.freeze({ status: 'already-active', activation: resolved });
|
|
601
520
|
}
|
|
@@ -607,5 +526,5 @@ export function createFileSystemDeploymentActivationRegistry(options) {
|
|
|
607
526
|
throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not update deployment activation state.', error);
|
|
608
527
|
}
|
|
609
528
|
}
|
|
610
|
-
return Object.freeze({ activate, current, history
|
|
529
|
+
return Object.freeze({ activate, current, history });
|
|
611
530
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError,
|
|
2
|
-
export type { DeploymentActivationErrorCode,
|
|
1
|
+
export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, } from './activation.js';
|
|
2
|
+
export type { DeploymentActivationErrorCode, DeploymentActivationRegistry, DeploymentActivationRelease, DeploymentActivationRecord, DeploymentActivationRequest, DeploymentActivationResult, DeploymentReleaseReader, FileSystemDeploymentActivationRegistryOptions, } from './activation.js';
|
|
3
3
|
export { DEPLOYMENT_BUNDLE_CONTRACT, DEPLOYMENT_BUNDLE_MANIFEST, verifyDeploymentBundle, } from './bundle.js';
|
|
4
4
|
export type { VerifiedDeploymentBundle } from './bundle.js';
|
|
5
5
|
export { DeploymentIntakeError, } from './errors.js';
|
|
@@ -7,19 +7,7 @@ export type { DeploymentIntakeErrorCode } from './errors.js';
|
|
|
7
7
|
export { createFileSystemDeploymentSubmissionStore, FileSystemDeploymentStoreError, } from './filesystem-store.js';
|
|
8
8
|
export type { FileSystemDeploymentStoreErrorCode, FileSystemDeploymentSubmissionStore, FileSystemDeploymentSubmissionStoreOptions, StoredDeploymentSubmission, } from './filesystem-store.js';
|
|
9
9
|
export { createDeploymentIntake, } from './intake.js';
|
|
10
|
-
export { createDeploymentControlPlaneFetchHandler, createDeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
|
|
11
|
-
export type { DeploymentControlPlaneFetchHandler, DeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
|
|
12
|
-
export { createDeploymentControlPlane, } from './control-plane.js';
|
|
13
|
-
export type { DeploymentControlPlane, DeploymentControlPlaneAction, DeploymentControlPlaneAuthorizationInput, DeploymentControlPlaneAuthorizer, DeploymentControlPlaneErrorCode, DeploymentControlPlaneOptions, DeploymentControlPlaneRequest, DeploymentControlPlaneResponse, } from './control-plane.js';
|
|
14
|
-
export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneLimits, } from './control-plane-limits.js';
|
|
15
|
-
export type { DeploymentControlPlaneLimits } from './control-plane-limits.js';
|
|
16
10
|
export { DEFAULT_DEPLOYMENT_INTAKE_LIMITS, resolveDeploymentIntakeLimits, } from './limits.js';
|
|
17
11
|
export type { DeploymentIntakeLimits } from './limits.js';
|
|
18
|
-
export { createNodeWorkerDeploymentRuntimeFactory, NodeDeploymentRuntimeError, } from './node-runtime-factory.js';
|
|
19
|
-
export type { NodeDeploymentRuntimeErrorCode, NodeDeploymentRuntimeFactoryOptions, } from './node-runtime-factory.js';
|
|
20
|
-
export { createDeploymentRuntimeMaterializer, DeploymentRuntimeMaterializationError, } from './runtime-materialization.js';
|
|
21
|
-
export type { DeploymentRuntimeArtifactSnapshot, DeploymentRuntimeMaterializationErrorCode, DeploymentRuntimeMaterializer, DeploymentRuntimeMaterializerOptions, DeploymentRuntimeQueryBinding, DeploymentRuntimeRelease, DeploymentRuntimeReleaseReader, DeploymentRuntimeSnapshot, } from './runtime-materialization.js';
|
|
22
|
-
export { createDeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorError, } from './runtime-supervisor.js';
|
|
23
|
-
export type { DeploymentRuntimeFactory, DeploymentRuntimeInstance, DeploymentRuntimeInstanceInvocation, DeploymentRuntimeInvocation, DeploymentRuntimeReconcileResult, DeploymentRuntimeStatus, DeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorErrorCode, DeploymentRuntimeSupervisorOptions, } from './runtime-supervisor.js';
|
|
24
12
|
export type { DeploymentAuthenticationInput, DeploymentAuthenticator, DeploymentAuthorizationInput, DeploymentAuthorizer, DeploymentIntake, DeploymentIntakeOptions, DeploymentIntakeRequest, DeploymentIntakeResponse, DeploymentSubmissionResponse, DeploymentSubmissionStore, VerifiedDeploymentSubmission, } from './types.js';
|
|
25
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4CAA4C,EAC5C,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4CAA4C,EAC5C,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,6BAA6B,EAC7B,4BAA4B,EAC5B,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,EACvB,6CAA6C,GAC9C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,yCAAyC,EACzC,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kCAAkC,EAClC,mCAAmC,EACnC,0CAA0C,EAC1C,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gCAAgC,EAChC,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError,
|
|
1
|
+
export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, } from './activation.js';
|
|
2
2
|
export { DEPLOYMENT_BUNDLE_CONTRACT, DEPLOYMENT_BUNDLE_MANIFEST, verifyDeploymentBundle, } from './bundle.js';
|
|
3
3
|
export { DeploymentIntakeError, } from './errors.js';
|
|
4
4
|
export { createFileSystemDeploymentSubmissionStore, FileSystemDeploymentStoreError, } from './filesystem-store.js';
|
|
5
5
|
export { createDeploymentIntake, } from './intake.js';
|
|
6
|
-
export { createDeploymentControlPlaneFetchHandler, createDeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
|
|
7
|
-
export { createDeploymentControlPlane, } from './control-plane.js';
|
|
8
|
-
export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneLimits, } from './control-plane-limits.js';
|
|
9
6
|
export { DEFAULT_DEPLOYMENT_INTAKE_LIMITS, resolveDeploymentIntakeLimits, } from './limits.js';
|
|
10
|
-
export { createNodeWorkerDeploymentRuntimeFactory, NodeDeploymentRuntimeError, } from './node-runtime-factory.js';
|
|
11
|
-
export { createDeploymentRuntimeMaterializer, DeploymentRuntimeMaterializationError, } from './runtime-materialization.js';
|
|
12
|
-
export { createDeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorError, } from './runtime-supervisor.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypequery/deployment",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Provider-neutral deployment verification and intake for Hypequery",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@hypequery/protocol": "0.
|
|
21
|
+
"@hypequery/protocol": "0.6.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^22.5.0",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
"dev": "tsc --project tsconfig.json --watch",
|
|
42
42
|
"lint": "eslint --ext .ts \"src/**/*.ts\"",
|
|
43
43
|
"test": "vitest run",
|
|
44
|
-
"types": "tsc --project tsconfig.json --noEmit
|
|
44
|
+
"types": "tsc --project tsconfig.json --noEmit"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import type { DeploymentControlPlane } from './control-plane.js';
|
|
3
|
-
export type DeploymentControlPlaneFetchHandler = (request: Request) => Promise<Response>;
|
|
4
|
-
export type DeploymentControlPlaneNodeHandler = (request: IncomingMessage, response: ServerResponse) => Promise<void>;
|
|
5
|
-
export declare function createDeploymentControlPlaneFetchHandler(controlPlane: DeploymentControlPlane): DeploymentControlPlaneFetchHandler;
|
|
6
|
-
export declare function createDeploymentControlPlaneNodeHandler(controlPlane: DeploymentControlPlane): DeploymentControlPlaneNodeHandler;
|
|
7
|
-
//# sourceMappingURL=control-plane-adapters.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-adapters.d.ts","sourceRoot":"","sources":["../src/control-plane-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,kCAAkC,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACzF,MAAM,MAAM,iCAAiC,GAAG,CAC9C,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;AAkHnB,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,sBAAsB,GACnC,kCAAkC,CAkBpC;AAED,wBAAgB,uCAAuC,CACrD,YAAY,EAAE,sBAAsB,GACnC,iCAAiC,CAgCnC"}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
const INTERNAL_BODY = '{"error":{"code":"HQ_CONTROL_INTERNAL","message":"The deployment control-plane request could not be processed."}}\n';
|
|
2
|
-
const INTERNAL_RESPONSE = Object.freeze({
|
|
3
|
-
status: 500,
|
|
4
|
-
headers: Object.freeze({
|
|
5
|
-
'content-type': 'application/json; charset=utf-8',
|
|
6
|
-
'content-length': String(Buffer.byteLength(INTERNAL_BODY)),
|
|
7
|
-
'cache-control': 'no-store',
|
|
8
|
-
}),
|
|
9
|
-
body: INTERNAL_BODY,
|
|
10
|
-
});
|
|
11
|
-
const FETCH_SINGLETON_HEADERS = new Set([
|
|
12
|
-
'authorization',
|
|
13
|
-
'content-length',
|
|
14
|
-
'content-type',
|
|
15
|
-
'idempotency-key',
|
|
16
|
-
'x-hypequery-bundle-identity',
|
|
17
|
-
'x-hypequery-release-identity',
|
|
18
|
-
]);
|
|
19
|
-
function queryParameters(search) {
|
|
20
|
-
const query = Object.create(null);
|
|
21
|
-
for (const [name, value] of search) {
|
|
22
|
-
const current = query[name];
|
|
23
|
-
if (current === undefined) {
|
|
24
|
-
query[name] = value;
|
|
25
|
-
}
|
|
26
|
-
else if (typeof current === 'string') {
|
|
27
|
-
query[name] = Object.freeze([current, value]);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
query[name] = Object.freeze([...current, value]);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return Object.freeze(query);
|
|
34
|
-
}
|
|
35
|
-
function fetchHeaders(input) {
|
|
36
|
-
const headers = Object.create(null);
|
|
37
|
-
for (const [name, value] of input.entries()) {
|
|
38
|
-
headers[name] = value;
|
|
39
|
-
if (FETCH_SINGLETON_HEADERS.has(name) && value.includes(',')) {
|
|
40
|
-
// Fetch combines duplicate header lines before exposing Headers. Reify a
|
|
41
|
-
// second case-insensitive entry so the core singleton guard rejects it.
|
|
42
|
-
headers[name.toUpperCase()] = value;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return Object.freeze(headers);
|
|
46
|
-
}
|
|
47
|
-
async function* fetchBody(input) {
|
|
48
|
-
if (input === null)
|
|
49
|
-
return;
|
|
50
|
-
const reader = input.getReader();
|
|
51
|
-
try {
|
|
52
|
-
while (true) {
|
|
53
|
-
const result = await reader.read();
|
|
54
|
-
if (result.done)
|
|
55
|
-
return;
|
|
56
|
-
yield result.value;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
reader.releaseLock();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function nodeHeaders(request) {
|
|
64
|
-
const headers = Object.create(null);
|
|
65
|
-
for (let index = 0; index < request.rawHeaders.length; index += 2) {
|
|
66
|
-
const name = request.rawHeaders[index].toLowerCase();
|
|
67
|
-
const value = request.rawHeaders[index + 1];
|
|
68
|
-
if (headers[name] === undefined) {
|
|
69
|
-
headers[name] = value;
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// Keep a second case-insensitive entry so the core duplicate-header guard
|
|
73
|
-
// observes duplicates instead of accepting Node's comma-joined value.
|
|
74
|
-
headers[name.toUpperCase()] = value;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return Object.freeze(headers);
|
|
78
|
-
}
|
|
79
|
-
async function* nodeBody(request) {
|
|
80
|
-
for await (const chunk of request) {
|
|
81
|
-
yield chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
function nodeHasBody(headers) {
|
|
85
|
-
return Object.entries(headers).some(([name, value]) => {
|
|
86
|
-
const normalized = name.toLowerCase();
|
|
87
|
-
return normalized === 'transfer-encoding'
|
|
88
|
-
|| (normalized === 'content-length' && value !== '0');
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
function internalFetchResponse() {
|
|
92
|
-
return new Response(INTERNAL_RESPONSE.body, {
|
|
93
|
-
status: INTERNAL_RESPONSE.status,
|
|
94
|
-
headers: INTERNAL_RESPONSE.headers,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
function sendNodeResponse(response, controlResponse) {
|
|
98
|
-
if (response.writableEnded || response.headersSent)
|
|
99
|
-
return;
|
|
100
|
-
response.statusCode = controlResponse.status;
|
|
101
|
-
for (const [name, value] of Object.entries(controlResponse.headers)) {
|
|
102
|
-
response.setHeader(name, value);
|
|
103
|
-
}
|
|
104
|
-
response.end(controlResponse.body);
|
|
105
|
-
}
|
|
106
|
-
export function createDeploymentControlPlaneFetchHandler(controlPlane) {
|
|
107
|
-
return async (request) => {
|
|
108
|
-
try {
|
|
109
|
-
const url = new URL(request.url);
|
|
110
|
-
const response = await controlPlane.handle({
|
|
111
|
-
method: request.method,
|
|
112
|
-
path: url.pathname,
|
|
113
|
-
query: queryParameters(url.searchParams),
|
|
114
|
-
headers: fetchHeaders(request.headers),
|
|
115
|
-
body: fetchBody(request.body),
|
|
116
|
-
hasBody: request.body !== null,
|
|
117
|
-
signal: request.signal,
|
|
118
|
-
});
|
|
119
|
-
return new Response(response.body, { status: response.status, headers: response.headers });
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return internalFetchResponse();
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
export function createDeploymentControlPlaneNodeHandler(controlPlane) {
|
|
127
|
-
return async (request, response) => {
|
|
128
|
-
const abort = new AbortController();
|
|
129
|
-
const abortRequest = () => {
|
|
130
|
-
if (!request.complete)
|
|
131
|
-
abort.abort(new Error('The request connection was closed.'));
|
|
132
|
-
};
|
|
133
|
-
const abortResponse = () => {
|
|
134
|
-
if (!response.writableEnded)
|
|
135
|
-
abort.abort(new Error('The response connection was closed.'));
|
|
136
|
-
};
|
|
137
|
-
request.socket.once('close', abortRequest);
|
|
138
|
-
response.once('close', abortResponse);
|
|
139
|
-
if (request.destroyed && !request.complete)
|
|
140
|
-
abortRequest();
|
|
141
|
-
try {
|
|
142
|
-
const url = new URL(request.url ?? '/', 'http://deployment-control-plane.invalid');
|
|
143
|
-
const headers = nodeHeaders(request);
|
|
144
|
-
const controlResponse = await controlPlane.handle({
|
|
145
|
-
method: request.method ?? 'GET',
|
|
146
|
-
path: url.pathname,
|
|
147
|
-
query: queryParameters(url.searchParams),
|
|
148
|
-
headers,
|
|
149
|
-
body: nodeBody(request),
|
|
150
|
-
hasBody: nodeHasBody(headers),
|
|
151
|
-
signal: abort.signal,
|
|
152
|
-
});
|
|
153
|
-
sendNodeResponse(response, controlResponse);
|
|
154
|
-
}
|
|
155
|
-
catch {
|
|
156
|
-
sendNodeResponse(response, INTERNAL_RESPONSE);
|
|
157
|
-
}
|
|
158
|
-
finally {
|
|
159
|
-
request.socket.off('close', abortRequest);
|
|
160
|
-
response.off('close', abortResponse);
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface DeploymentControlPlaneLimits {
|
|
2
|
-
readonly maxActivationRequestBytes: number;
|
|
3
|
-
readonly maxHistoryPageSize: number;
|
|
4
|
-
}
|
|
5
|
-
export declare const DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS: Readonly<DeploymentControlPlaneLimits>;
|
|
6
|
-
export declare function resolveDeploymentControlPlaneLimits(input?: Partial<DeploymentControlPlaneLimits>): Readonly<DeploymentControlPlaneLimits>;
|
|
7
|
-
//# sourceMappingURL=control-plane-limits.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane-limits.d.ts","sourceRoot":"","sources":["../src/control-plane-limits.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,uCAAuC,EACpD,QAAQ,CAAC,4BAA4B,CAGnC,CAAC;AAEH,wBAAgB,mCAAmC,CACjD,KAAK,GAAE,OAAO,CAAC,4BAA4B,CAAM,GAChD,QAAQ,CAAC,4BAA4B,CAAC,CAcxC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS = Object.freeze({
|
|
2
|
-
maxActivationRequestBytes: 16 * 1024,
|
|
3
|
-
maxHistoryPageSize: 100,
|
|
4
|
-
});
|
|
5
|
-
export function resolveDeploymentControlPlaneLimits(input = {}) {
|
|
6
|
-
const limits = { ...DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS };
|
|
7
|
-
for (const key of Object.keys(limits)) {
|
|
8
|
-
const value = input[key];
|
|
9
|
-
if (value === undefined)
|
|
10
|
-
continue;
|
|
11
|
-
if (!Number.isSafeInteger(value) || value < 1
|
|
12
|
-
|| value > DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS[key]) {
|
|
13
|
-
throw new RangeError(`${key} must be a positive safe integer no greater than the control-plane v1 maximum`);
|
|
14
|
-
}
|
|
15
|
-
limits[key] = value;
|
|
16
|
-
}
|
|
17
|
-
return Object.freeze(limits);
|
|
18
|
-
}
|