@hypequery/deployment 0.3.0 → 0.5.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 +103 -3
- package/dist/control-plane.d.ts +4 -1
- package/dist/control-plane.d.ts.map +1 -1
- package/dist/control-plane.js +19 -0
- package/dist/data-plane-adapters.d.ts +18 -0
- package/dist/data-plane-adapters.d.ts.map +1 -0
- package/dist/data-plane-adapters.js +304 -0
- package/dist/data-plane-limits.d.ts +5 -0
- package/dist/data-plane-limits.d.ts.map +1 -0
- package/dist/data-plane-limits.js +5 -0
- package/dist/data-plane-runtime.d.ts +13 -0
- package/dist/data-plane-runtime.d.ts.map +1 -0
- package/dist/data-plane-runtime.js +12 -0
- package/dist/data-plane.d.ts +84 -0
- package/dist/data-plane.d.ts.map +1 -0
- package/dist/data-plane.js +209 -0
- package/dist/filesystem-host.d.ts +51 -0
- package/dist/filesystem-host.d.ts.map +1 -0
- package/dist/filesystem-host.js +73 -0
- package/dist/host.d.ts +40 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +183 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/runtime-supervisor.d.ts +8 -1
- package/dist/runtime-supervisor.d.ts.map +1 -1
- package/dist/runtime-supervisor.js +11 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# @hypequery/deployment
|
|
2
2
|
|
|
3
|
-
Provider-neutral verification, intake, activation, and HTTP
|
|
3
|
+
Provider-neutral verification, intake, activation, runtime, and HTTP hosting
|
|
4
4
|
building blocks for Hypequery deployment 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
|
|
8
8
|
storage, and revalidates the release, bundle manifest, file hashes, deployment
|
|
9
|
-
identity, and runtime references before handing the submission to a store.
|
|
10
|
-
does not activate or execute a release.
|
|
9
|
+
identity, and runtime references before handing the submission to a store.
|
|
11
10
|
|
|
12
11
|
## Intake adapters
|
|
13
12
|
|
|
@@ -245,4 +244,105 @@ remote-sandbox isolation behind the same lifecycle interface.
|
|
|
245
244
|
The reference worker is a lifecycle boundary, not a hostile-code security
|
|
246
245
|
sandbox. Only trusted deployment code should use it directly.
|
|
247
246
|
|
|
247
|
+
## Data-plane execution
|
|
248
|
+
|
|
249
|
+
`createDeploymentDataPlane` executes named-query routes from one validated,
|
|
250
|
+
immutable deployment contract. It applies bounded input defaults and unknown
|
|
251
|
+
property behavior, enforces access and tenant policy, dispatches the declared
|
|
252
|
+
implementation kind through an injected adapter, and validates output before
|
|
253
|
+
returning it.
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
import {
|
|
257
|
+
createDeploymentDataPlane,
|
|
258
|
+
createDeploymentRuntimeSupervisorExecutor,
|
|
259
|
+
} from '@hypequery/deployment';
|
|
260
|
+
|
|
261
|
+
const executeRuntimeReference = createDeploymentRuntimeSupervisorExecutor({
|
|
262
|
+
supervisor,
|
|
263
|
+
target,
|
|
264
|
+
activationRevision: snapshot.activation.revision,
|
|
265
|
+
argument: ({ input, principal, tenant }) => ({ input, principal, tenant }),
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const dataPlane = createDeploymentDataPlane({
|
|
269
|
+
deployment: snapshot.deployment,
|
|
270
|
+
authenticate,
|
|
271
|
+
resolveTenant,
|
|
272
|
+
executeSemanticPlan,
|
|
273
|
+
executeCompiledSql,
|
|
274
|
+
executeRuntimeReference,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const result = await dataPlane.execute({
|
|
278
|
+
method: 'POST',
|
|
279
|
+
path: '/analytics/queries/orders',
|
|
280
|
+
credentials,
|
|
281
|
+
input: { status: 'paid' },
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The runtime-supervisor adapter requires the exact activation revision used to
|
|
286
|
+
construct the data plane. A later activation therefore cannot accidentally run
|
|
287
|
+
against stale route or schema metadata. Argument mapping remains explicit so a
|
|
288
|
+
host can preserve the handler contract of its chosen runtime.
|
|
289
|
+
|
|
290
|
+
Semantic-plan and compiled-SQL adapters own database execution. The core passes
|
|
291
|
+
only validated values, the fixed implementation artifact, and closed typed SQL
|
|
292
|
+
parameter bindings; it does not select credentials or interpolate SQL.
|
|
293
|
+
|
|
294
|
+
## Data-plane hosting
|
|
295
|
+
|
|
296
|
+
`createDeploymentHost` keeps route/schema execution and supervised runtime
|
|
297
|
+
dispatch pinned to the same activation revision. Reconciliation builds a new
|
|
298
|
+
data plane from the supervisor's immutable generation view and publishes it
|
|
299
|
+
only after confirming that the active generation did not change during
|
|
300
|
+
configuration.
|
|
301
|
+
|
|
302
|
+
`createDeploymentDataPlaneFetchHandler` and
|
|
303
|
+
`createDeploymentDataPlaneNodeHandler` expose a hosted data plane over HTTP.
|
|
304
|
+
They accept either query parameters or one bounded UTF-8 JSON body, reject
|
|
305
|
+
duplicate JSON property names, forward cancellation, and return bounded JSON
|
|
306
|
+
errors. Public cache metadata is emitted only when execution confirms the
|
|
307
|
+
request was public, tenant-independent, and unauthenticated.
|
|
308
|
+
|
|
309
|
+
For a single-node service, `createFileSystemDeploymentHost` composes the
|
|
310
|
+
filesystem submission store, activation registry, intake, control plane,
|
|
311
|
+
runtime materializer, supervisor, and generation-pinned data plane. It
|
|
312
|
+
reconciles configured targets at startup and schedules reconciliation after a
|
|
313
|
+
durable activation without changing an already-successful activation response
|
|
314
|
+
if runtime startup later fails.
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
import {
|
|
318
|
+
createDeploymentDataPlaneNodeHandler,
|
|
319
|
+
createFileSystemDeploymentHost,
|
|
320
|
+
} from '@hypequery/deployment';
|
|
321
|
+
|
|
322
|
+
const service = createFileSystemDeploymentHost({
|
|
323
|
+
directory: '/var/lib/hypequery/deployments',
|
|
324
|
+
targets: [{ project: 'analytics', environment: 'production' }],
|
|
325
|
+
intake: { authenticator: deploymentAuthenticator, authorizer: deploymentAuthorizer },
|
|
326
|
+
controlPlane: { authenticator: operatorAuthenticator, authorizer: operatorAuthorizer },
|
|
327
|
+
configureDataPlane: () => ({
|
|
328
|
+
authenticate: queryAuthenticator,
|
|
329
|
+
resolveTenant,
|
|
330
|
+
executeSemanticPlan,
|
|
331
|
+
executeCompiledSql,
|
|
332
|
+
runtimeArgument: ({ input, principal, tenant }) => ({ input, principal, tenant }),
|
|
333
|
+
}),
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
await service.start();
|
|
337
|
+
const queryHandler = createDeploymentDataPlaneNodeHandler(
|
|
338
|
+
service.host.dataPlane({ project: 'analytics', environment: 'production' }),
|
|
339
|
+
);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Cloud and other distributed systems can use the same host, supervisor, and HTTP
|
|
343
|
+
adapter interfaces while supplying provider-owned persistence, runtime, SQL,
|
|
344
|
+
authentication, tenant, routing, and observability implementations. The
|
|
345
|
+
filesystem assembly is a reference single-host composition, not a distributed
|
|
346
|
+
control plane.
|
|
347
|
+
|
|
248
348
|
The package is ESM-only and requires Node.js 20 or newer.
|
package/dist/control-plane.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProtocolDeploymentReleaseTarget } from '@hypequery/protocol';
|
|
2
|
-
import { type DeploymentActivationRegistry } from './activation.js';
|
|
2
|
+
import { type DeploymentActivationRecord, type DeploymentActivationRegistry } from './activation.js';
|
|
3
3
|
import { type DeploymentControlPlaneLimits } from './control-plane-limits.js';
|
|
4
4
|
import type { DeploymentAuthenticator, DeploymentIntake, DeploymentIntakeRequest, DeploymentIntakeResponse } from './types.js';
|
|
5
5
|
export type DeploymentControlPlaneAction = 'activate' | 'read-current-activation' | 'read-activation-history';
|
|
@@ -29,6 +29,9 @@ export interface DeploymentControlPlaneOptions<Principal> {
|
|
|
29
29
|
readonly authenticator: DeploymentAuthenticator<Principal>;
|
|
30
30
|
readonly authorizer: DeploymentControlPlaneAuthorizer<Principal>;
|
|
31
31
|
readonly limits?: Partial<DeploymentControlPlaneLimits>;
|
|
32
|
+
/** Called after a successful activation has been durably committed. */
|
|
33
|
+
readonly onActivation?: (activation: DeploymentActivationRecord) => void | Promise<void>;
|
|
34
|
+
readonly onBackgroundError?: (error: unknown) => void;
|
|
32
35
|
}
|
|
33
36
|
export type DeploymentControlPlaneErrorCode = 'HQ_CONTROL_BAD_REQUEST' | 'HQ_CONTROL_UNAUTHENTICATED' | 'HQ_CONTROL_FORBIDDEN' | 'HQ_CONTROL_NOT_FOUND' | 'HQ_CONTROL_METHOD_NOT_ALLOWED' | 'HQ_CONTROL_TOO_LARGE' | 'HQ_CONTROL_RELEASE_NOT_FOUND' | 'HQ_CONTROL_RELEASE_UNAVAILABLE' | 'HQ_CONTROL_INTERNAL';
|
|
34
37
|
export declare function createDeploymentControlPlane<Principal>(options: DeploymentControlPlaneOptions<Principal>): DeploymentControlPlane;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,
|
|
1
|
+
{"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,uBAAuB,EACvB,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,yBAAyB,GACzB,yBAAyB,CAAC;AAE9B,MAAM,WAAW,wCAAwC,CAAC,SAAS;IACjE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,MAAM,WAAW,gCAAgC,CAAC,SAAS;IACzD,SAAS,CAAC,KAAK,EAAE,wCAAwC,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzF;AAED,MAAM,WAAW,6BAA8B,SAAQ,uBAAuB;IAC5E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;IAClF,sEAAsE;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,8BAA8B,GAAG,wBAAwB,CAAC;AAEtE,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAAC;CACzF;AAED,MAAM,WAAW,6BAA6B,CAAC,SAAS;IACtD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,4BAA4B,CAAC;IACnD,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC3D,QAAQ,CAAC,UAAU,EAAE,gCAAgC,CAAC,SAAS,CAAC,CAAC;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACxD,uEAAuE;IACvE,QAAQ,CAAC,YAAY,CAAC,EAAE,CACtB,UAAU,EAAE,0BAA0B,KACnC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD;AAED,MAAM,MAAM,+BAA+B,GACvC,wBAAwB,GACxB,4BAA4B,GAC5B,sBAAsB,GACtB,sBAAsB,GACtB,+BAA+B,GAC/B,sBAAsB,GACtB,8BAA8B,GAC9B,gCAAgC,GAChC,qBAAqB,CAAC;AA+X1B,wBAAgB,4BAA4B,CAAC,SAAS,EACpD,OAAO,EAAE,6BAA6B,CAAC,SAAS,CAAC,GAChD,sBAAsB,CAoIxB"}
|
package/dist/control-plane.js
CHANGED
|
@@ -269,6 +269,24 @@ function validatedHistoryQuery(query, maximum) {
|
|
|
269
269
|
}
|
|
270
270
|
export function createDeploymentControlPlane(options) {
|
|
271
271
|
const limits = resolveDeploymentControlPlaneLimits(options.limits);
|
|
272
|
+
function reportBackgroundError(error) {
|
|
273
|
+
try {
|
|
274
|
+
options.onBackgroundError?.(error);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Diagnostics cannot change the result of an already-durable activation.
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function notifyActivation(activation) {
|
|
281
|
+
try {
|
|
282
|
+
const operation = options.onActivation?.(activation);
|
|
283
|
+
if (operation)
|
|
284
|
+
void Promise.resolve(operation).catch(reportBackgroundError);
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
reportBackgroundError(error);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
272
290
|
async function authenticateAndAuthorize(request, action, target) {
|
|
273
291
|
throwIfAborted(request.signal);
|
|
274
292
|
const token = bearerToken(request.headers);
|
|
@@ -334,6 +352,7 @@ export function createDeploymentControlPlane(options) {
|
|
|
334
352
|
current: result.current,
|
|
335
353
|
});
|
|
336
354
|
}
|
|
355
|
+
notifyActivation(result.activation);
|
|
337
356
|
return activationResponse(result.status, result.activation);
|
|
338
357
|
}
|
|
339
358
|
requireMethod(method, 'GET');
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,304 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-plane.d.ts","sourceRoot":"","sources":["../src/data-plane.ts"],"names":[],"mappings":"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"}
|