@astrale-os/kernel-server 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/app/create.d.ts +48 -0
  2. package/dist/app/create.d.ts.map +1 -0
  3. package/dist/app/create.js +107 -0
  4. package/dist/app/create.js.map +1 -0
  5. package/dist/app/index.d.ts +4 -0
  6. package/dist/app/index.d.ts.map +1 -0
  7. package/dist/app/index.js +4 -0
  8. package/dist/app/index.js.map +1 -0
  9. package/dist/app/multiplexed.d.ts +53 -0
  10. package/dist/app/multiplexed.d.ts.map +1 -0
  11. package/dist/app/multiplexed.js +63 -0
  12. package/dist/app/multiplexed.js.map +1 -0
  13. package/dist/app/ws-upgrade.d.ts +35 -0
  14. package/dist/app/ws-upgrade.d.ts.map +1 -0
  15. package/dist/app/ws-upgrade.js +93 -0
  16. package/dist/app/ws-upgrade.js.map +1 -0
  17. package/dist/cors.d.ts +21 -0
  18. package/dist/cors.d.ts.map +1 -0
  19. package/dist/cors.js +17 -0
  20. package/dist/cors.js.map +1 -0
  21. package/dist/envelope/batch.d.ts +12 -0
  22. package/dist/envelope/batch.d.ts.map +1 -0
  23. package/dist/envelope/batch.js +90 -0
  24. package/dist/envelope/batch.js.map +1 -0
  25. package/dist/envelope/codec.d.ts +26 -0
  26. package/dist/envelope/codec.d.ts.map +1 -0
  27. package/dist/envelope/codec.js +52 -0
  28. package/dist/envelope/codec.js.map +1 -0
  29. package/dist/envelope/credential.d.ts +20 -0
  30. package/dist/envelope/credential.d.ts.map +1 -0
  31. package/dist/envelope/credential.js +32 -0
  32. package/dist/envelope/credential.js.map +1 -0
  33. package/dist/envelope/http.d.ts +30 -0
  34. package/dist/envelope/http.d.ts.map +1 -0
  35. package/dist/envelope/http.js +128 -0
  36. package/dist/envelope/http.js.map +1 -0
  37. package/dist/envelope/index.d.ts +6 -0
  38. package/dist/envelope/index.d.ts.map +1 -0
  39. package/dist/envelope/index.js +6 -0
  40. package/dist/envelope/index.js.map +1 -0
  41. package/dist/envelope/sse.d.ts +11 -0
  42. package/dist/envelope/sse.d.ts.map +1 -0
  43. package/dist/envelope/sse.js +73 -0
  44. package/dist/envelope/sse.js.map +1 -0
  45. package/dist/envelope/ws.d.ts +32 -0
  46. package/dist/envelope/ws.d.ts.map +1 -0
  47. package/dist/envelope/ws.js +136 -0
  48. package/dist/envelope/ws.js.map +1 -0
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +17 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/jwks/discovery.d.ts +40 -0
  54. package/dist/jwks/discovery.d.ts.map +1 -0
  55. package/dist/jwks/discovery.js +113 -0
  56. package/dist/jwks/discovery.js.map +1 -0
  57. package/dist/jwks/index.d.ts +3 -0
  58. package/dist/jwks/index.d.ts.map +1 -0
  59. package/dist/jwks/index.js +3 -0
  60. package/dist/jwks/index.js.map +1 -0
  61. package/dist/jwks/issuers.d.ts +47 -0
  62. package/dist/jwks/issuers.d.ts.map +1 -0
  63. package/dist/jwks/issuers.js +76 -0
  64. package/dist/jwks/issuers.js.map +1 -0
  65. package/dist/jwks/keys.d.ts +44 -0
  66. package/dist/jwks/keys.d.ts.map +1 -0
  67. package/dist/jwks/keys.js +56 -0
  68. package/dist/jwks/keys.js.map +1 -0
  69. package/dist/plan/host-params.d.ts +13 -0
  70. package/dist/plan/host-params.d.ts.map +1 -0
  71. package/dist/plan/host-params.js +23 -0
  72. package/dist/plan/host-params.js.map +1 -0
  73. package/dist/plan/host.d.ts +24 -0
  74. package/dist/plan/host.d.ts.map +1 -0
  75. package/dist/plan/host.js +24 -0
  76. package/dist/plan/host.js.map +1 -0
  77. package/dist/plan/index.d.ts +4 -0
  78. package/dist/plan/index.d.ts.map +1 -0
  79. package/dist/plan/index.js +4 -0
  80. package/dist/plan/index.js.map +1 -0
  81. package/dist/plan/walk.d.ts +51 -0
  82. package/dist/plan/walk.d.ts.map +1 -0
  83. package/dist/plan/walk.js +110 -0
  84. package/dist/plan/walk.js.map +1 -0
  85. package/dist/render/binary.d.ts +19 -0
  86. package/dist/render/binary.d.ts.map +1 -0
  87. package/dist/render/binary.js +33 -0
  88. package/dist/render/binary.js.map +1 -0
  89. package/dist/render/body.d.ts +10 -0
  90. package/dist/render/body.d.ts.map +1 -0
  91. package/dist/render/body.js +17 -0
  92. package/dist/render/body.js.map +1 -0
  93. package/dist/render/index.d.ts +3 -0
  94. package/dist/render/index.d.ts.map +1 -0
  95. package/dist/render/index.js +3 -0
  96. package/dist/render/index.js.map +1 -0
  97. package/dist/routed/credential.d.ts +10 -0
  98. package/dist/routed/credential.d.ts.map +1 -0
  99. package/dist/routed/credential.js +55 -0
  100. package/dist/routed/credential.js.map +1 -0
  101. package/dist/routed/handler.d.ts +36 -0
  102. package/dist/routed/handler.d.ts.map +1 -0
  103. package/dist/routed/handler.js +119 -0
  104. package/dist/routed/handler.js.map +1 -0
  105. package/dist/routed/index.d.ts +5 -0
  106. package/dist/routed/index.d.ts.map +1 -0
  107. package/dist/routed/index.js +5 -0
  108. package/dist/routed/index.js.map +1 -0
  109. package/dist/routed/params.d.ts +40 -0
  110. package/dist/routed/params.d.ts.map +1 -0
  111. package/dist/routed/params.js +146 -0
  112. package/dist/routed/params.js.map +1 -0
  113. package/dist/routed/stream.d.ts +21 -0
  114. package/dist/routed/stream.d.ts.map +1 -0
  115. package/dist/routed/stream.js +69 -0
  116. package/dist/routed/stream.js.map +1 -0
  117. package/package.json +45 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Domain walker — turns a list of MountableContract into a mount plan.
