@hypequery/deployment 0.7.5 → 0.9.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 (70) hide show
  1. package/README.md +5 -31
  2. package/dist/activation.d.ts.map +1 -1
  3. package/dist/activation.js +2 -1
  4. package/dist/authorized-contract.d.ts +72 -0
  5. package/dist/authorized-contract.d.ts.map +1 -0
  6. package/dist/authorized-contract.js +132 -0
  7. package/dist/bundle.d.ts.map +1 -1
  8. package/dist/bundle.js +10 -36
  9. package/dist/control-plane-limits.js +1 -1
  10. package/dist/filesystem-store.d.ts.map +1 -1
  11. package/dist/filesystem-store.js +7 -22
  12. package/dist/index.d.ts +6 -18
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +5 -9
  15. package/dist/intake.d.ts.map +1 -1
  16. package/dist/intake.js +8 -5
  17. package/dist/limits.d.ts.map +1 -1
  18. package/dist/limits.js +5 -2
  19. package/dist/principal.d.ts +11 -0
  20. package/dist/principal.d.ts.map +1 -0
  21. package/dist/principal.js +1 -0
  22. package/dist/semantic-data-plane.d.ts +70 -0
  23. package/dist/semantic-data-plane.d.ts.map +1 -0
  24. package/dist/semantic-data-plane.js +234 -0
  25. package/dist/semantic-invocation-errors.d.ts +30 -0
  26. package/dist/semantic-invocation-errors.d.ts.map +1 -0
  27. package/dist/semantic-invocation-errors.js +45 -0
  28. package/dist/semantic-operation-validation.d.ts +29 -0
  29. package/dist/semantic-operation-validation.d.ts.map +1 -0
  30. package/dist/semantic-operation-validation.js +157 -0
  31. package/dist/utils/read-bounded-file.d.ts +4 -0
  32. package/dist/utils/read-bounded-file.d.ts.map +1 -0
  33. package/dist/utils/read-bounded-file.js +18 -0
  34. package/dist/utils/required-access.d.ts +2 -0
  35. package/dist/utils/required-access.d.ts.map +1 -0
  36. package/dist/utils/required-access.js +4 -0
  37. package/dist/utils/semantic-budget-limits.d.ts +7 -0
  38. package/dist/utils/semantic-budget-limits.d.ts.map +1 -0
  39. package/dist/utils/semantic-budget-limits.js +15 -0
  40. package/dist/utils/semantic-executor-failure.d.ts +21 -0
  41. package/dist/utils/semantic-executor-failure.d.ts.map +1 -0
  42. package/dist/utils/semantic-executor-failure.js +52 -0
  43. package/package.json +5 -4
  44. package/dist/data-plane-adapters.d.ts +0 -18
  45. package/dist/data-plane-adapters.d.ts.map +0 -1
  46. package/dist/data-plane-adapters.js +0 -304
  47. package/dist/data-plane-limits.d.ts +0 -5
  48. package/dist/data-plane-limits.d.ts.map +0 -1
  49. package/dist/data-plane-limits.js +0 -5
  50. package/dist/data-plane-runtime.d.ts +0 -13
  51. package/dist/data-plane-runtime.d.ts.map +0 -1
  52. package/dist/data-plane-runtime.js +0 -12
  53. package/dist/data-plane.d.ts +0 -84
  54. package/dist/data-plane.d.ts.map +0 -1
  55. package/dist/data-plane.js +0 -209
  56. package/dist/filesystem-host.d.ts +0 -51
  57. package/dist/filesystem-host.d.ts.map +0 -1
  58. package/dist/filesystem-host.js +0 -73
  59. package/dist/host.d.ts +0 -40
  60. package/dist/host.d.ts.map +0 -1
  61. package/dist/host.js +0 -183
  62. package/dist/node-runtime-factory.d.ts +0 -27
  63. package/dist/node-runtime-factory.d.ts.map +0 -1
  64. package/dist/node-runtime-factory.js +0 -336
  65. package/dist/runtime-materialization.d.ts +0 -58
  66. package/dist/runtime-materialization.d.ts.map +0 -1
  67. package/dist/runtime-materialization.js +0 -187
  68. package/dist/runtime-supervisor.d.ts +0 -77
  69. package/dist/runtime-supervisor.d.ts.map +0 -1
  70. package/dist/runtime-supervisor.js +0 -265
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-budget-limits.d.ts","sourceRoot":"","sources":["../../src/utils/semantic-budget-limits.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAKjF;AAED,mFAAmF;AACnF,wBAAgB,MAAM,CAAC,GAAG,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,SAAS,CAGrF;AAED,oFAAoF;AACpF,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7E"}
@@ -0,0 +1,15 @@
1
+ /** Drops explicitly-undefined properties, so a spread cannot erase a default. */
2
+ export function definedLimits(limits) {
3
+ if (limits === undefined)
4
+ return {};
5
+ return Object.fromEntries(Object.entries(limits).filter(([, value]) => value !== undefined));
6
+ }
7
+ /** The lowest of every ceiling that applies. A caller can tighten, never widen. */
8
+ export function lowest(...values) {
9
+ const finite = values.filter((value) => value !== undefined);
10
+ return finite.length === 0 ? undefined : Math.min(...finite);
11
+ }
12
+ /** A declared ceiling under a server one; declaring nothing leaves the server's. */
13
+ export function tighten(declared, ceiling) {
14
+ return declared === undefined ? ceiling : Math.min(declared, ceiling);
15
+ }
@@ -0,0 +1,21 @@
1
+ import type { ProtocolSemanticInvocationFailureCategory } from '@hypequery/protocol';
2
+ /**
3
+ * The category an executor claimed, when it deliberately claimed one.
4
+ *
5
+ * The `hypequerySemanticFailure` marker, not the shape of the error, is what
6
+ * grants the claim. Allow-listing a `category` string alone would let a
7
+ * provider or library exception that happens to carry a generic one — a
8
+ * `not-found` from an HTTP client, say — put its own message in front of a
9
+ * caller and decide whether the call is retried. This module refuses to unwrap
10
+ * a cause for exactly that reason, and duck-typing would have reopened the door
11
+ * beside it. An error without the marker stays `executor-failed` with the
12
+ * generic message.
13
+ */
14
+ export declare function claimedFailure(error: unknown): {
15
+ category: ProtocolSemanticInvocationFailureCategory;
16
+ code: string;
17
+ message: string;
18
+ retryable: boolean;
19
+ relist: boolean;
20
+ } | undefined;
21
+ //# sourceMappingURL=semantic-executor-failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-executor-failure.d.ts","sourceRoot":"","sources":["../../src/utils/semantic-executor-failure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,qBAAqB,CAAC;AAiCrF;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG;IAC9C,QAAQ,EAAE,yCAAyC,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,SAAS,CAgBZ"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Categories an injected executor may claim for itself.
3
+ *
4
+ * Execution is injected, so the executor is the only component that knows the
5
+ * difference between "this query broke", "this deployment cannot express that",
6
+ * and "this deployment is incoherent". Every category here is one only the
7
+ * executor can determine; the ones it must never claim — `unauthenticated`,
8
+ * `forbidden`, `cancelled`, `stale-activation` — are decided by this module and
9
+ * are deliberately absent.
10
+ */
11
+ const EXECUTOR_CATEGORIES = new Set([
12
+ 'unsupported-capability',
13
+ 'budget-exceeded',
14
+ 'tenant-required',
15
+ 'configuration-invalid',
16
+ 'not-found',
17
+ 'input-invalid',
18
+ 'output-invalid',
19
+ 'executor-unavailable',
20
+ 'executor-failed',
21
+ ]);
22
+ /**
23
+ * The category an executor claimed, when it deliberately claimed one.
24
+ *
25
+ * The `hypequerySemanticFailure` marker, not the shape of the error, is what
26
+ * grants the claim. Allow-listing a `category` string alone would let a
27
+ * provider or library exception that happens to carry a generic one — a
28
+ * `not-found` from an HTTP client, say — put its own message in front of a
29
+ * caller and decide whether the call is retried. This module refuses to unwrap
30
+ * a cause for exactly that reason, and duck-typing would have reopened the door
31
+ * beside it. An error without the marker stays `executor-failed` with the
32
+ * generic message.
33
+ */
34
+ export function claimedFailure(error) {
35
+ if (typeof error !== 'object' || error === null)
36
+ return undefined;
37
+ const shape = error;
38
+ if (shape.hypequerySemanticFailure !== true)
39
+ return undefined;
40
+ if (typeof shape.category !== 'string' || !EXECUTOR_CATEGORIES.has(shape.category)) {
41
+ return undefined;
42
+ }
43
+ return {
44
+ category: shape.category,
45
+ code: typeof shape.code === 'string' && /^[A-Z][A-Z0-9_]*$/.test(shape.code)
46
+ ? shape.code
47
+ : 'HQ_SEMANTIC_EXECUTION_FAILED',
48
+ message: typeof shape.message === 'string' ? shape.message : 'Semantic execution failed.',
49
+ retryable: shape.retryable === true,
50
+ relist: shape.relist === true,
51
+ };
52
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hypequery/deployment",
3
- "version": "0.7.5",
4
- "description": "Verified deployment intake, activation, and runtime hosting for Hypequery analytics",
3
+ "version": "0.9.0",
4
+ "description": "Verified deployment intake, activation, and semantic invocation for Hypequery analytics",
5
5
  "keywords": [
6
6
  "hypequery",
7
7
  "deployment",
@@ -26,12 +26,13 @@
26
26
  "README.md"
27
27
  ],
28
28
  "dependencies": {
29
- "@hypequery/protocol": "0.12.0"
29
+ "@hypequery/protocol": "0.14.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.5.0",
33
33
  "typescript": "^5.7.3",
34
- "vitest": "^3.2.6"
34
+ "vitest": "^3.2.6",
35
+ "@hypequery/datasets": "0.17.0"
35
36
  },
36
37
  "engines": {
37
38
  "node": ">=20"
@@ -1,18 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { type DeploymentDataPlane } from './data-plane.js';
3
- export type DeploymentDataPlaneFetchHandler = (request: Request) => Promise<Response>;
4
- export type DeploymentDataPlaneNodeHandler = (request: IncomingMessage, response: ServerResponse) => Promise<void>;
5
- export interface DeploymentDataPlaneAdapterRequest {
6
- readonly method: string;
7
- readonly path: string;
8
- readonly query: Readonly<Record<string, string | readonly string[]>>;
9
- readonly headers: Readonly<Record<string, string>>;
10
- }
11
- export interface DeploymentDataPlaneAdapterOptions {
12
- /** Request body limit from 1 through 1,048,576 bytes. */
13
- readonly maxRequestBytes?: number;
14
- readonly credentials?: (request: DeploymentDataPlaneAdapterRequest) => unknown;
15
- }
16
- export declare function createDeploymentDataPlaneFetchHandler(dataPlane: DeploymentDataPlane, options?: DeploymentDataPlaneAdapterOptions): DeploymentDataPlaneFetchHandler;
17
- export declare function createDeploymentDataPlaneNodeHandler(dataPlane: DeploymentDataPlane, options?: DeploymentDataPlaneAdapterOptions): DeploymentDataPlaneNodeHandler;
18
- //# sourceMappingURL=data-plane-adapters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-plane-adapters.d.ts","sourceRoot":"","sources":["../src/data-plane-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,+BAA+B,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACtF,MAAM,MAAM,8BAA8B,GAAG,CAC3C,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,iCAAiC;IAChD,yDAAyD;IACzD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,iCAAiC,KAAK,OAAO,CAAC;CAChF;AAoPD,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,mBAAmB,EAC9B,OAAO,GAAE,iCAAsC,GAC9C,+BAA+B,CAwBjC;AAqDD,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,mBAAmB,EAC9B,OAAO,GAAE,iCAAsC,GAC9C,8BAA8B,CAuChC"}
@@ -1,304 +0,0 @@
1
- import { DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, } from '@hypequery/protocol';
2
- import { DeploymentDataPlaneError, } from './data-plane.js';
3
- import { DeploymentHostError } from './host.js';
4
- class AdapterError extends Error {
5
- code;
6
- status;
7
- constructor(code, status, message) {
8
- super(message);
9
- this.code = code;
10
- this.status = status;
11
- }
12
- }
13
- const JSON_CONTENT_TYPE = /^application\/json(?:;\s*charset=utf-8)?$/i;
14
- function maximumBytes(input) {
15
- const maximum = DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS.maxInputBytes;
16
- const value = input ?? maximum;
17
- if (!Number.isSafeInteger(value) || value < 1 || value > maximum) {
18
- throw new RangeError(`maxRequestBytes must be an integer between 1 and ${maximum}`);
19
- }
20
- return value;
21
- }
22
- function queryParameters(search) {
23
- const query = Object.create(null);
24
- for (const [name, value] of search) {
25
- const current = query[name];
26
- if (current === undefined)
27
- query[name] = value;
28
- else if (typeof current === 'string')
29
- query[name] = Object.freeze([current, value]);
30
- else
31
- query[name] = Object.freeze([...current, value]);
32
- }
33
- return Object.freeze(query);
34
- }
35
- function contentLength(headers, maximum) {
36
- const value = headers['content-length'];
37
- if (value === undefined)
38
- return undefined;
39
- if (!/^(?:0|[1-9][0-9]*)$/.test(value)) {
40
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Content-Length is invalid.');
41
- }
42
- const length = Number(value);
43
- if (!Number.isSafeInteger(length)) {
44
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Content-Length is invalid.');
45
- }
46
- if (length > maximum) {
47
- throw new AdapterError('HQ_DATA_PLANE_REQUEST_TOO_LARGE', 413, 'The data-plane request exceeds its byte limit.');
48
- }
49
- return length;
50
- }
51
- function requestInput(query, body, contentType) {
52
- const hasQuery = Object.keys(query).length > 0;
53
- if (body !== undefined && hasQuery) {
54
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'A data-plane request cannot contain both query parameters and a JSON body.');
55
- }
56
- if (body !== undefined) {
57
- if (!contentType || !JSON_CONTENT_TYPE.test(contentType)) {
58
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Data-plane request bodies require application/json with UTF-8 encoding.');
59
- }
60
- return body;
61
- }
62
- return hasQuery ? JSON.stringify(query) : undefined;
63
- }
64
- function credentials(options, request) {
65
- return options.credentials ? options.credentials(request) : request.headers.authorization;
66
- }
67
- function cacheControl(result) {
68
- if (result.cacheTtlMs === undefined || result.cacheTtlMs <= 0)
69
- return 'no-store';
70
- return `public, max-age=${Math.floor(result.cacheTtlMs / 1_000)}`;
71
- }
72
- function successResponse(result) {
73
- if (result.output === undefined) {
74
- return Object.freeze({
75
- status: 204,
76
- headers: Object.freeze({ 'cache-control': cacheControl(result) }),
77
- });
78
- }
79
- const body = `${JSON.stringify(result.output)}\n`;
80
- return Object.freeze({
81
- status: 200,
82
- headers: Object.freeze({
83
- 'content-type': 'application/json; charset=utf-8',
84
- 'content-length': String(Buffer.byteLength(body)),
85
- 'cache-control': cacheControl(result),
86
- }),
87
- body,
88
- });
89
- }
90
- function errorStatus(error) {
91
- switch (error.code) {
92
- case 'HQ_DATA_PLANE_INPUT_INVALID': return 400;
93
- case 'HQ_DATA_PLANE_UNAUTHENTICATED': return 401;
94
- case 'HQ_DATA_PLANE_FORBIDDEN':
95
- case 'HQ_DATA_PLANE_TENANT_REQUIRED': return 403;
96
- case 'HQ_DATA_PLANE_ROUTE_NOT_FOUND': return 404;
97
- case 'HQ_DATA_PLANE_METHOD_NOT_ALLOWED': return 405;
98
- case 'HQ_DATA_PLANE_ABORTED': return 499;
99
- case 'HQ_DATA_PLANE_EXECUTOR_UNAVAILABLE': return 503;
100
- default: return 500;
101
- }
102
- }
103
- function errorResponse(error) {
104
- let status = 500;
105
- let code = 'HQ_DATA_PLANE_INTERNAL';
106
- let message = 'The deployment data-plane request could not be processed.';
107
- let path;
108
- if (error instanceof AdapterError) {
109
- status = error.status;
110
- code = error.code;
111
- message = error.message;
112
- }
113
- else if (error instanceof DeploymentDataPlaneError) {
114
- status = errorStatus(error);
115
- code = error.code;
116
- if (status < 500) {
117
- message = error.message;
118
- path = error.path;
119
- }
120
- }
121
- else if (error instanceof DeploymentHostError) {
122
- code = error.code;
123
- if (error.code === 'HQ_DEPLOYMENT_HOST_NOT_READY'
124
- || error.code === 'HQ_DEPLOYMENT_HOST_CLOSED') {
125
- status = 503;
126
- message = error.message;
127
- }
128
- }
129
- const body = `${JSON.stringify({
130
- error: { code, message, ...(path === undefined ? {} : { path }) },
131
- })}\n`;
132
- return Object.freeze({
133
- status,
134
- headers: Object.freeze({
135
- 'content-type': 'application/json; charset=utf-8',
136
- 'content-length': String(Buffer.byteLength(body)),
137
- 'cache-control': 'no-store',
138
- ...(status === 401 ? { 'www-authenticate': 'Bearer' } : {}),
139
- }),
140
- body,
141
- });
142
- }
143
- async function execute(dataPlane, options, request, input, signal) {
144
- try {
145
- const result = await dataPlane.executeJson({
146
- ...request,
147
- input,
148
- credentials: credentials(options, request),
149
- signal,
150
- });
151
- return successResponse(result);
152
- }
153
- catch (error) {
154
- return errorResponse(error);
155
- }
156
- }
157
- function fetchHeaders(input) {
158
- const headers = Object.create(null);
159
- for (const [name, value] of input)
160
- headers[name.toLowerCase()] = value;
161
- if (headers.authorization?.includes(',')) {
162
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Authorization header is ambiguous.');
163
- }
164
- return Object.freeze(headers);
165
- }
166
- async function fetchBytes(stream, declared, maximum) {
167
- if (stream === null) {
168
- if (declared !== undefined && declared !== 0) {
169
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Request body length is invalid.');
170
- }
171
- return undefined;
172
- }
173
- const reader = stream.getReader();
174
- const chunks = [];
175
- let total = 0;
176
- try {
177
- while (true) {
178
- const result = await reader.read();
179
- if (result.done)
180
- break;
181
- total += result.value.byteLength;
182
- if (total > maximum)
183
- throw new AdapterError('HQ_DATA_PLANE_REQUEST_TOO_LARGE', 413, 'The data-plane request exceeds its byte limit.');
184
- if (declared !== undefined && total > declared) {
185
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Request body length is invalid.');
186
- }
187
- chunks.push(result.value);
188
- }
189
- }
190
- catch (error) {
191
- await reader.cancel(error).catch(() => undefined);
192
- throw error;
193
- }
194
- finally {
195
- reader.releaseLock();
196
- }
197
- if (declared !== undefined && total !== declared) {
198
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Request body length is invalid.');
199
- }
200
- const bytes = new Uint8Array(total);
201
- let offset = 0;
202
- for (const chunk of chunks) {
203
- bytes.set(chunk, offset);
204
- offset += chunk.byteLength;
205
- }
206
- return bytes.byteLength === 0 ? undefined : bytes;
207
- }
208
- export function createDeploymentDataPlaneFetchHandler(dataPlane, options = {}) {
209
- const maximum = maximumBytes(options.maxRequestBytes);
210
- return async (request) => {
211
- let response;
212
- try {
213
- const url = new URL(request.url);
214
- const headers = fetchHeaders(request.headers);
215
- const query = queryParameters(url.searchParams);
216
- const body = await fetchBytes(request.body, contentLength(headers, maximum), maximum);
217
- const adapted = Object.freeze({
218
- method: request.method.toUpperCase(), path: url.pathname, query, headers,
219
- });
220
- response = await execute(dataPlane, options, adapted, requestInput(query, body, headers['content-type']), request.signal);
221
- }
222
- catch (error) {
223
- response = errorResponse(error);
224
- }
225
- return new Response(response.body ?? null, { status: response.status, headers: response.headers });
226
- };
227
- }
228
- function nodeHeaders(request) {
229
- const headers = Object.create(null);
230
- for (let index = 0; index < request.rawHeaders.length; index += 2) {
231
- const name = request.rawHeaders[index].toLowerCase();
232
- const value = request.rawHeaders[index + 1];
233
- if (name === 'authorization' && headers[name] !== undefined) {
234
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Authorization header is ambiguous.');
235
- }
236
- headers[name] = headers[name] === undefined ? value : `${headers[name]}, ${value}`;
237
- }
238
- return Object.freeze(headers);
239
- }
240
- function nodeHasBody(headers) {
241
- return headers['transfer-encoding'] !== undefined
242
- || headers['content-length'] !== undefined && headers['content-length'] !== '0';
243
- }
244
- async function nodeBytes(request, hasBody, declared, maximum) {
245
- if (!hasBody)
246
- return undefined;
247
- const chunks = [];
248
- let total = 0;
249
- for await (const chunk of request) {
250
- const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
251
- total += bytes.byteLength;
252
- if (total > maximum)
253
- throw new AdapterError('HQ_DATA_PLANE_REQUEST_TOO_LARGE', 413, 'The data-plane request exceeds its byte limit.');
254
- if (declared !== undefined && total > declared) {
255
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Request body length is invalid.');
256
- }
257
- chunks.push(bytes);
258
- }
259
- if (declared !== undefined && total !== declared) {
260
- throw new AdapterError('HQ_DATA_PLANE_INPUT_INVALID', 400, 'Request body length is invalid.');
261
- }
262
- return total === 0 ? undefined : Buffer.concat(chunks, total);
263
- }
264
- function sendNodeResponse(response, result) {
265
- if (response.writableEnded || response.headersSent)
266
- return;
267
- response.statusCode = result.status;
268
- for (const [name, value] of Object.entries(result.headers))
269
- response.setHeader(name, value);
270
- response.end(result.body);
271
- }
272
- export function createDeploymentDataPlaneNodeHandler(dataPlane, options = {}) {
273
- const maximum = maximumBytes(options.maxRequestBytes);
274
- return async (request, response) => {
275
- const abort = new AbortController();
276
- const onRequestClose = () => {
277
- if (!request.complete)
278
- abort.abort(new Error('The data-plane request was interrupted.'));
279
- };
280
- const onResponseClose = () => {
281
- if (!response.writableEnded)
282
- abort.abort(new Error('The data-plane response was interrupted.'));
283
- };
284
- request.once('close', onRequestClose);
285
- response.once('close', onResponseClose);
286
- try {
287
- const url = new URL(request.url ?? '/', 'http://deployment-data-plane.invalid');
288
- const headers = nodeHeaders(request);
289
- const query = queryParameters(url.searchParams);
290
- const body = await nodeBytes(request, nodeHasBody(headers), contentLength(headers, maximum), maximum);
291
- const adapted = Object.freeze({
292
- method: (request.method ?? 'GET').toUpperCase(), path: url.pathname, query, headers,
293
- });
294
- sendNodeResponse(response, await execute(dataPlane, options, adapted, requestInput(query, body, headers['content-type']), abort.signal));
295
- }
296
- catch (error) {
297
- sendNodeResponse(response, errorResponse(error));
298
- }
299
- finally {
300
- request.off('close', onRequestClose);
301
- response.off('close', onResponseClose);
302
- }
303
- };
304
- }
@@ -1,5 +0,0 @@
1
- import { type ProtocolSchemaValueLimits } from '@hypequery/protocol';
2
- export type DeploymentDataPlaneLimits = ProtocolSchemaValueLimits;
3
- export declare const DEFAULT_DEPLOYMENT_DATA_PLANE_LIMITS: Readonly<ProtocolSchemaValueLimits>;
4
- export declare function resolveDeploymentDataPlaneLimits(input?: Partial<DeploymentDataPlaneLimits>): Readonly<DeploymentDataPlaneLimits>;
5
- //# sourceMappingURL=data-plane-limits.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-plane-limits.d.ts","sourceRoot":"","sources":["../src/data-plane-limits.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAElE,eAAO,MAAM,oCAAoC,qCAAuC,CAAC;AAEzF,wBAAgB,gCAAgC,CAC9C,KAAK,GAAE,OAAO,CAAC,yBAAyB,CAAM,GAC7C,QAAQ,CAAC,yBAAyB,CAAC,CAErC"}
@@ -1,5 +0,0 @@
1
- import { DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS, resolveProtocolSchemaValueLimits, } from '@hypequery/protocol';
2
- export const DEFAULT_DEPLOYMENT_DATA_PLANE_LIMITS = DEFAULT_PROTOCOL_SCHEMA_VALUE_LIMITS;
3
- export function resolveDeploymentDataPlaneLimits(input = {}) {
4
- return resolveProtocolSchemaValueLimits({ limits: input });
5
- }
@@ -1,13 +0,0 @@
1
- import type { ProtocolDeploymentReleaseTarget } from '@hypequery/protocol';
2
- import type { DeploymentRuntimeReferenceExecutionInput } from './data-plane.js';
3
- import type { DeploymentRuntimeSupervisor } from './runtime-supervisor.js';
4
- export interface DeploymentRuntimeSupervisorExecutorOptions {
5
- readonly supervisor: DeploymentRuntimeSupervisor;
6
- readonly target: ProtocolDeploymentReleaseTarget;
7
- /** The immutable activation generation used to build the matching data plane. */
8
- readonly activationRevision: string;
9
- /** Convert provider-neutral execution context into the runtime handler's argument contract. */
10
- readonly argument: (input: DeploymentRuntimeReferenceExecutionInput) => unknown;
11
- }
12
- export declare function createDeploymentRuntimeSupervisorExecutor(options: DeploymentRuntimeSupervisorExecutorOptions): (input: DeploymentRuntimeReferenceExecutionInput) => Promise<unknown>;
13
- //# sourceMappingURL=data-plane-runtime.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-plane-runtime.d.ts","sourceRoot":"","sources":["../src/data-plane-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,KAAK,EACV,wCAAwC,EACzC,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAE3E,MAAM,WAAW,0CAA0C;IACzD,QAAQ,CAAC,UAAU,EAAE,2BAA2B,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,wCAAwC,KAAK,OAAO,CAAC;CACjF;AAED,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,0CAA0C,GAClD,CAAC,KAAK,EAAE,wCAAwC,KAAK,OAAO,CAAC,OAAO,CAAC,CAWvE"}
@@ -1,12 +0,0 @@
1
- export function createDeploymentRuntimeSupervisorExecutor(options) {
2
- if (!/^[0-9a-f]{64}$/.test(options.activationRevision)) {
3
- throw new RangeError('activationRevision must be a lowercase SHA-256 identity');
4
- }
5
- return async (input) => await options.supervisor.invoke({
6
- target: options.target,
7
- activationRevision: options.activationRevision,
8
- query: input.query.name,
9
- argument: options.argument(input),
10
- signal: input.signal,
11
- });
12
- }
@@ -1,84 +0,0 @@
1
- import type { ProtocolDeploymentContract, ProtocolNamedQueryContract, ProtocolQueryImplementation } from '@hypequery/protocol';
2
- import { type DeploymentDataPlaneLimits } from './data-plane-limits.js';
3
- export type DeploymentDataPlaneErrorCode = 'HQ_DATA_PLANE_CONFIGURATION' | 'HQ_DATA_PLANE_ROUTE_NOT_FOUND' | 'HQ_DATA_PLANE_METHOD_NOT_ALLOWED' | 'HQ_DATA_PLANE_UNAUTHENTICATED' | 'HQ_DATA_PLANE_FORBIDDEN' | 'HQ_DATA_PLANE_TENANT_REQUIRED' | 'HQ_DATA_PLANE_INPUT_INVALID' | 'HQ_DATA_PLANE_OUTPUT_INVALID' | 'HQ_DATA_PLANE_EXECUTOR_UNAVAILABLE' | 'HQ_DATA_PLANE_EXECUTION_FAILED' | 'HQ_DATA_PLANE_ABORTED';
4
- export declare class DeploymentDataPlaneError extends Error {
5
- readonly code: DeploymentDataPlaneErrorCode;
6
- readonly path?: string;
7
- constructor(code: DeploymentDataPlaneErrorCode, message: string, options?: {
8
- readonly path?: string;
9
- readonly cause?: unknown;
10
- });
11
- }
12
- export interface DeploymentDataPlanePrincipal {
13
- readonly subject?: string;
14
- readonly roles?: readonly string[];
15
- readonly scopes?: readonly string[];
16
- readonly claims?: Readonly<Record<string, unknown>>;
17
- }
18
- export interface DeploymentDataPlaneRequest {
19
- readonly method: string;
20
- readonly path: string;
21
- readonly input?: unknown;
22
- readonly query?: Readonly<Record<string, string | readonly string[]>>;
23
- readonly headers?: Readonly<Record<string, string>>;
24
- readonly credentials?: unknown;
25
- readonly signal?: AbortSignal;
26
- }
27
- export type DeploymentDataPlaneJsonRequest = Omit<DeploymentDataPlaneRequest, 'input'> & {
28
- readonly input?: string | Uint8Array;
29
- };
30
- export interface DeploymentDataPlaneAuthenticationInput {
31
- readonly credentials: unknown;
32
- readonly request: DeploymentDataPlaneRequest;
33
- readonly query: ProtocolNamedQueryContract;
34
- }
35
- export interface DeploymentDataPlaneTenantInput {
36
- readonly principal: DeploymentDataPlanePrincipal | null;
37
- readonly request: DeploymentDataPlaneRequest;
38
- readonly query: ProtocolNamedQueryContract;
39
- }
40
- export interface DeploymentDataPlaneExecutionInput {
41
- readonly query: ProtocolNamedQueryContract;
42
- readonly input: unknown;
43
- readonly principal: DeploymentDataPlanePrincipal | null;
44
- readonly tenant: unknown;
45
- readonly request: DeploymentDataPlaneRequest;
46
- readonly signal?: AbortSignal;
47
- }
48
- export interface DeploymentSemanticPlanExecutionInput extends DeploymentDataPlaneExecutionInput {
49
- readonly implementation: Extract<ProtocolQueryImplementation, {
50
- readonly kind: 'semantic-plan';
51
- }>;
52
- readonly deployment: ProtocolDeploymentContract;
53
- }
54
- export interface DeploymentCompiledSqlExecutionInput extends DeploymentDataPlaneExecutionInput {
55
- readonly implementation: Extract<ProtocolQueryImplementation, {
56
- readonly kind: 'compiled-sql';
57
- }>;
58
- readonly parameters: Readonly<Record<string, unknown>>;
59
- }
60
- export interface DeploymentRuntimeReferenceExecutionInput extends DeploymentDataPlaneExecutionInput {
61
- readonly implementation: Extract<ProtocolQueryImplementation, {
62
- readonly kind: 'runtime-reference';
63
- }>;
64
- }
65
- export interface DeploymentDataPlaneResult {
66
- readonly query: string;
67
- readonly output: unknown;
68
- readonly cacheTtlMs?: number;
69
- }
70
- export interface DeploymentDataPlane {
71
- execute(request: DeploymentDataPlaneRequest): Promise<DeploymentDataPlaneResult>;
72
- executeJson(request: DeploymentDataPlaneJsonRequest): Promise<DeploymentDataPlaneResult>;
73
- }
74
- export interface DeploymentDataPlaneOptions {
75
- readonly deployment: ProtocolDeploymentContract;
76
- readonly authenticate?: (input: DeploymentDataPlaneAuthenticationInput) => Promise<DeploymentDataPlanePrincipal | null>;
77
- readonly resolveTenant?: (input: DeploymentDataPlaneTenantInput) => Promise<unknown>;
78
- readonly executeSemanticPlan?: (input: DeploymentSemanticPlanExecutionInput) => Promise<unknown>;
79
- readonly executeCompiledSql?: (input: DeploymentCompiledSqlExecutionInput) => Promise<unknown>;
80
- readonly executeRuntimeReference?: (input: DeploymentRuntimeReferenceExecutionInput) => Promise<unknown>;
81
- readonly limits?: Partial<DeploymentDataPlaneLimits>;
82
- }
83
- export declare function createDeploymentDataPlane(options: DeploymentDataPlaneOptions): DeploymentDataPlane;
84
- //# sourceMappingURL=data-plane.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"data-plane.d.ts","sourceRoot":"","sources":["../src/data-plane.ts"],"names":[],"mappings":"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"}