@nextera.one/axis-server-sdk 0.1.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.
@@ -0,0 +1,59 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+
3
+ declare const HANDLER_METADATA_KEY = "axis:handler";
4
+ declare function Handler(intent?: string): ClassDecorator;
5
+
6
+ declare const INTENT_ROUTES_KEY = "axis:intent_routes";
7
+ interface IntentRoute {
8
+ action: string;
9
+ methodName: string | symbol;
10
+ absolute?: boolean;
11
+ frame?: boolean;
12
+ }
13
+ interface IntentOptions {
14
+ absolute?: boolean;
15
+ frame?: boolean;
16
+ }
17
+ declare function Intent(action: string, options?: IntentOptions): MethodDecorator;
18
+
19
+ interface AxisFrame {
20
+ flags: number;
21
+ headers: Map<number, Uint8Array>;
22
+ body: Uint8Array;
23
+ sig: Uint8Array;
24
+ metadata?: Record<string, any>;
25
+ }
26
+
27
+ interface AxisEffect {
28
+ ok: boolean;
29
+ effect: string;
30
+ body?: Uint8Array;
31
+ headers?: Map<number, Uint8Array>;
32
+ metadata?: any;
33
+ }
34
+ declare class IntentRouter {
35
+ private handlers;
36
+ register(intent: string, handler: any): void;
37
+ registerHandler(instance: any): void;
38
+ route(frame: AxisFrame): Promise<AxisEffect>;
39
+ private recordLatency;
40
+ }
41
+
42
+ interface AxisHandler {
43
+ readonly name: string;
44
+ readonly open?: boolean;
45
+ readonly description?: string;
46
+ readonly execute?: (body: Uint8Array, headers?: Map<number, Uint8Array>) => Promise<Uint8Array | any>;
47
+ }
48
+ interface AxisHandlerInit extends AxisHandler, OnModuleInit {
49
+ }
50
+
51
+ interface AxisCrudHandler extends AxisHandlerInit {
52
+ create(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
53
+ findAll(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
54
+ findOne(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
55
+ update(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
56
+ remove(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
57
+ }
58
+
59
+ export { type AxisCrudHandler, type AxisEffect, type AxisFrame, type AxisHandler, type AxisHandlerInit, HANDLER_METADATA_KEY, Handler, INTENT_ROUTES_KEY, Intent, type IntentOptions, type IntentRoute, IntentRouter };
@@ -0,0 +1,59 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+
3
+ declare const HANDLER_METADATA_KEY = "axis:handler";
4
+ declare function Handler(intent?: string): ClassDecorator;
5
+
6
+ declare const INTENT_ROUTES_KEY = "axis:intent_routes";
7
+ interface IntentRoute {
8
+ action: string;
9
+ methodName: string | symbol;
10
+ absolute?: boolean;
11
+ frame?: boolean;
12
+ }
13
+ interface IntentOptions {
14
+ absolute?: boolean;
15
+ frame?: boolean;
16
+ }
17
+ declare function Intent(action: string, options?: IntentOptions): MethodDecorator;
18
+
19
+ interface AxisFrame {
20
+ flags: number;
21
+ headers: Map<number, Uint8Array>;
22
+ body: Uint8Array;
23
+ sig: Uint8Array;
24
+ metadata?: Record<string, any>;
25
+ }
26
+
27
+ interface AxisEffect {
28
+ ok: boolean;
29
+ effect: string;
30
+ body?: Uint8Array;
31
+ headers?: Map<number, Uint8Array>;
32
+ metadata?: any;
33
+ }
34
+ declare class IntentRouter {
35
+ private handlers;
36
+ register(intent: string, handler: any): void;
37
+ registerHandler(instance: any): void;
38
+ route(frame: AxisFrame): Promise<AxisEffect>;
39
+ private recordLatency;
40
+ }
41
+
42
+ interface AxisHandler {
43
+ readonly name: string;
44
+ readonly open?: boolean;
45
+ readonly description?: string;
46
+ readonly execute?: (body: Uint8Array, headers?: Map<number, Uint8Array>) => Promise<Uint8Array | any>;
47
+ }
48
+ interface AxisHandlerInit extends AxisHandler, OnModuleInit {
49
+ }
50
+
51
+ interface AxisCrudHandler extends AxisHandlerInit {
52
+ create(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
53
+ findAll(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
54
+ findOne(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
55
+ update(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
56
+ remove(body: Uint8Array, headers?: Map<number, Uint8Array>): Promise<Uint8Array>;
57
+ }
58
+
59
+ export { type AxisCrudHandler, type AxisEffect, type AxisFrame, type AxisHandler, type AxisHandlerInit, HANDLER_METADATA_KEY, Handler, INTENT_ROUTES_KEY, Intent, type IntentOptions, type IntentRoute, IntentRouter };
package/dist/index.js ADDED
@@ -0,0 +1,233 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var __decorateClass = (decorators, target, key, kind) => {
19
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
20
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
21
+ if (decorator = decorators[i])
22
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
23
+ if (kind && result) __defProp(target, key, result);
24
+ return result;
25
+ };
26
+
27
+ // src/index.ts
28
+ var index_exports = {};
29
+ __export(index_exports, {
30
+ HANDLER_METADATA_KEY: () => HANDLER_METADATA_KEY,
31
+ Handler: () => Handler,
32
+ INTENT_ROUTES_KEY: () => INTENT_ROUTES_KEY,
33
+ Intent: () => Intent,
34
+ IntentRouter: () => IntentRouter
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/decorators/handler.decorator.ts
39
+ var import_common = require("@nestjs/common");
40
+ var HANDLER_METADATA_KEY = "axis:handler";
41
+ function Handler(intent) {
42
+ return (target) => {
43
+ (0, import_common.SetMetadata)(HANDLER_METADATA_KEY, { intent })(target);
44
+ (0, import_common.Injectable)()(target);
45
+ };
46
+ }
47
+
48
+ // src/decorators/intent.decorator.ts
49
+ var import_reflect_metadata = require("reflect-metadata");
50
+ var INTENT_ROUTES_KEY = "axis:intent_routes";
51
+ function Intent(action, options) {
52
+ return (target, propertyKey) => {
53
+ const routes = Reflect.getMetadata(INTENT_ROUTES_KEY, target.constructor) || [];
54
+ routes.push({
55
+ action,
56
+ methodName: propertyKey,
57
+ absolute: options?.absolute,
58
+ frame: options?.frame
59
+ });
60
+ Reflect.defineMetadata(INTENT_ROUTES_KEY, routes, target.constructor);
61
+ };
62
+ }
63
+
64
+ // src/engine/intent.router.ts
65
+ var import_common2 = require("@nestjs/common");
66
+ var IntentRouter = class {
67
+ constructor() {
68
+ /** Internal registry of dynamic intent handlers */
69
+ this.handlers = /* @__PURE__ */ new Map();
70
+ }
71
+ /**
72
+ * Registers a handler for a specific intent.
73
+ * Handlers can be functions: `(body, headers) => Promise<Uint8Array | AxisEffect>`
74
+ * Or objects with a method: `handle(frame: AxisFrame) => Promise<AxisEffect>`
75
+ *
76
+ * @param {string} intent - The unique intent identifier (e.g., 'axis.vault.create')
77
+ * @param {any} handler - The handler function or object
78
+ */
79
+ register(intent, handler) {
80
+ this.handlers.set(intent, handler);
81
+ }
82
+ /**
83
+ * Automatically registers all `@Intent`-decorated methods from a handler instance.
84
+ *
85
+ * Reads the handler prefix from `@Handler` metadata (or falls back to `instance.name`),
86
+ * then registers each `@Intent`-decorated method accordingly.
87
+ *
88
+ * @param {any} instance - The handler instance with `@Intent`-decorated methods
89
+ */
90
+ registerHandler(instance) {
91
+ const handlerMeta = Reflect.getMetadata(
92
+ HANDLER_METADATA_KEY,
93
+ instance.constructor
94
+ );
95
+ const prefix = handlerMeta?.intent || instance.name;
96
+ const routes = Reflect.getMetadata(INTENT_ROUTES_KEY, instance.constructor) || [];
97
+ for (const route of routes) {
98
+ const intentName = route.absolute ? route.action : `${prefix}.${route.action}`;
99
+ const fn = instance[route.methodName].bind(instance);
100
+ if (route.frame) {
101
+ this.register(intentName, { handle: fn });
102
+ } else {
103
+ this.register(intentName, fn);
104
+ }
105
+ }
106
+ }
107
+ /**
108
+ * Routes a decoded AXIS frame to the appropriate handler.
109
+ *
110
+ * **Precedence:**
111
+ * 1. System Built-ins (`system.ping`, `public.ping`, `system.time`, `system.echo`)
112
+ * 2. Meta-intent execution (`INTENT.EXEC` / `axis.intent.exec`)
113
+ * 3. Dynamically registered handlers from modules.
114
+ *
115
+ * @param {AxisFrame} frame - The validated and decoded binary frame
116
+ * @returns {Promise<AxisEffect>} The resulting effect of the execution
117
+ * @throws {Error} If the intent header is missing or no handler is registered
118
+ */
119
+ async route(frame) {
120
+ const start = process.hrtime();
121
+ let intent = "unknown";
122
+ try {
123
+ const intentBytes = frame.headers.get(3);
124
+ if (!intentBytes) throw new Error("Missing intent");
125
+ intent = new TextDecoder().decode(intentBytes);
126
+ let effect;
127
+ if (intent === "system.ping" || intent === "public.ping") {
128
+ effect = {
129
+ ok: true,
130
+ effect: "pong",
131
+ headers: /* @__PURE__ */ new Map([
132
+ [100, new TextEncoder().encode("AXIS_BACKEND_V1")]
133
+ ]),
134
+ body: new TextEncoder().encode(
135
+ JSON.stringify({
136
+ status: "ok",
137
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
138
+ version: "1.0.0"
139
+ })
140
+ )
141
+ };
142
+ } else if (intent === "system.time") {
143
+ const ts = Date.now().toString();
144
+ effect = {
145
+ ok: true,
146
+ effect: "time",
147
+ body: new TextEncoder().encode(
148
+ JSON.stringify({
149
+ ts,
150
+ iso: (/* @__PURE__ */ new Date()).toISOString()
151
+ })
152
+ )
153
+ };
154
+ } else if (intent === "system.echo") {
155
+ effect = {
156
+ ok: true,
157
+ effect: "echo",
158
+ body: frame.body
159
+ };
160
+ } else if (intent === "INTENT.EXEC" || intent === "axis.intent.exec") {
161
+ try {
162
+ const bodyJSON = JSON.parse(new TextDecoder().decode(frame.body));
163
+ const innerIntent = bodyJSON.intent;
164
+ const innerArgs = bodyJSON.args || {};
165
+ if (!innerIntent) {
166
+ throw new Error("INTENT.EXEC missing inner intent");
167
+ }
168
+ const innerFrame = {
169
+ ...frame,
170
+ headers: new Map(frame.headers),
171
+ body: new TextEncoder().encode(JSON.stringify(innerArgs))
172
+ };
173
+ innerFrame.headers.set(3, new TextEncoder().encode(innerIntent));
174
+ return await this.route(innerFrame);
175
+ } catch (e) {
176
+ throw new Error(`INTENT.EXEC unwrapping failed: ${e.message}`);
177
+ }
178
+ } else {
179
+ const handler = this.handlers.get(intent);
180
+ if (!handler) {
181
+ throw new Error(`Intent not found: ${intent}`);
182
+ }
183
+ if (typeof handler === "function") {
184
+ const resultBody = await handler(frame.body, frame.headers);
185
+ effect = {
186
+ ok: true,
187
+ effect: "complete",
188
+ body: resultBody
189
+ };
190
+ } else {
191
+ if (typeof handler.handle === "function") {
192
+ effect = await handler.handle(frame);
193
+ } else if (typeof handler.execute === "function") {
194
+ const bodyRes = await handler.execute(
195
+ frame.body,
196
+ frame.headers
197
+ );
198
+ effect = {
199
+ ok: true,
200
+ effect: "complete",
201
+ body: bodyRes
202
+ };
203
+ } else {
204
+ throw new Error(
205
+ `Handler for ${intent} does not implement handle or execute`
206
+ );
207
+ }
208
+ }
209
+ }
210
+ this.recordLatency(intent, start);
211
+ return effect;
212
+ } catch (e) {
213
+ console.error(`Error routing intent ${intent}:`, e.message);
214
+ throw e;
215
+ }
216
+ }
217
+ recordLatency(intent, start) {
218
+ const diff = process.hrtime(start);
219
+ void diff;
220
+ }
221
+ };
222
+ IntentRouter = __decorateClass([
223
+ (0, import_common2.Injectable)()
224
+ ], IntentRouter);
225
+ // Annotate the CommonJS export names for ESM import in node:
226
+ 0 && (module.exports = {
227
+ HANDLER_METADATA_KEY,
228
+ Handler,
229
+ INTENT_ROUTES_KEY,
230
+ Intent,
231
+ IntentRouter
232
+ });
233
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/decorators/handler.decorator.ts","../src/decorators/intent.decorator.ts","../src/engine/intent.router.ts"],"sourcesContent":["// Decorators\nexport { Handler, HANDLER_METADATA_KEY } from './decorators/handler.decorator';\nexport {\n Intent,\n INTENT_ROUTES_KEY,\n IntentRoute,\n IntentOptions,\n} from './decorators/intent.decorator';\n\n// Engine\nexport { IntentRouter, AxisEffect } from './engine/intent.router';\n\n// Interfaces\nexport { AxisHandler, AxisHandlerInit } from './interfaces/axis-handler.interface';\nexport { AxisCrudHandler } from './interfaces/axis-crud-handler.interface';\n\n// Types\nexport { AxisFrame } from './types/axis-frame';\n","import { Injectable, SetMetadata } from '@nestjs/common';\n\nexport const HANDLER_METADATA_KEY = 'axis:handler';\n\n/**\n * Decorator to mark a class as an Axis Handler.\n * Handlers are responsible for processing intents or specific logic\n * for Axis modules.\n */\nexport function Handler(intent?: string): ClassDecorator {\n return (target: Function) => {\n SetMetadata(HANDLER_METADATA_KEY, { intent })(target);\n Injectable()(target as any);\n };\n}\n","import 'reflect-metadata';\n\nexport const INTENT_ROUTES_KEY = 'axis:intent_routes';\n\nexport interface IntentRoute {\n action: string;\n methodName: string | symbol;\n absolute?: boolean;\n frame?: boolean;\n}\n\nexport interface IntentOptions {\n /** If true, the action is the full intent name (not prefixed with handler name) */\n absolute?: boolean;\n /** If true, register as { handle: fn } for frame-based handlers */\n frame?: boolean;\n}\n\n/**\n * Marks a method as an intent handler.\n *\n * The full intent name is resolved as `{handler_prefix}.{action}` by default.\n * Use `{ absolute: true }` to use the action string as the full intent name.\n * Use `{ frame: true }` for handlers that receive an AxisFrame and return AxisEffect.\n *\n * @example\n * ```ts\n * @Handler('axis.actor_keys')\n * class MyHandler {\n * @Intent('create')\n * async create(body: Uint8Array) { ... }\n *\n * @Intent('public.auth.capsule.issue', { absolute: true })\n * async publicIssue(body: Uint8Array) { ... }\n *\n * @Intent('presence.resume', { frame: true })\n * async handlePresence(frame: AxisFrame) { ... }\n * }\n * ```\n */\nexport function Intent(action: string, options?: IntentOptions): MethodDecorator {\n return (target, propertyKey) => {\n const routes: IntentRoute[] =\n Reflect.getMetadata(INTENT_ROUTES_KEY, target.constructor) || [];\n routes.push({\n action,\n methodName: propertyKey,\n absolute: options?.absolute,\n frame: options?.frame,\n });\n Reflect.defineMetadata(INTENT_ROUTES_KEY, routes, target.constructor);\n };\n}\n","import { Injectable } from '@nestjs/common';\nimport { AxisFrame } from '../types/axis-frame';\nimport { HANDLER_METADATA_KEY } from '../decorators/handler.decorator';\nimport { INTENT_ROUTES_KEY, IntentRoute } from '../decorators/intent.decorator';\n\n/**\n * Represents the outcome of an AXIS intent execution.\n *\n * @interface AxisEffect\n */\nexport interface AxisEffect {\n /** Whether the intent was processed successfully at the application level */\n ok: boolean;\n /** A descriptive string classifier for the result (e.g., 'FILE_CREATED', 'PONG') */\n effect: string;\n /** Optional binary payload (body) to be returned to the requester */\n body?: Uint8Array;\n /** Optional custom TLV headers to be included in the response frame */\n headers?: Map<number, Uint8Array>;\n /** Optional metadata for internal logging or audit (not sent to client) */\n metadata?: any;\n}\n\n/**\n * IntentRouter\n *\n * The central dispatching mechanism of the AXIS backend.\n * Maps binary intents (identified by their name in the header) to specialized handlers.\n *\n * **Features:**\n * 1. **Built-in Fast Path:** Handles high-frequency system intents (ping, time, echo) directly.\n * 2. **Dynamic Handler Registration:** Allows modules to register handlers at runtime.\n * 3. **Decorator-driven Registration:** Uses {@link registerHandler} to auto-register `@Intent`-decorated methods.\n * 4. **Polymorphic Handlers:** Supports both raw function handlers and object-based `{ handle }` handlers.\n *\n * @class IntentRouter\n */\n@Injectable()\nexport class IntentRouter {\n /** Internal registry of dynamic intent handlers */\n private handlers = new Map<string, any>();\n\n /**\n * Registers a handler for a specific intent.\n * Handlers can be functions: `(body, headers) => Promise<Uint8Array | AxisEffect>`\n * Or objects with a method: `handle(frame: AxisFrame) => Promise<AxisEffect>`\n *\n * @param {string} intent - The unique intent identifier (e.g., 'axis.vault.create')\n * @param {any} handler - The handler function or object\n */\n register(intent: string, handler: any) {\n this.handlers.set(intent, handler);\n }\n\n /**\n * Automatically registers all `@Intent`-decorated methods from a handler instance.\n *\n * Reads the handler prefix from `@Handler` metadata (or falls back to `instance.name`),\n * then registers each `@Intent`-decorated method accordingly.\n *\n * @param {any} instance - The handler instance with `@Intent`-decorated methods\n */\n registerHandler(instance: any) {\n const handlerMeta = Reflect.getMetadata(\n HANDLER_METADATA_KEY,\n instance.constructor,\n );\n const prefix: string | undefined = handlerMeta?.intent || instance.name;\n\n const routes: IntentRoute[] =\n Reflect.getMetadata(INTENT_ROUTES_KEY, instance.constructor) || [];\n\n for (const route of routes) {\n const intentName = route.absolute\n ? route.action\n : `${prefix}.${route.action}`;\n const fn = instance[route.methodName].bind(instance);\n\n if (route.frame) {\n this.register(intentName, { handle: fn });\n } else {\n this.register(intentName, fn);\n }\n }\n }\n\n /**\n * Routes a decoded AXIS frame to the appropriate handler.\n *\n * **Precedence:**\n * 1. System Built-ins (`system.ping`, `public.ping`, `system.time`, `system.echo`)\n * 2. Meta-intent execution (`INTENT.EXEC` / `axis.intent.exec`)\n * 3. Dynamically registered handlers from modules.\n *\n * @param {AxisFrame} frame - The validated and decoded binary frame\n * @returns {Promise<AxisEffect>} The resulting effect of the execution\n * @throws {Error} If the intent header is missing or no handler is registered\n */\n async route(frame: AxisFrame): Promise<AxisEffect> {\n const start = process.hrtime();\n let intent = 'unknown';\n\n try {\n // Extract intent from header TLV (tag 3 = TLV_INTENT)\n const intentBytes = frame.headers.get(3);\n if (!intentBytes) throw new Error('Missing intent');\n intent = new TextDecoder().decode(intentBytes);\n\n let effect: AxisEffect;\n\n if (intent === 'system.ping' || intent === 'public.ping') {\n effect = {\n ok: true,\n effect: 'pong',\n headers: new Map([\n [100, new TextEncoder().encode('AXIS_BACKEND_V1')],\n ]),\n body: new TextEncoder().encode(\n JSON.stringify({\n status: 'ok',\n timestamp: new Date().toISOString(),\n version: '1.0.0',\n }),\n ),\n };\n } else if (intent === 'system.time') {\n const ts = Date.now().toString();\n effect = {\n ok: true,\n effect: 'time',\n body: new TextEncoder().encode(\n JSON.stringify({\n ts,\n iso: new Date().toISOString(),\n }),\n ),\n };\n } else if (intent === 'system.echo') {\n effect = {\n ok: true,\n effect: 'echo',\n body: frame.body,\n };\n } else if (intent === 'INTENT.EXEC' || intent === 'axis.intent.exec') {\n // Meta-intent: Unwrap and execute the inner intent\n try {\n const bodyJSON = JSON.parse(new TextDecoder().decode(frame.body));\n const innerIntent = bodyJSON.intent;\n const innerArgs = bodyJSON.args || {};\n\n if (!innerIntent) {\n throw new Error('INTENT.EXEC missing inner intent');\n }\n\n const innerFrame: AxisFrame = {\n ...frame,\n headers: new Map(frame.headers),\n body: new TextEncoder().encode(JSON.stringify(innerArgs)),\n };\n innerFrame.headers.set(3, new TextEncoder().encode(innerIntent));\n\n return await this.route(innerFrame);\n } catch (e: any) {\n throw new Error(`INTENT.EXEC unwrapping failed: ${e.message}`);\n }\n } else {\n const handler = this.handlers.get(intent);\n if (!handler) {\n throw new Error(`Intent not found: ${intent}`);\n }\n\n if (typeof handler === 'function') {\n const resultBody = await handler(frame.body, frame.headers);\n effect = {\n ok: true,\n effect: 'complete',\n body: resultBody,\n };\n } else {\n if (typeof (handler as any).handle === 'function') {\n effect = await (handler as any).handle(frame);\n } else if (typeof (handler as any).execute === 'function') {\n const bodyRes = await (handler as any).execute(\n frame.body,\n frame.headers,\n );\n effect = {\n ok: true,\n effect: 'complete',\n body: bodyRes,\n };\n } else {\n throw new Error(\n `Handler for ${intent} does not implement handle or execute`,\n );\n }\n }\n }\n\n this.recordLatency(intent, start);\n return effect;\n } catch (e: any) {\n console.error(`Error routing intent ${intent}:`, e.message);\n throw e;\n }\n }\n\n private recordLatency(intent: string, start: [number, number]) {\n const diff = process.hrtime(start);\n // Available for subclass telemetry hooks or future logging\n void diff;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAwC;AAEjC,IAAM,uBAAuB;AAO7B,SAAS,QAAQ,QAAiC;AACvD,SAAO,CAAC,WAAqB;AAC3B,mCAAY,sBAAsB,EAAE,OAAO,CAAC,EAAE,MAAM;AACpD,kCAAW,EAAE,MAAa;AAAA,EAC5B;AACF;;;ACdA,8BAAO;AAEA,IAAM,oBAAoB;AAsC1B,SAAS,OAAO,QAAgB,SAA0C;AAC/E,SAAO,CAAC,QAAQ,gBAAgB;AAC9B,UAAM,SACJ,QAAQ,YAAY,mBAAmB,OAAO,WAAW,KAAK,CAAC;AACjE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,YAAY;AAAA,MACZ,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,IAClB,CAAC;AACD,YAAQ,eAAe,mBAAmB,QAAQ,OAAO,WAAW;AAAA,EACtE;AACF;;;ACpDA,IAAAA,iBAA2B;AAsCpB,IAAM,eAAN,MAAmB;AAAA,EAAnB;AAEL;AAAA,SAAQ,WAAW,oBAAI,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxC,SAAS,QAAgB,SAAc;AACrC,SAAK,SAAS,IAAI,QAAQ,OAAO;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,gBAAgB,UAAe;AAC7B,UAAM,cAAc,QAAQ;AAAA,MAC1B;AAAA,MACA,SAAS;AAAA,IACX;AACA,UAAM,SAA6B,aAAa,UAAU,SAAS;AAEnE,UAAM,SACJ,QAAQ,YAAY,mBAAmB,SAAS,WAAW,KAAK,CAAC;AAEnE,eAAW,SAAS,QAAQ;AAC1B,YAAM,aAAa,MAAM,WACrB,MAAM,SACN,GAAG,MAAM,IAAI,MAAM,MAAM;AAC7B,YAAM,KAAK,SAAS,MAAM,UAAU,EAAE,KAAK,QAAQ;AAEnD,UAAI,MAAM,OAAO;AACf,aAAK,SAAS,YAAY,EAAE,QAAQ,GAAG,CAAC;AAAA,MAC1C,OAAO;AACL,aAAK,SAAS,YAAY,EAAE;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MAAM,OAAuC;AACjD,UAAM,QAAQ,QAAQ,OAAO;AAC7B,QAAI,SAAS;AAEb,QAAI;AAEF,YAAM,cAAc,MAAM,QAAQ,IAAI,CAAC;AACvC,UAAI,CAAC,YAAa,OAAM,IAAI,MAAM,gBAAgB;AAClD,eAAS,IAAI,YAAY,EAAE,OAAO,WAAW;AAE7C,UAAI;AAEJ,UAAI,WAAW,iBAAiB,WAAW,eAAe;AACxD,iBAAS;AAAA,UACP,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,SAAS,oBAAI,IAAI;AAAA,YACf,CAAC,KAAK,IAAI,YAAY,EAAE,OAAO,iBAAiB,CAAC;AAAA,UACnD,CAAC;AAAA,UACD,MAAM,IAAI,YAAY,EAAE;AAAA,YACtB,KAAK,UAAU;AAAA,cACb,QAAQ;AAAA,cACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,cAClC,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,WAAW,WAAW,eAAe;AACnC,cAAM,KAAK,KAAK,IAAI,EAAE,SAAS;AAC/B,iBAAS;AAAA,UACP,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM,IAAI,YAAY,EAAE;AAAA,YACtB,KAAK,UAAU;AAAA,cACb;AAAA,cACA,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,YAC9B,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,WAAW,WAAW,eAAe;AACnC,iBAAS;AAAA,UACP,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM,MAAM;AAAA,QACd;AAAA,MACF,WAAW,WAAW,iBAAiB,WAAW,oBAAoB;AAEpE,YAAI;AACF,gBAAM,WAAW,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,MAAM,IAAI,CAAC;AAChE,gBAAM,cAAc,SAAS;AAC7B,gBAAM,YAAY,SAAS,QAAQ,CAAC;AAEpC,cAAI,CAAC,aAAa;AAChB,kBAAM,IAAI,MAAM,kCAAkC;AAAA,UACpD;AAEA,gBAAM,aAAwB;AAAA,YAC5B,GAAG;AAAA,YACH,SAAS,IAAI,IAAI,MAAM,OAAO;AAAA,YAC9B,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,SAAS,CAAC;AAAA,UAC1D;AACA,qBAAW,QAAQ,IAAI,GAAG,IAAI,YAAY,EAAE,OAAO,WAAW,CAAC;AAE/D,iBAAO,MAAM,KAAK,MAAM,UAAU;AAAA,QACpC,SAAS,GAAQ;AACf,gBAAM,IAAI,MAAM,kCAAkC,EAAE,OAAO,EAAE;AAAA,QAC/D;AAAA,MACF,OAAO;AACL,cAAM,UAAU,KAAK,SAAS,IAAI,MAAM;AACxC,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,qBAAqB,MAAM,EAAE;AAAA,QAC/C;AAEA,YAAI,OAAO,YAAY,YAAY;AACjC,gBAAM,aAAa,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO;AAC1D,mBAAS;AAAA,YACP,IAAI;AAAA,YACJ,QAAQ;AAAA,YACR,MAAM;AAAA,UACR;AAAA,QACF,OAAO;AACL,cAAI,OAAQ,QAAgB,WAAW,YAAY;AACjD,qBAAS,MAAO,QAAgB,OAAO,KAAK;AAAA,UAC9C,WAAW,OAAQ,QAAgB,YAAY,YAAY;AACzD,kBAAM,UAAU,MAAO,QAAgB;AAAA,cACrC,MAAM;AAAA,cACN,MAAM;AAAA,YACR;AACA,qBAAS;AAAA,cACP,IAAI;AAAA,cACJ,QAAQ;AAAA,cACR,MAAM;AAAA,YACR;AAAA,UACF,OAAO;AACL,kBAAM,IAAI;AAAA,cACR,eAAe,MAAM;AAAA,YACvB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK,cAAc,QAAQ,KAAK;AAChC,aAAO;AAAA,IACT,SAAS,GAAQ;AACf,cAAQ,MAAM,wBAAwB,MAAM,KAAK,EAAE,OAAO;AAC1D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,cAAc,QAAgB,OAAyB;AAC7D,UAAM,OAAO,QAAQ,OAAO,KAAK;AAEjC,SAAK;AAAA,EACP;AACF;AA9Ka,eAAN;AAAA,MADN,2BAAW;AAAA,GACC;","names":["import_common"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,206 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+
12
+ // src/decorators/handler.decorator.ts
13
+ import { Injectable, SetMetadata } from "@nestjs/common";
14
+ var HANDLER_METADATA_KEY = "axis:handler";
15
+ function Handler(intent) {
16
+ return (target) => {
17
+ SetMetadata(HANDLER_METADATA_KEY, { intent })(target);
18
+ Injectable()(target);
19
+ };
20
+ }
21
+
22
+ // src/decorators/intent.decorator.ts
23
+ import "reflect-metadata";
24
+ var INTENT_ROUTES_KEY = "axis:intent_routes";
25
+ function Intent(action, options) {
26
+ return (target, propertyKey) => {
27
+ const routes = Reflect.getMetadata(INTENT_ROUTES_KEY, target.constructor) || [];
28
+ routes.push({
29
+ action,
30
+ methodName: propertyKey,
31
+ absolute: options?.absolute,
32
+ frame: options?.frame
33
+ });
34
+ Reflect.defineMetadata(INTENT_ROUTES_KEY, routes, target.constructor);
35
+ };
36
+ }
37
+
38
+ // src/engine/intent.router.ts
39
+ import { Injectable as Injectable2 } from "@nestjs/common";
40
+ var IntentRouter = class {
41
+ constructor() {
42
+ /** Internal registry of dynamic intent handlers */
43
+ this.handlers = /* @__PURE__ */ new Map();
44
+ }
45
+ /**
46
+ * Registers a handler for a specific intent.
47
+ * Handlers can be functions: `(body, headers) => Promise<Uint8Array | AxisEffect>`
48
+ * Or objects with a method: `handle(frame: AxisFrame) => Promise<AxisEffect>`
49
+ *
50
+ * @param {string} intent - The unique intent identifier (e.g., 'axis.vault.create')
51
+ * @param {any} handler - The handler function or object
52
+ */
53
+ register(intent, handler) {
54
+ this.handlers.set(intent, handler);
55
+ }
56
+ /**
57
+ * Automatically registers all `@Intent`-decorated methods from a handler instance.
58
+ *
59
+ * Reads the handler prefix from `@Handler` metadata (or falls back to `instance.name`),
60
+ * then registers each `@Intent`-decorated method accordingly.
61
+ *
62
+ * @param {any} instance - The handler instance with `@Intent`-decorated methods
63
+ */
64
+ registerHandler(instance) {
65
+ const handlerMeta = Reflect.getMetadata(
66
+ HANDLER_METADATA_KEY,
67
+ instance.constructor
68
+ );
69
+ const prefix = handlerMeta?.intent || instance.name;
70
+ const routes = Reflect.getMetadata(INTENT_ROUTES_KEY, instance.constructor) || [];
71
+ for (const route of routes) {
72
+ const intentName = route.absolute ? route.action : `${prefix}.${route.action}`;
73
+ const fn = instance[route.methodName].bind(instance);
74
+ if (route.frame) {
75
+ this.register(intentName, { handle: fn });
76
+ } else {
77
+ this.register(intentName, fn);
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * Routes a decoded AXIS frame to the appropriate handler.
83
+ *
84
+ * **Precedence:**
85
+ * 1. System Built-ins (`system.ping`, `public.ping`, `system.time`, `system.echo`)
86
+ * 2. Meta-intent execution (`INTENT.EXEC` / `axis.intent.exec`)
87
+ * 3. Dynamically registered handlers from modules.
88
+ *
89
+ * @param {AxisFrame} frame - The validated and decoded binary frame
90
+ * @returns {Promise<AxisEffect>} The resulting effect of the execution
91
+ * @throws {Error} If the intent header is missing or no handler is registered
92
+ */
93
+ async route(frame) {
94
+ const start = process.hrtime();
95
+ let intent = "unknown";
96
+ try {
97
+ const intentBytes = frame.headers.get(3);
98
+ if (!intentBytes) throw new Error("Missing intent");
99
+ intent = new TextDecoder().decode(intentBytes);
100
+ let effect;
101
+ if (intent === "system.ping" || intent === "public.ping") {
102
+ effect = {
103
+ ok: true,
104
+ effect: "pong",
105
+ headers: /* @__PURE__ */ new Map([
106
+ [100, new TextEncoder().encode("AXIS_BACKEND_V1")]
107
+ ]),
108
+ body: new TextEncoder().encode(
109
+ JSON.stringify({
110
+ status: "ok",
111
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
112
+ version: "1.0.0"
113
+ })
114
+ )
115
+ };
116
+ } else if (intent === "system.time") {
117
+ const ts = Date.now().toString();
118
+ effect = {
119
+ ok: true,
120
+ effect: "time",
121
+ body: new TextEncoder().encode(
122
+ JSON.stringify({
123
+ ts,
124
+ iso: (/* @__PURE__ */ new Date()).toISOString()
125
+ })
126
+ )
127
+ };
128
+ } else if (intent === "system.echo") {
129
+ effect = {
130
+ ok: true,
131
+ effect: "echo",
132
+ body: frame.body
133
+ };
134
+ } else if (intent === "INTENT.EXEC" || intent === "axis.intent.exec") {
135
+ try {
136
+ const bodyJSON = JSON.parse(new TextDecoder().decode(frame.body));
137
+ const innerIntent = bodyJSON.intent;
138
+ const innerArgs = bodyJSON.args || {};
139
+ if (!innerIntent) {
140
+ throw new Error("INTENT.EXEC missing inner intent");
141
+ }
142
+ const innerFrame = {
143
+ ...frame,
144
+ headers: new Map(frame.headers),
145
+ body: new TextEncoder().encode(JSON.stringify(innerArgs))
146
+ };
147
+ innerFrame.headers.set(3, new TextEncoder().encode(innerIntent));
148
+ return await this.route(innerFrame);
149
+ } catch (e) {
150
+ throw new Error(`INTENT.EXEC unwrapping failed: ${e.message}`);
151
+ }
152
+ } else {
153
+ const handler = this.handlers.get(intent);
154
+ if (!handler) {
155
+ throw new Error(`Intent not found: ${intent}`);
156
+ }
157
+ if (typeof handler === "function") {
158
+ const resultBody = await handler(frame.body, frame.headers);
159
+ effect = {
160
+ ok: true,
161
+ effect: "complete",
162
+ body: resultBody
163
+ };
164
+ } else {
165
+ if (typeof handler.handle === "function") {
166
+ effect = await handler.handle(frame);
167
+ } else if (typeof handler.execute === "function") {
168
+ const bodyRes = await handler.execute(
169
+ frame.body,
170
+ frame.headers
171
+ );
172
+ effect = {
173
+ ok: true,
174
+ effect: "complete",
175
+ body: bodyRes
176
+ };
177
+ } else {
178
+ throw new Error(
179
+ `Handler for ${intent} does not implement handle or execute`
180
+ );
181
+ }
182
+ }
183
+ }
184
+ this.recordLatency(intent, start);
185
+ return effect;
186
+ } catch (e) {
187
+ console.error(`Error routing intent ${intent}:`, e.message);
188
+ throw e;
189
+ }
190
+ }
191
+ recordLatency(intent, start) {
192
+ const diff = process.hrtime(start);
193
+ void diff;
194
+ }
195
+ };
196
+ IntentRouter = __decorateClass([
197
+ Injectable2()
198
+ ], IntentRouter);
199
+ export {
200
+ HANDLER_METADATA_KEY,
201
+ Handler,
202
+ INTENT_ROUTES_KEY,
203
+ Intent,
204
+ IntentRouter
205
+ };
206
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/decorators/handler.decorator.ts","../src/decorators/intent.decorator.ts","../src/engine/intent.router.ts"],"sourcesContent":["import { Injectable, SetMetadata } from '@nestjs/common';\n\nexport const HANDLER_METADATA_KEY = 'axis:handler';\n\n/**\n * Decorator to mark a class as an Axis Handler.\n * Handlers are responsible for processing intents or specific logic\n * for Axis modules.\n */\nexport function Handler(intent?: string): ClassDecorator {\n return (target: Function) => {\n SetMetadata(HANDLER_METADATA_KEY, { intent })(target);\n Injectable()(target as any);\n };\n}\n","import 'reflect-metadata';\n\nexport const INTENT_ROUTES_KEY = 'axis:intent_routes';\n\nexport interface IntentRoute {\n action: string;\n methodName: string | symbol;\n absolute?: boolean;\n frame?: boolean;\n}\n\nexport interface IntentOptions {\n /** If true, the action is the full intent name (not prefixed with handler name) */\n absolute?: boolean;\n /** If true, register as { handle: fn } for frame-based handlers */\n frame?: boolean;\n}\n\n/**\n * Marks a method as an intent handler.\n *\n * The full intent name is resolved as `{handler_prefix}.{action}` by default.\n * Use `{ absolute: true }` to use the action string as the full intent name.\n * Use `{ frame: true }` for handlers that receive an AxisFrame and return AxisEffect.\n *\n * @example\n * ```ts\n * @Handler('axis.actor_keys')\n * class MyHandler {\n * @Intent('create')\n * async create(body: Uint8Array) { ... }\n *\n * @Intent('public.auth.capsule.issue', { absolute: true })\n * async publicIssue(body: Uint8Array) { ... }\n *\n * @Intent('presence.resume', { frame: true })\n * async handlePresence(frame: AxisFrame) { ... }\n * }\n * ```\n */\nexport function Intent(action: string, options?: IntentOptions): MethodDecorator {\n return (target, propertyKey) => {\n const routes: IntentRoute[] =\n Reflect.getMetadata(INTENT_ROUTES_KEY, target.constructor) || [];\n routes.push({\n action,\n methodName: propertyKey,\n absolute: options?.absolute,\n frame: options?.frame,\n });\n Reflect.defineMetadata(INTENT_ROUTES_KEY, routes, target.constructor);\n };\n}\n","import { Injectable } from '@nestjs/common';\nimport { AxisFrame } from '../types/axis-frame';\nimport { HANDLER_METADATA_KEY } from '../decorators/handler.decorator';\nimport { INTENT_ROUTES_KEY, IntentRoute } from '../decorators/intent.decorator';\n\n/**\n * Represents the outcome of an AXIS intent execution.\n *\n * @interface AxisEffect\n */\nexport interface AxisEffect {\n /** Whether the intent was processed successfully at the application level */\n ok: boolean;\n /** A descriptive string classifier for the result (e.g., 'FILE_CREATED', 'PONG') */\n effect: string;\n /** Optional binary payload (body) to be returned to the requester */\n body?: Uint8Array;\n /** Optional custom TLV headers to be included in the response frame */\n headers?: Map<number, Uint8Array>;\n /** Optional metadata for internal logging or audit (not sent to client) */\n metadata?: any;\n}\n\n/**\n * IntentRouter\n *\n * The central dispatching mechanism of the AXIS backend.\n * Maps binary intents (identified by their name in the header) to specialized handlers.\n *\n * **Features:**\n * 1. **Built-in Fast Path:** Handles high-frequency system intents (ping, time, echo) directly.\n * 2. **Dynamic Handler Registration:** Allows modules to register handlers at runtime.\n * 3. **Decorator-driven Registration:** Uses {@link registerHandler} to auto-register `@Intent`-decorated methods.\n * 4. **Polymorphic Handlers:** Supports both raw function handlers and object-based `{ handle }` handlers.\n *\n * @class IntentRouter\n */\n@Injectable()\nexport class IntentRouter {\n /** Internal registry of dynamic intent handlers */\n private handlers = new Map<string, any>();\n\n /**\n * Registers a handler for a specific intent.\n * Handlers can be functions: `(body, headers) => Promise<Uint8Array | AxisEffect>`\n * Or objects with a method: `handle(frame: AxisFrame) => Promise<AxisEffect>`\n *\n * @param {string} intent - The unique intent identifier (e.g., 'axis.vault.create')\n * @param {any} handler - The handler function or object\n */\n register(intent: string, handler: any) {\n this.handlers.set(intent, handler);\n }\n\n /**\n * Automatically registers all `@Intent`-decorated methods from a handler instance.\n *\n * Reads the handler prefix from `@Handler` metadata (or falls back to `instance.name`),\n * then registers each `@Intent`-decorated method accordingly.\n *\n * @param {any} instance - The handler instance with `@Intent`-decorated methods\n */\n registerHandler(instance: any) {\n const handlerMeta = Reflect.getMetadata(\n HANDLER_METADATA_KEY,\n instance.constructor,\n );\n const prefix: string | undefined = handlerMeta?.intent || instance.name;\n\n const routes: IntentRoute[] =\n Reflect.getMetadata(INTENT_ROUTES_KEY, instance.constructor) || [];\n\n for (const route of routes) {\n const intentName = route.absolute\n ? route.action\n : `${prefix}.${route.action}`;\n const fn = instance[route.methodName].bind(instance);\n\n if (route.frame) {\n this.register(intentName, { handle: fn });\n } else {\n this.register(intentName, fn);\n }\n }\n }\n\n /**\n * Routes a decoded AXIS frame to the appropriate handler.\n *\n * **Precedence:**\n * 1. System Built-ins (`system.ping`, `public.ping`, `system.time`, `system.echo`)\n * 2. Meta-intent execution (`INTENT.EXEC` / `axis.intent.exec`)\n * 3. Dynamically registered handlers from modules.\n *\n * @param {AxisFrame} frame - The validated and decoded binary frame\n * @returns {Promise<AxisEffect>} The resulting effect of the execution\n * @throws {Error} If the intent header is missing or no handler is registered\n */\n async route(frame: AxisFrame): Promise<AxisEffect> {\n const start = process.hrtime();\n let intent = 'unknown';\n\n try {\n // Extract intent from header TLV (tag 3 = TLV_INTENT)\n const intentBytes = frame.headers.get(3);\n if (!intentBytes) throw new Error('Missing intent');\n intent = new TextDecoder().decode(intentBytes);\n\n let effect: AxisEffect;\n\n if (intent === 'system.ping' || intent === 'public.ping') {\n effect = {\n ok: true,\n effect: 'pong',\n headers: new Map([\n [100, new TextEncoder().encode('AXIS_BACKEND_V1')],\n ]),\n body: new TextEncoder().encode(\n JSON.stringify({\n status: 'ok',\n timestamp: new Date().toISOString(),\n version: '1.0.0',\n }),\n ),\n };\n } else if (intent === 'system.time') {\n const ts = Date.now().toString();\n effect = {\n ok: true,\n effect: 'time',\n body: new TextEncoder().encode(\n JSON.stringify({\n ts,\n iso: new Date().toISOString(),\n }),\n ),\n };\n } else if (intent === 'system.echo') {\n effect = {\n ok: true,\n effect: 'echo',\n body: frame.body,\n };\n } else if (intent === 'INTENT.EXEC' || intent === 'axis.intent.exec') {\n // Meta-intent: Unwrap and execute the inner intent\n try {\n const bodyJSON = JSON.parse(new TextDecoder().decode(frame.body));\n const innerIntent = bodyJSON.intent;\n const innerArgs = bodyJSON.args || {};\n\n if (!innerIntent) {\n throw new Error('INTENT.EXEC missing inner intent');\n }\n\n const innerFrame: AxisFrame = {\n ...frame,\n headers: new Map(frame.headers),\n body: new TextEncoder().encode(JSON.stringify(innerArgs)),\n };\n innerFrame.headers.set(3, new TextEncoder().encode(innerIntent));\n\n return await this.route(innerFrame);\n } catch (e: any) {\n throw new Error(`INTENT.EXEC unwrapping failed: ${e.message}`);\n }\n } else {\n const handler = this.handlers.get(intent);\n if (!handler) {\n throw new Error(`Intent not found: ${intent}`);\n }\n\n if (typeof handler === 'function') {\n const resultBody = await handler(frame.body, frame.headers);\n effect = {\n ok: true,\n effect: 'complete',\n body: resultBody,\n };\n } else {\n if (typeof (handler as any).handle === 'function') {\n effect = await (handler as any).handle(frame);\n } else if (typeof (handler as any).execute === 'function') {\n const bodyRes = await (handler as any).execute(\n frame.body,\n frame.headers,\n );\n effect = {\n ok: true,\n effect: 'complete',\n body: bodyRes,\n };\n } else {\n throw new Error(\n `Handler for ${intent} does not implement handle or execute`,\n );\n }\n }\n }\n\n this.recordLatency(intent, start);\n return effect;\n } catch (e: any) {\n console.error(`Error routing intent ${intent}:`, e.message);\n throw e;\n }\n }\n\n private recordLatency(intent: string, start: [number, number]) {\n const diff = process.hrtime(start);\n // Available for subclass telemetry hooks or future logging\n void diff;\n }\n}\n"],"mappings":"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","names":["Injectable","Injectable"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@nextera.one/axis-server-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Axis Protocol server-side SDK — decorators, interfaces, and routing primitives for building Axis handlers",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "prepublishOnly": "npm run build",
23
+ "dev": "tsup --watch"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/digital-pages-co/axis.git",
28
+ "directory": "axis-server-sdk"
29
+ },
30
+ "homepage": "https://axisprotocol.io",
31
+ "bugs": {
32
+ "url": "https://github.com/digital-pages-co/axis/issues"
33
+ },
34
+ "keywords": [
35
+ "axis",
36
+ "protocol",
37
+ "typescript",
38
+ "server",
39
+ "sdk",
40
+ "handler",
41
+ "decorator",
42
+ "intent",
43
+ "router",
44
+ "binary"
45
+ ],
46
+ "author": "NextEra.One",
47
+ "license": "Apache-2.0",
48
+ "type": "commonjs",
49
+ "peerDependencies": {
50
+ "@nestjs/common": ">=10.0.0",
51
+ "reflect-metadata": ">=0.1.12"
52
+ },
53
+ "devDependencies": {
54
+ "@nestjs/common": "^11.1.12",
55
+ "@nestjs/core": "^11.1.12",
56
+ "@types/node": "^22.0.0",
57
+ "reflect-metadata": "^0.2.2",
58
+ "tsup": "^8.5.1",
59
+ "typescript": "^5.9.3"
60
+ },
61
+ "dependencies": {}
62
+ }