3
+ *
4
+ * For each contract, decide whether it mounts on THIS server:
5
+ * - ambient (no binding.remoteUrl) → always mount
6
+ * - anchored (binding.remoteUrl set) → match host pattern against host.url
7
+ *
8
+ * Then bucket by base URL to compute one kernel mount per unique (host+basePath).
9
+ * Collect route bindings and check for path collisions.
10
+ *
11
+ * See docs/protocol-redesign.md §6 ("Server").
12
+ */
13
+ import type { MountableContract, RouteBinding } from '@astrale-os/kernel-api/routed';
14
+ import { type ServerHost } from './host';
15
+ export type MountedFunction = {
16
+ contract: MountableContract;
17
+ /**
18
+ * Base URL template for this function's kernel mount.
19
+ *
20
+ * Ambient functions share the server host URL. Anchored functions use
21
+ * their own `binding.remoteUrl` (verified to match the server host).
22
+ */
23
+ baseUrl: string;
24
+ /** Anchored functions only — the parsed base path from remoteUrl. */
25
+ basePath: string;
26
+ };
27
+ export type MountedRoute = {
28
+ contract: MountableContract;
29
+ route: RouteBinding;
30
+ /** Full path from base URL (host stripped) + route.path. */
31
+ fullPath: string;
32
+ /** Normalized pattern: `{name}` → `:p`, `{name+}` → `*` — used for collision detection. */
33
+ normalizedKey: string;
34
+ };
35
+ export type MountPlan = {
36
+ /** Kernel mounts keyed by their base path (relative to the server host URL). */
37
+ kernelMounts: Map<string, MountedFunction[]>;
38
+ /** Route mounts. */
39
+ routes: MountedRoute[];
40
+ /** Fully-qualified method name → mounted function (for dispatch lookup). */
41
+ methodIndex: Map<string, MountedFunction>;
42
+ /**
43
+ * Compiled Host header matcher when the server host URL contains placeholders.
44
+ * Used at request time to extract host params and merge into params.
45
+ */
46
+ hostMatcher: RegExp | null;
47
+ /** Names of host placeholders, in source order. */
48
+ hostPlaceholders: string[];
49
+ };
50
+ export declare function walkDomain(contracts: MountableContract[], host: ServerHost): MountPlan;
51
+ //# sourceMappingURL=walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../plan/walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AAIpF,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAA;AAIzD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,KAAK,EAAE,YAAY,CAAA;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB,2FAA2F;IAC3F,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,gFAAgF;IAChF,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;IAC5C,oBAAoB;IACpB,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,4EAA4E;IAC5E,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACzC;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B,CAAA;AAID,wBAAgB,UAAU,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,CAgGtF"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Domain walker — turns a list of MountableContract into a mount plan.
3
+ *
4
+ * For each contract, decide whether it mounts on THIS server:
5
+ * - ambient (no binding.remoteUrl) → always mount
6
+ * - anchored (binding.remoteUrl set) → match host pattern against host.url
7
+ *
8
+ * Then bucket by base URL to compute one kernel mount per unique (host+basePath).
9
+ * Collect route bindings and check for path collisions.
10
+ *
11
+ * See docs/protocol-redesign.md §6 ("Server").
12
+ */
13
+ import { isSubdomainOf, parseUrlTemplate } from '@astrale-os/kernel-api/routed';
14
+ import { parseServerHost } from './host';
15
+ // ─── Walk ────────────────────────────────────────────────────────────────────
16
+ export function walkDomain(contracts, host) {
17
+ const parsed = parseServerHost(host);
18
+ const kernelMounts = new Map();
19
+ const routes = [];
20
+ const methodIndex = new Map();
21
+ const routeCollisionKeys = new Map();
22
+ for (const contract of contracts) {
23
+ const binding = contract.binding;
24
+ const remoteUrl = binding?.remoteUrl;
25
+ let basePath;
26
+ let baseUrl;
27
+ if (!remoteUrl) {
28
+ // Ambient — mounts at the server host URL.
29
+ basePath = parsed.basePath;
30
+ baseUrl = host.url;
31
+ }
32
+ else {
33
+ // Anchored — must match or be a subdomain of the server's host pattern.
34
+ const fnParsed = parseUrlTemplate(remoteUrl);
35
+ if (!isSubdomainOf(fnParsed.hostPattern, parsed.hostPattern)) {
36
+ // Not this server's responsibility — skip (debug log).
37
+ // oxlint-disable-next-line no-console
38
+ console.debug(`[server] Skipping ${contract.ref}: remoteUrl host "${fnParsed.hostPattern}" does not match server host "${parsed.hostPattern}"`);
39
+ continue;
40
+ }
41
+ basePath = stripTrailingSlash(fnParsed.basePath);
42
+ baseUrl = remoteUrl;
43
+ }
44
+ const mounted = { contract, baseUrl, basePath };
45
+ methodIndex.set(contract.ref, mounted);
46
+ // Add to the kernel mount bucket for this basePath.
47
+ const bucket = kernelMounts.get(basePath) ?? [];
48
+ bucket.push(mounted);
49
+ kernelMounts.set(basePath, bucket);
50
+ // Route binding?
51
+ if (binding?.route) {
52
+ const route = binding.route;
53
+ const fullPath = joinPath(basePath, route.path);
54
+ const normalizedPath = normalizePath(fullPath);
55
+ const normalizedKey = `${route.method} ${normalizedPath}`;
56
+ if (route.method === '*') {
57
+ // Wildcard: collides with ANY existing route on this path.
58
+ const wildcardKey = `* ${normalizedPath}`;
59
+ const existingWild = routeCollisionKeys.get(wildcardKey);
60
+ if (existingWild) {
61
+ throw new Error(`Route collision: ${contract.ref} and ${existingWild} both mount at ${wildcardKey}`);
62
+ }
63
+ for (const m of ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']) {
64
+ const specificKey = `${m} ${normalizedPath}`;
65
+ const existingSpecific = routeCollisionKeys.get(specificKey);
66
+ if (existingSpecific) {
67
+ throw new Error(`Route collision: ${contract.ref} (wildcard) and ${existingSpecific} both mount at ${specificKey}`);
68
+ }
69
+ }
70
+ routeCollisionKeys.set(wildcardKey, contract.ref);
71
+ }
72
+ else {
73
+ // Specific method: check same method AND existing wildcard.
74
+ const existing = routeCollisionKeys.get(normalizedKey);
75
+ if (existing) {
76
+ throw new Error(`Route collision: ${contract.ref} and ${existing} both mount at ${normalizedKey}`);
77
+ }
78
+ const existingWild = routeCollisionKeys.get(`* ${normalizedPath}`);
79
+ if (existingWild) {
80
+ throw new Error(`Route collision: ${contract.ref} and ${existingWild} (wildcard) both mount at * ${normalizedPath}`);
81
+ }
82
+ routeCollisionKeys.set(normalizedKey, contract.ref);
83
+ }
84
+ routes.push({ contract, route, fullPath, normalizedKey });
85
+ }
86
+ }
87
+ return {
88
+ kernelMounts,
89
+ routes,
90
+ methodIndex,
91
+ hostMatcher: parsed.hostMatcher,
92
+ hostPlaceholders: parsed.hostPlaceholders,
93
+ };
94
+ }
95
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
96
+ function stripTrailingSlash(p) {
97
+ if (p.length > 1 && p.endsWith('/'))
98
+ return p.slice(0, -1);
99
+ return p;
100
+ }
101
+ function joinPath(base, child) {
102
+ const b = stripTrailingSlash(base);
103
+ // child is guaranteed to start with '/'
104
+ return `${b}${child}` || '/';
105
+ }
106
+ /** Normalize a path template for collision detection. */
107
+ function normalizePath(path) {
108
+ return path.replace(/\{[a-zA-Z_]\w*[+*]\}/g, '*').replace(/\{[a-zA-Z_]\w*\}/g, ':p');
109
+ }
110
+ //# sourceMappingURL=walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../../plan/walk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Binary HTTP response — `BinaryResult` → `Response`.
3
+ *
4
+ * Tags binary responses with `x-binary-result: true` so kernel-client can
5
+ * distinguish them from accidental opaque blobs (the kernel envelope is
6
+ * bypassed for binary results).
7
+ *
8
+ * Header precedence (low → high, later wins):
9
+ * CORS headers < `br.headers` < canonical `content-type` + `x-binary-result`
10
+ *
11
+ * This lets a handler pass through any framing-specific headers its body
12
+ * needs (e.g. `x-vercel-ai-ui-message-stream`, `x-accel-buffering`, a tuned
13
+ * `cache-control`) while guaranteeing the kernel's own invariants
14
+ * (`content-type` matches `br.contentType`, `x-binary-result` is always
15
+ * set) cannot be accidentally clobbered.
16
+ */
17
+ import type { BinaryResult } from '@astrale-os/kernel-api';
18
+ export declare function buildBinaryResponse(br: BinaryResult, corsHeaders: Record<string, string>): Response;
19
+ //# sourceMappingURL=binary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../render/binary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAM1D,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,YAAY,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,QAAQ,CAcV"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Binary HTTP response — `BinaryResult` → `Response`.
3
+ *
4
+ * Tags binary responses with `x-binary-result: true` so kernel-client can
5
+ * distinguish them from accidental opaque blobs (the kernel envelope is
6
+ * bypassed for binary results).
7
+ *
8
+ * Header precedence (low → high, later wins):
9
+ * CORS headers < `br.headers` < canonical `content-type` + `x-binary-result`
10
+ *
11
+ * This lets a handler pass through any framing-specific headers its body
12
+ * needs (e.g. `x-vercel-ai-ui-message-stream`, `x-accel-buffering`, a tuned
13
+ * `cache-control`) while guaranteeing the kernel's own invariants
14
+ * (`content-type` matches `br.contentType`, `x-binary-result` is always
15
+ * set) cannot be accidentally clobbered.
16
+ */
17
+ import { BINARY_RESULT_HEADER } from '@astrale-os/kernel-api';
18
+ import { toBody } from './body';
19
+ export function buildBinaryResponse(br, corsHeaders) {
20
+ const body = br.body instanceof Uint8Array
21
+ ? toBody(br.body)
22
+ : br.body;
23
+ return new Response(body, {
24
+ status: br.status ?? 200,
25
+ headers: {
26
+ ...corsHeaders,
27
+ ...br.headers,
28
+ 'content-type': br.contentType,
29
+ [BINARY_RESULT_HEADER]: 'true',
30
+ },
31
+ });
32
+ }
33
+ //# sourceMappingURL=binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../render/binary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAE7D,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,UAAU,mBAAmB,CACjC,EAAgB,EAChB,WAAmC;IAEnC,MAAM,IAAI,GACR,EAAE,CAAC,IAAI,YAAY,UAAU;QAC3B,CAAC,CAAE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAiB;QAClC,CAAC,CAAE,EAAE,CAAC,IAAmC,CAAA;IAC7C,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,GAAG;QACxB,OAAO,EAAE;YACP,GAAG,WAAW;YACd,GAAG,EAAE,CAAC,OAAO;YACb,cAAc,EAAE,EAAE,CAAC,WAAW;YAC9B,CAAC,oBAAoB,CAAC,EAAE,MAAM;SAC/B;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Convert codec output (string or Uint8Array) to a Response-compatible body.
3
+ *
4
+ * Text codecs (JSON) return strings — passed through.
5
+ * Binary codecs (MsgPack) return Uint8Array — narrowed to ArrayBuffer for
6
+ * tsgo's stricter `BodyInit` typing. The fast path avoids a copy when the
7
+ * Uint8Array is a full view of its backing buffer.
8
+ */
9
+ export declare function toBody(data: string | Uint8Array): string | ArrayBuffer;
10
+ //# sourceMappingURL=body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../../render/body.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,WAAW,CAMtE"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Convert codec output (string or Uint8Array) to a Response-compatible body.
3
+ *
4
+ * Text codecs (JSON) return strings — passed through.
5
+ * Binary codecs (MsgPack) return Uint8Array — narrowed to ArrayBuffer for
6
+ * tsgo's stricter `BodyInit` typing. The fast path avoids a copy when the
7
+ * Uint8Array is a full view of its backing buffer.
8
+ */
9
+ export function toBody(data) {
10
+ if (typeof data === 'string')
11
+ return data;
12
+ if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
13
+ return data.buffer;
14
+ }
15
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
16
+ }
17
+ //# sourceMappingURL=body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.js","sourceRoot":"","sources":["../../render/body.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,IAAyB;IAC9C,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACzC,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACxE,OAAO,IAAI,CAAC,MAAqB,CAAA;IACnC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAgB,CAAA;AAC7F,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { toBody } from './body';
2
+ export { buildBinaryResponse } from './binary';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { toBody } from './body';
2
+ export { buildBinaryResponse } from './binary';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Credential extraction for route bindings.
3
+ *
4
+ * A route binding declares where to find the request credential — header,
5
+ * cookie, or query parameter — via its `route.credential` field. This module
6
+ * implements the lookup, including cookie splitting and URL decoding.
7
+ */
8
+ import type { CredentialSource } from '@astrale-os/kernel-api';
9
+ export declare function readCredential(req: Request, source: CredentialSource): string;
10
+ //# sourceMappingURL=credential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../../routed/credential.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAA0B,MAAM,wBAAwB,CAAA;AAEtF,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAS7E"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Credential extraction for route bindings.
3
+ *
4
+ * A route binding declares where to find the request credential — header,
5
+ * cookie, or query parameter — via its `route.credential` field. This module
6
+ * implements the lookup, including cookie splitting and URL decoding.
7
+ */
8
+ export function readCredential(req, source) {
9
+ if (Array.isArray(source)) {
10
+ for (const s of source) {
11
+ const value = readSingle(req, s);
12
+ if (value)
13
+ return value;
14
+ }
15
+ return '';
16
+ }
17
+ return readSingle(req, source);
18
+ }
19
+ function readSingle(req, source) {
20
+ switch (source.in) {
21
+ case 'header': {
22
+ const raw = req.headers.get(source.name ?? 'authorization') ?? '';
23
+ return stripBearerPrefix(raw);
24
+ }
25
+ case 'query':
26
+ return new URL(req.url).searchParams.get(source.name ?? 'credential') ?? '';
27
+ case 'cookie': {
28
+ const header = req.headers.get('cookie');
29
+ if (!header || !source.name)
30
+ return '';
31
+ const cookies = header.split(';').map((c) => c.trim());
32
+ for (const c of cookies) {
33
+ const [k, v] = c.split('=', 2);
34
+ if (k === source.name)
35
+ return decodeURIComponent(v ?? '');
36
+ }
37
+ return '';
38
+ }
39
+ }
40
+ }
41
+ /**
42
+ * Strip an optional `Bearer ` (case-insensitive) prefix from an
43
+ * Authorization-header value. Other values pass through as-is —
44
+ * validation is the auth layer's responsibility, not extraction's.
45
+ *
46
+ * Header-source credentials are interpreted per RFC 7235: the header value is
47
+ * `<scheme> <credentials>`, so an optional leading `Bearer ` prefix is
48
+ * stripped. This keeps the reader HTTP-standard-compliant and lets route
49
+ * bindings interoperate with any client that sends `Authorization: Bearer
50
+ * <token>`
51
+ */
52
+ function stripBearerPrefix(value) {
53
+ return value.trim().replace(/^Bearer\s+/i, '');
54
+ }
55
+ //# sourceMappingURL=credential.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential.js","sourceRoot":"","sources":["../../routed/credential.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,UAAU,cAAc,CAAC,GAAY,EAAE,MAAwB;IACnE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAChC,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;QACzB,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;AAChC,CAAC;AAED,SAAS,UAAU,CAAC,GAAY,EAAE,MAA8B;IAC9D,QAAQ,MAAM,CAAC,EAAE,EAAE,CAAC;QAClB,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,CAAA;YACjE,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAA;QAC/B,CAAC;QACD,KAAK,OAAO;YACV,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC,IAAI,EAAE,CAAA;QAC7E,KAAK,QAAQ,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACxC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI;gBAAE,OAAO,EAAE,CAAA;YACtC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACtD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;gBAC9B,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI;oBAAE,OAAO,kBAAkB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YAC3D,CAAC;YACD,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;AAChD,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Route binding HTTP handler — native HTTP shape (REST-like).
3
+ *
4
+ * One handler per mounted route. Decodes params from the request, dispatches
5
+ * via the kernel API, encodes the response per output mode:
6
+ * - value → JSON body, HTTP status from error code table on error
7
+ * - stream → SSE with one event per yielded chunk (raw, NOT kernel envelope)
8
+ * - binary → raw bytes with BinaryResult contentType + status
9
+ *
10
+ * Errors use the kernel envelope's `{ error: { code, message, data? } }` shape
11
+ * for consistency with kernel HTTP. The HTTP status comes from the error code
12
+ * table (`kernelErrorHttpStatus`).
13
+ */
14
+ import type { KernelAPI, RouteBinding } from '@astrale-os/kernel-api';
15
+ import type { AuthPolicy } from '@astrale-os/kernel-api/routed';
16
+ import type { CorsConfig } from '../cors';
17
+ export type RouteHandlerConfig = {
18
+ /** The full kernel method name to dispatch (e.g. `Task.read`). */
19
+ method: string;
20
+ route: RouteBinding;
21
+ kernel: KernelAPI;
22
+ cors: CorsConfig;
23
+ /**
24
+ * Optional host placeholder extractor — returned values are merged into
25
+ * params at the lowest priority (host < path < query < header < body).
26
+ * Return null to reject the request with 404.
27
+ */
28
+ hostParams?: (req: Request) => Record<string, string> | null;
29
+ /** Authentication policy from the method definition. Defaults to `'required'`. */
30
+ auth?: AuthPolicy;
31
+ };
32
+ /**
33
+ * Build a Hono-compatible handler for a single route binding.
34
+ */
35
+ export declare function createRouteHandler(config: RouteHandlerConfig): (req: Request, pathParams: Record<string, string>) => Promise<Response>;
36
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../routed/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAiC,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACpG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAU/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AA0BzC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,UAAU,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5D,kFAAkF;IAClF,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,GACzB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAuGzE"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Route binding HTTP handler — native HTTP shape (REST-like).
3
+ *
4
+ * One handler per mounted route. Decodes params from the request, dispatches
5
+ * via the kernel API, encodes the response per output mode:
6
+ * - value → JSON body, HTTP status from error code table on error
7
+ * - stream → SSE with one event per yielded chunk (raw, NOT kernel envelope)
8
+ * - binary → raw bytes with BinaryResult contentType + status
9
+ *
10
+ * Errors use the kernel envelope's `{ error: { code, message, data? } }` shape
11
+ * for consistency with kernel HTTP. The HTTP status comes from the error code
12
+ * table (`kernelErrorHttpStatus`).
13
+ */
14
+ import { KERNEL_ERROR_CODES, dispatch, isBinaryResult, jsonCodec, kernelErrorHttpStatus, } from '@astrale-os/kernel-api';
15
+ import { buildCorsHeaders } from '../cors';
16
+ import { buildBinaryResponse, toBody } from '../render';
17
+ import { readCredential } from './credential';
18
+ import { decodeRouteRequest } from './params';
19
+ import { buildRouteStreamResponse } from './stream';
20
+ // ─── Helpers ────────────────────────────────────────────────────────────────
21
+ function errorResponse(error, corsHeaders) {
22
+ const status = kernelErrorHttpStatus(error.code);
23
+ const body = jsonCodec.encode({
24
+ error: error.data === undefined
25
+ ? { code: error.code, message: error.message }
26
+ : { code: error.code, message: error.message, data: error.data },
27
+ });
28
+ return new Response(toBody(body), {
29
+ status,
30
+ headers: { ...corsHeaders, 'content-type': 'application/json' },
31
+ });
32
+ }
33
+ /**
34
+ * Build a Hono-compatible handler for a single route binding.
35
+ */
36
+ export function createRouteHandler(config) {
37
+ const corsHeaders = buildCorsHeaders(config.cors);
38
+ const hostParamsFn = config.hostParams;
39
+ return async (req, pathParams) => {
40
+ if (req.method === 'OPTIONS') {
41
+ return new Response(null, { status: 204, headers: corsHeaders });
42
+ }
43
+ // 0. Host params (lowest priority).
44
+ let hostParams = {};
45
+ if (hostParamsFn) {
46
+ const extracted = hostParamsFn(req);
47
+ if (extracted === null) {
48
+ return new Response('Host not recognised', { status: 404, headers: corsHeaders });
49
+ }
50
+ hostParams = extracted;
51
+ }
52
+ // 1. Decode params + self
53
+ let decoded;
54
+ try {
55
+ decoded = await decodeRouteRequest({
56
+ route: config.route,
57
+ pathParams,
58
+ hostParams,
59
+ request: req,
60
+ });
61
+ }
62
+ catch (err) {
63
+ return errorResponse({
64
+ code: KERNEL_ERROR_CODES.PARSE_ERROR,
65
+ message: err instanceof Error ? err.message : 'Parse error',
66
+ }, corsHeaders);
67
+ }
68
+ const params = decoded.params;
69
+ // 1b. Inject actual HTTP method for wildcard routes.
70
+ if (config.route.method === '*') {
71
+ params._method = req.method;
72
+ }
73
+ // 2. Resolve credential.
74
+ // Configurable via route.credential. Defaults to Authorization header.
75
+ const credSource = config.route.credential ?? { in: 'header', name: 'authorization' };
76
+ const credential = readCredential(req, credSource);
77
+ // 3. Stream detection (Accept header opt-in)
78
+ const isStream = req.headers.get('accept')?.includes('text/event-stream') === true;
79
+ // 4. Dispatch
80
+ const requestId = crypto.randomUUID();
81
+ const result = await dispatch(config.method, params, credential, config.kernel, { id: requestId, isStream }, decoded.self);
82
+ // 5. Render
83
+ switch (result.kind) {
84
+ case 'ack':
85
+ return new Response(null, { status: 204, headers: corsHeaders });
86
+ case 'success': {
87
+ if (isBinaryResult(result.data)) {
88
+ return buildBinaryResponse(result.data, corsHeaders);
89
+ }
90
+ const body = jsonCodec.encode(result.data);
91
+ return new Response(toBody(body), {
92
+ status: 200,
93
+ headers: { ...corsHeaders, 'content-type': 'application/json' },
94
+ });
95
+ }
96
+ case 'error':
97
+ return errorResponse(result.error, corsHeaders);
98
+ case 'redirect': {
99
+ const body = jsonCodec.encode({ redirect: result.redirection });
100
+ return new Response(toBody(body), {
101
+ status: 307,
102
+ headers: {
103
+ ...corsHeaders,
104
+ 'content-type': 'application/json',
105
+ location: result.redirection.url,
106
+ },
107
+ });
108
+ }
109
+ case 'stream': {
110
+ const streamResult = await buildRouteStreamResponse(result.generator, corsHeaders);
111
+ if (streamResult.kind === 'error') {
112
+ return errorResponse(streamResult.error, corsHeaders);
113
+ }
114
+ return streamResult.response;
115
+ }
116
+ }
117
+ };
118
+ }
119
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../routed/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { createRouteHandler, type RouteHandlerConfig } from './handler';
2
+ export { decodeRouteRequest, type DecodedRouteParams, type DecodeRouteInput } from './params';
3
+ export { readCredential } from './credential';
4
+ export { buildRouteStreamResponse, type StreamResponseResult } from './stream';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../routed/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,wBAAwB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { createRouteHandler } from './handler';
2
+ export { decodeRouteRequest } from './params';
3
+ export { readCredential } from './credential';
4
+ export { buildRouteStreamResponse } from './stream';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../routed/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,WAAW,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAkD,MAAM,UAAU,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,wBAAwB,EAA6B,MAAM,UAAU,CAAA"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Route binding parameter decoder.
3
+ *
4
+ * Extracts params from all sources (host, path, query, header, body) per
5
+ * spec §3. Merge order: host < path < query < header < body — later wins.
6
+ * `route.self`, if set, is lifted to a separate top-level `self` channel
7
+ * AND removed from `params` — handlers read it via the `self` sibling in
8
+ * their execute context (`self.path.raw`), never from `params`. Leaving
9
+ * a copy in `params` would trip strict Zod validation of `inputSchema`
10
+ * (`route-self.ts` explicitly allows the placeholder to be absent from
11
+ * the schema, so the runtime must not smuggle it through anyway).
12
+ *
13
+ * Body modes:
14
+ * - `'*'` parse JSON body, merge top-level fields into params.
15
+ * - `'raw'` skip parsing; raw bytes at `params._body`.
16
+ * - `Record` parse JSON, pick mapped fields with wire-name remapping.
17
+ */
18
+ import type { RouteBinding } from '@astrale-os/kernel-api';
19
+ export type DecodedRouteParams = Record<string, unknown>;
20
+ export type DecodedRoute = {
21
+ params: DecodedRouteParams;
22
+ /** Lifted from the placeholder declared by `route.self`. Sibling of params. */
23
+ self?: string;
24
+ };
25
+ export type DecodeRouteInput = {
26
+ route: RouteBinding;
27
+ /** Pre-extracted path params (from path matcher). */
28
+ pathParams: Record<string, string>;
29
+ /** Pre-extracted host params (from server-side host matcher). May be empty. */
30
+ hostParams?: Record<string, string>;
31
+ /** The raw request. */
32
+ request: Request;
33
+ };
34
+ /**
35
+ * Decode params from a route + request.
36
+ *
37
+ * Throws on body parse errors — the caller should map to PARSE_ERROR.
38
+ */
39
+ export declare function decodeRouteRequest(input: DecodeRouteInput): Promise<DecodedRoute>;
40
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../routed/params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAY,YAAY,EAAE,MAAM,wBAAwB,CAAA;AASpE,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAExD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,YAAY,CAAA;IACnB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,uBAAuB;IACvB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAqGvF"}