@astrale-os/sdk 0.4.9 → 0.4.11
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/dist/auth/identity.d.ts +2 -0
- package/dist/auth/identity.d.ts.map +1 -1
- package/dist/auth/verify.js +1 -1
- package/dist/auth/verify.js.map +1 -1
- package/dist/cli/spec.d.ts.map +1 -1
- package/dist/cli/spec.js +1 -0
- package/dist/cli/spec.js.map +1 -1
- package/dist/config/define-domain.d.ts +5 -1
- package/dist/config/define-domain.d.ts.map +1 -1
- package/dist/config/define-domain.js +1 -0
- package/dist/config/define-domain.js.map +1 -1
- package/dist/defer/index.d.ts +24 -0
- package/dist/defer/index.d.ts.map +1 -0
- package/dist/defer/index.js +42 -0
- package/dist/defer/index.js.map +1 -0
- package/dist/define/remote-function.d.ts +3 -0
- package/dist/define/remote-function.d.ts.map +1 -1
- package/dist/define/remote-function.js.map +1 -1
- package/dist/dispatch/dispatcher.d.ts +6 -3
- package/dist/dispatch/dispatcher.d.ts.map +1 -1
- package/dist/dispatch/dispatcher.js +45 -23
- package/dist/dispatch/dispatcher.js.map +1 -1
- package/dist/dispatch/execute.d.ts +2 -0
- package/dist/dispatch/execute.d.ts.map +1 -1
- package/dist/dispatch/execute.js +1 -0
- package/dist/dispatch/execute.js.map +1 -1
- package/dist/domain/build-spec.js +4 -0
- package/dist/domain/build-spec.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/method/context.d.ts +3 -0
- package/dist/method/context.d.ts.map +1 -1
- package/dist/server/auxiliary-routes.d.ts.map +1 -1
- package/dist/server/auxiliary-routes.js +47 -11
- package/dist/server/auxiliary-routes.js.map +1 -1
- package/dist/server/worker-entry.d.ts +3 -2
- package/dist/server/worker-entry.d.ts.map +1 -1
- package/dist/server/worker-entry.js +2 -2
- package/dist/server/worker-entry.js.map +1 -1
- package/package.json +1 -1
- package/src/auth/identity.ts +2 -0
- package/src/auth/verify.ts +1 -1
- package/src/cli/spec.ts +1 -0
- package/src/config/define-domain.ts +6 -1
- package/src/defer/index.ts +64 -0
- package/src/define/remote-function.ts +3 -0
- package/src/dispatch/dispatcher.ts +50 -22
- package/src/dispatch/execute.ts +3 -0
- package/src/domain/build-spec.ts +4 -0
- package/src/index.ts +3 -0
- package/src/method/context.ts +3 -0
- package/src/server/auxiliary-routes.ts +59 -10
- package/src/server/worker-entry.ts +12 -4
|
@@ -18,10 +18,15 @@ import type { AuthContext } from '@astrale-os/kernel-core'
|
|
|
18
18
|
import type { Context, Hono } from 'hono'
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
|
+
decodeKernelRequest,
|
|
21
22
|
isKernelErrorClassifiable,
|
|
23
|
+
KERNEL_CONTENT_TYPE_JSON,
|
|
24
|
+
KERNEL_CONTENT_TYPE_MSGPACK,
|
|
22
25
|
KERNEL_ERROR_CODES,
|
|
23
26
|
kernelErrorHttpStatus,
|
|
27
|
+
resolveCodec,
|
|
24
28
|
type KernelErrorPayload,
|
|
29
|
+
type RequestId,
|
|
25
30
|
} from '@astrale-os/kernel-api'
|
|
26
31
|
import {
|
|
27
32
|
isSubdomainOf,
|
|
@@ -41,6 +46,7 @@ import type { AuxIdentityMap } from '../dispatch/identity'
|
|
|
41
46
|
import { makeFunctionContext } from '../auth/function-context'
|
|
42
47
|
import { makeDomainAuthority } from '../auth/issuer-mint'
|
|
43
48
|
import { resolveInboundAuth } from '../auth/resolve'
|
|
49
|
+
import { createHandlerLifecycle, executionLifetime } from '../defer'
|
|
44
50
|
import { runAuthorize } from '../dispatch/authorize'
|
|
45
51
|
import { SdkResultValidationError, SdkValidationError } from '../dispatch/errors'
|
|
46
52
|
import { validateParams, validateResult } from '../dispatch/validate'
|
|
@@ -137,11 +143,8 @@ export function mountAuxiliaryRoutes<TDeps>(config: AuxiliaryRoutesConfig<TDeps>
|
|
|
137
143
|
identity,
|
|
138
144
|
corsHeaders,
|
|
139
145
|
run: async ({ c, auth, kernel }) => {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
.json()
|
|
143
|
-
.catch(() => ({}))
|
|
144
|
-
const validation = validateParams(def.inputSchema, rawBody)
|
|
146
|
+
const input = await readRemoteFunctionInput(c)
|
|
147
|
+
const validation = validateParams(def.inputSchema, input.params)
|
|
145
148
|
if (!validation.ok) {
|
|
146
149
|
throw new SdkValidationError(validation.issues as SdkValidationError['issues'])
|
|
147
150
|
}
|
|
@@ -169,10 +172,20 @@ export function mountAuxiliaryRoutes<TDeps>(config: AuxiliaryRoutesConfig<TDeps>
|
|
|
169
172
|
}),
|
|
170
173
|
}
|
|
171
174
|
if (def.authorize) await runAuthorize(def.authorize, ctx)
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
const lifecycle = createHandlerLifecycle(executionLifetime(c))
|
|
176
|
+
const result = await (async () => {
|
|
177
|
+
try {
|
|
178
|
+
return await def.execute({
|
|
179
|
+
...ctx,
|
|
180
|
+
step: createInlineStep({
|
|
181
|
+
scope: { kind: 'function', ref: `function.${slug}`, slug },
|
|
182
|
+
}),
|
|
183
|
+
defer: lifecycle.defer,
|
|
184
|
+
})
|
|
185
|
+
} finally {
|
|
186
|
+
await lifecycle.settle()
|
|
187
|
+
}
|
|
188
|
+
})()
|
|
176
189
|
const outValidation = validateResult(def.outputSchema, result)
|
|
177
190
|
if (!outValidation.ok) {
|
|
178
191
|
throw new SdkResultValidationError(
|
|
@@ -180,7 +193,10 @@ export function mountAuxiliaryRoutes<TDeps>(config: AuxiliaryRoutesConfig<TDeps>
|
|
|
180
193
|
`function.${slug}`,
|
|
181
194
|
)
|
|
182
195
|
}
|
|
183
|
-
return c.json({
|
|
196
|
+
return c.json({
|
|
197
|
+
result: outValidation.data,
|
|
198
|
+
...(input.enveloped ? { id: input.id ?? null } : {}),
|
|
199
|
+
})
|
|
184
200
|
},
|
|
185
201
|
})
|
|
186
202
|
}
|
|
@@ -306,6 +322,39 @@ function mountEntry(args: MountEntryArgs): void {
|
|
|
306
322
|
})
|
|
307
323
|
}
|
|
308
324
|
|
|
325
|
+
type RemoteFunctionInput = {
|
|
326
|
+
params: unknown
|
|
327
|
+
enveloped: boolean
|
|
328
|
+
id?: RequestId
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* A Function binding is reached in two legitimate ways:
|
|
333
|
+
* - kernel-client follows a graph redirect and sends the canonical kernel envelope;
|
|
334
|
+
* - an external webhook caller POSTs its raw JSON contract directly.
|
|
335
|
+
*
|
|
336
|
+
* The vendor content type is the discriminator. Shape-sniffing would break a valid
|
|
337
|
+
* webhook whose own payload happens to contain `method` and `params` fields.
|
|
338
|
+
*/
|
|
339
|
+
async function readRemoteFunctionInput(c: Context): Promise<RemoteFunctionInput> {
|
|
340
|
+
const contentType = c.req.header('content-type') ?? ''
|
|
341
|
+
const isJsonEnvelope = contentType.includes(KERNEL_CONTENT_TYPE_JSON)
|
|
342
|
+
const isMsgpackEnvelope = contentType.includes(KERNEL_CONTENT_TYPE_MSGPACK)
|
|
343
|
+
|
|
344
|
+
if (isJsonEnvelope || isMsgpackEnvelope) {
|
|
345
|
+
const bytes = new Uint8Array(await c.req.raw.clone().arrayBuffer())
|
|
346
|
+
const codec = resolveCodec(isMsgpackEnvelope ? 'msgpack' : 'json')
|
|
347
|
+
const request = decodeKernelRequest(codec.decode(bytes))
|
|
348
|
+
return { params: request.params, enveloped: true, id: request.id }
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const params: unknown = await c.req.raw
|
|
352
|
+
.clone()
|
|
353
|
+
.json()
|
|
354
|
+
.catch(() => ({}))
|
|
355
|
+
return { params, enveloped: false }
|
|
356
|
+
}
|
|
357
|
+
|
|
309
358
|
function applyCorsToContext(c: Context, headers: Record<string, string>): void {
|
|
310
359
|
for (const [name, value] of Object.entries(headers)) c.header(name, value)
|
|
311
360
|
}
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
* The worker file is then just schema + methods + a `build(url, env)` callback.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
+
import type { ExecutionContext } from 'hono'
|
|
26
|
+
|
|
25
27
|
import type { RemoteServerConfig } from './config'
|
|
26
28
|
|
|
27
29
|
import { createRemoteServer } from './create'
|
|
@@ -29,7 +31,13 @@ import { requireEnv } from './require-env'
|
|
|
29
31
|
import { canonicalizeServingUrl } from './serving-url'
|
|
30
32
|
|
|
31
33
|
type Fetcher = { fetch(request: Request): Response | Promise<Response> }
|
|
32
|
-
type App = {
|
|
34
|
+
type App = {
|
|
35
|
+
fetch(
|
|
36
|
+
request: Request,
|
|
37
|
+
env?: unknown,
|
|
38
|
+
executionCtx?: ExecutionContext,
|
|
39
|
+
): Response | Promise<Response>
|
|
40
|
+
}
|
|
33
41
|
|
|
34
42
|
/** A built app cached by its serving URL: `origin` for same-origin matching,
|
|
35
43
|
* `app` for in-process self-dispatch. */
|
|
@@ -130,7 +138,7 @@ export interface WorkerEntryConfig<TDeps> {
|
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
export interface WorkerEntry<TDeps> {
|
|
133
|
-
fetch(request: Request, env: TDeps): Response | Promise<Response>
|
|
141
|
+
fetch(request: Request, env: TDeps, executionCtx?: ExecutionContext): Response | Promise<Response>
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
/**
|
|
@@ -243,7 +251,7 @@ export function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): Work
|
|
|
243
251
|
}
|
|
244
252
|
|
|
245
253
|
return {
|
|
246
|
-
async fetch(request: Request, env: TDeps): Promise<Response> {
|
|
254
|
+
async fetch(request: Request, env: TDeps, executionCtx?: ExecutionContext): Promise<Response> {
|
|
247
255
|
if (config.selfBinding) self ??= config.selfBinding(env) ?? null
|
|
248
256
|
if (config.routeSubrequest) routeEnv = env
|
|
249
257
|
// Only parse the request URL when a hook actually needs it.
|
|
@@ -259,7 +267,7 @@ export function createWorkerEntry<TDeps>(config: WorkerEntryConfig<TDeps>): Work
|
|
|
259
267
|
: requireEnv(env, 'WORKER_URL', "the worker's public serving URL (its iss identity)")
|
|
260
268
|
const url = canonicalizeServingUrl(raw)
|
|
261
269
|
const dispatched = config.rewriteRequest ? config.rewriteRequest(env, request) : request
|
|
262
|
-
return getApp(url, env).fetch(dispatched)
|
|
270
|
+
return getApp(url, env).fetch(dispatched, env, executionCtx)
|
|
263
271
|
},
|
|
264
272
|
}
|
|
265
273
|
}
|