@resourcexjs/type 2.3.0 → 2.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @resourcexjs/type
2
2
 
3
- Type system for ResourceX with global singleton TypeHandlerChain.
3
+ Type system for ResourceX with sandbox-compatible execution.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,141 +10,113 @@ bun add @resourcexjs/type
10
10
 
11
11
  ## Overview
12
12
 
13
- The `@resourcexjs/type` package provides the type system for ResourceX, managing how different resource types are serialized, deserialized, and resolved.
13
+ The `@resourcexjs/type` package provides the type system for ResourceX, managing how different resource types are resolved and executed.
14
14
 
15
15
  ### Key Concepts
16
16
 
17
- - **ResourceType**: Defines how a resource type is handled (serialization, deserialization, resolution)
18
- - **TypeHandlerChain**: Global singleton managing all registered types
19
- - **Builtin Types**: Text, JSON, and Binary types are automatically registered
17
+ - **BundledType**: Pre-bundled resource type ready for sandbox execution
18
+ - **TypeHandlerChain**: Type registry managing type lookup and registration
19
+ - **ResourceType**: Interface for defining custom types (before bundling)
20
+ - **ResolvedResource**: Result object with execute function and optional schema
21
+ - **Builtin Types**: Text, JSON, and Binary types are included by default
20
22
 
21
23
  ## Usage
22
24
 
23
- ### Using Builtin Types
24
-
25
- Builtin types are automatically available:
25
+ ### Using TypeHandlerChain
26
26
 
27
27
  ```typescript
28
- import { globalTypeHandlerChain } from "@resourcexjs/type";
28
+ import { TypeHandlerChain } from "@resourcexjs/type";
29
+
30
+ // Create a new chain (builtin types included)
31
+ const chain = TypeHandlerChain.create();
29
32
 
30
33
  // Check if type is supported
31
- globalTypeHandlerChain.canHandle("text"); // true
32
- globalTypeHandlerChain.canHandle("json"); // true
33
- globalTypeHandlerChain.canHandle("binary"); // true
34
+ chain.canHandle("text"); // true
35
+ chain.canHandle("json"); // true
36
+ chain.canHandle("binary"); // true
34
37
 
35
38
  // Builtin aliases
36
- globalTypeHandlerChain.canHandle("txt"); // true (alias for text)
37
- globalTypeHandlerChain.canHandle("config"); // true (alias for json)
39
+ chain.canHandle("txt"); // true (alias for text)
40
+ chain.canHandle("config"); // true (alias for json)
41
+
42
+ // Get handler
43
+ const handler = chain.getHandler("text");
44
+ console.log(handler.name); // "text"
45
+
46
+ // Get all supported types
47
+ const types = chain.getSupportedTypes();
48
+ // ["text", "txt", "plaintext", "json", "config", "manifest", "binary", "bin", "blob", "raw"]
38
49
  ```
39
50
 
40
51
  ### Registering Custom Types
41
52
 
42
53
  ```typescript
43
- import { globalTypeHandlerChain } from "@resourcexjs/type";
44
- import type { ResourceType } from "@resourcexjs/type";
54
+ import { TypeHandlerChain, bundleResourceType } from "@resourcexjs/type";
55
+ import type { BundledType } from "@resourcexjs/type";
45
56
 
46
- // Define custom type - resolver returns a callable function
47
- const promptType: ResourceType<void, string> = {
48
- name: "prompt",
49
- aliases: ["deepractice-prompt"],
50
- description: "AI Prompt template",
51
- serializer: {
52
- async serialize(rxr) {
53
- return rxr.content.buffer();
54
- },
55
- async deserialize(data, manifest) {
56
- // ... implementation
57
- },
58
- },
59
- resolver: {
60
- async resolve(rxr) {
61
- // Return a callable function (lazy loading)
62
- return async () => {
63
- const buffer = await rxr.content.file("content");
64
- return buffer.toString("utf-8");
65
- };
66
- },
67
- },
68
- };
57
+ // Bundle a resource type from source file
58
+ const promptType = await bundleResourceType("./prompt.type.ts");
69
59
 
70
- // Register globally
71
- globalTypeHandlerChain.register(promptType);
60
+ // Register with chain
61
+ const chain = TypeHandlerChain.create();
62
+ chain.register(promptType);
72
63
  ```
73
64
 
74
- ### Query Supported Types
65
+ ### Bundling Resource Types
75
66
 
76
- ```typescript
77
- import { globalTypeHandlerChain } from "@resourcexjs/type";
67
+ Resource types must be bundled before registration. The bundler converts a `.type.ts` source file into a `BundledType` with executable code:
78
68
 
79
- // Get all supported types (including aliases)
80
- const types = globalTypeHandlerChain.getSupportedTypes();
81
- // ["text", "txt", "plaintext", "json", "config", "manifest", "binary", "bin", "blob", "raw"]
69
+ ```typescript
70
+ import { bundleResourceType } from "@resourcexjs/type";
82
71
 
83
- // Get handler for specific type
84
- const handler = globalTypeHandlerChain.getHandler("text");
85
- console.log(handler?.name); // "text"
72
+ // Bundle from source file
73
+ const myType = await bundleResourceType("./my-resource.type.ts");
74
+ // → { name, aliases, description, schema, code }
86
75
  ```
87
76
 
88
- ### Serialize/Deserialize
77
+ **Source file format (`my-resource.type.ts`):**
89
78
 
90
79
  ```typescript
91
- import { globalTypeHandlerChain } from "@resourcexjs/type";
92
- import { createRXM, createRXC, parseRXL } from "@resourcexjs/core";
93
-
94
- // Serialize RXR to Buffer
95
- const manifest = createRXM({
96
- domain: "localhost",
97
- name: "test",
98
- type: "text",
99
- version: "1.0.0",
100
- });
101
-
102
- const rxr = {
103
- locator: parseRXL(manifest.toLocator()),
104
- manifest,
105
- content: createRXC("Hello, World!"),
80
+ export default {
81
+ name: "prompt",
82
+ aliases: ["deepractice-prompt"],
83
+ description: "AI Prompt template",
84
+ schema: undefined, // or JSONSchema for types with args
85
+ async resolve(ctx) {
86
+ // ctx.manifest - resource metadata
87
+ // ctx.files - extracted files as Record<string, Uint8Array>
88
+ const content = new TextDecoder().decode(ctx.files["content"]);
89
+ return content;
90
+ },
106
91
  };
107
-
108
- const buffer = await globalTypeHandlerChain.serialize(rxr);
109
- // Buffer containing "Hello, World!"
110
-
111
- // Deserialize Buffer to RXR
112
- const restored = await globalTypeHandlerChain.deserialize(buffer, manifest);
113
- console.log(await restored.content.text()); // "Hello, World!"
114
92
  ```
115
93
 
116
- ### Resolve Content
117
-
118
- ```typescript
119
- import { globalTypeHandlerChain } from "@resourcexjs/type";
94
+ ## API Reference
120
95
 
121
- // Resolve RXR to structured result (lazy loading)
122
- const result = await globalTypeHandlerChain.resolve<void, string>(rxr);
96
+ ### `TypeHandlerChain`
123
97
 
124
- // Check schema (undefined for builtin types)
125
- console.log(result.schema); // undefined
98
+ Type registry managing type lookup and registration.
126
99
 
127
- // Execute to get the actual content
128
- const text = await result.execute();
129
- console.log(text); // "Hello, World!"
130
- ```
100
+ #### Static Methods
131
101
 
132
- ## API Reference
102
+ ##### `TypeHandlerChain.create(): TypeHandlerChain`
133
103
 
134
- ### `globalTypeHandlerChain`
104
+ Create a new TypeHandlerChain instance with builtin types.
135
105
 
136
- Global singleton instance of TypeHandlerChain.
106
+ ```typescript
107
+ const chain = TypeHandlerChain.create();
108
+ ```
137
109
 
138
- #### Methods
110
+ #### Instance Methods
139
111
 
140
- ##### `register(type: ResourceType): void`
112
+ ##### `register(type: BundledType): void`
141
113
 
142
- Register an extension type.
114
+ Register a custom type.
143
115
 
144
116
  **Throws**: `ResourceTypeError` if type name or alias already exists.
145
117
 
146
118
  ```typescript
147
- globalTypeHandlerChain.register(customType);
119
+ chain.register(promptType);
148
120
  ```
149
121
 
150
122
  ##### `canHandle(typeName: string): boolean`
@@ -152,15 +124,25 @@ globalTypeHandlerChain.register(customType);
152
124
  Check if a type is supported.
153
125
 
154
126
  ```typescript
155
- globalTypeHandlerChain.canHandle("text"); // true
127
+ chain.canHandle("text"); // true
156
128
  ```
157
129
 
158
- ##### `getHandler(typeName: string): ResourceType | undefined`
130
+ ##### `getHandler(typeName: string): BundledType`
159
131
 
160
132
  Get handler for a type.
161
133
 
134
+ **Throws**: `ResourceTypeError` if type not supported.
135
+
162
136
  ```typescript
163
- const handler = globalTypeHandlerChain.getHandler("text");
137
+ const handler = chain.getHandler("text");
138
+ ```
139
+
140
+ ##### `getHandlerOrUndefined(typeName: string): BundledType | undefined`
141
+
142
+ Get handler or undefined if not found.
143
+
144
+ ```typescript
145
+ const handler = chain.getHandlerOrUndefined("unknown"); // undefined
164
146
  ```
165
147
 
166
148
  ##### `getSupportedTypes(): string[]`
@@ -168,180 +150,152 @@ const handler = globalTypeHandlerChain.getHandler("text");
168
150
  Get all supported type names (including aliases).
169
151
 
170
152
  ```typescript
171
- const types = globalTypeHandlerChain.getSupportedTypes();
153
+ const types = chain.getSupportedTypes();
172
154
  ```
173
155
 
174
- ##### `serialize(rxr: RXR): Promise<Buffer>`
156
+ ##### `clear(): void`
175
157
 
176
- Serialize RXR to Buffer using appropriate type handler.
158
+ Clear all registered types (for testing).
177
159
 
178
- **Throws**: `ResourceTypeError` if type not supported.
160
+ ```typescript
161
+ chain.clear();
162
+ ```
179
163
 
180
- ##### `deserialize(data: Buffer, manifest: RXM): Promise<RXR>`
164
+ ### `bundleResourceType(sourcePath, basePath?)`
181
165
 
182
- Deserialize Buffer to RXR using appropriate type handler.
166
+ Bundle a resource type from a source file.
183
167
 
184
- **Throws**: `ResourceTypeError` if type not supported.
168
+ **Parameters:**
185
169
 
186
- ##### `resolve<TArgs, TResult>(rxr: RXR): Promise<ResolvedResource<TArgs, TResult>>`
170
+ - `sourcePath: string` - Path to the .type.ts file
171
+ - `basePath?: string` - Base path for resolving relative paths (defaults to cwd)
187
172
 
188
- Resolve RXR content to structured result using appropriate type handler.
173
+ **Returns**: `Promise<BundledType>`
189
174
 
190
- **Returns**: A structured object with `execute` function and optional `schema`.
175
+ ```typescript
176
+ const myType = await bundleResourceType("./my-resource.type.ts");
177
+ ```
191
178
 
192
- **Throws**: `ResourceTypeError` if type not supported.
179
+ ## Types
180
+
181
+ ### BundledType
182
+
183
+ Pre-bundled resource type ready for execution:
193
184
 
194
185
  ```typescript
195
- const result = await globalTypeHandlerChain.resolve<void, string>(rxr);
196
- result.schema; // undefined for builtin types
197
- await result.execute(); // Lazy load content
198
-
199
- // For types with args
200
- const toolResult = await globalTypeHandlerChain.resolve<{ query: string }, unknown>(rxr);
201
- toolResult.schema; // JSONSchema for UI form rendering
202
- await toolResult.execute({ query: "test" });
186
+ interface BundledType {
187
+ name: string; // Type name (e.g., "text", "json")
188
+ aliases?: string[]; // Alternative names
189
+ description: string; // Human-readable description
190
+ schema?: JSONSchema; // JSON Schema for resolver arguments
191
+ code: string; // Bundled resolver code
192
+ }
193
+ ```
194
+
195
+ ### ResolvedResource
196
+
197
+ Result object returned after resolution:
198
+
199
+ ```typescript
200
+ interface ResolvedResource<TArgs = void, TResult = unknown> {
201
+ resource: unknown; // Original RXR object
202
+ execute: (args?: TArgs) => TResult | Promise<TResult>;
203
+ schema: TArgs extends void ? undefined : JSONSchema;
204
+ }
203
205
  ```
204
206
 
205
- ##### `clearExtensions(): void`
207
+ ### ResolveContext
206
208
 
207
- Clear all extension types (for testing). Builtin types remain.
209
+ Context passed to resolver in sandbox:
208
210
 
209
211
  ```typescript
210
- globalTypeHandlerChain.clearExtensions();
212
+ interface ResolveContext {
213
+ manifest: {
214
+ domain: string;
215
+ path?: string;
216
+ name: string;
217
+ type: string;
218
+ version: string;
219
+ };
220
+ files: Record<string, Uint8Array>;
221
+ }
211
222
  ```
212
223
 
224
+ ### IsolatorType
225
+
226
+ Sandbox isolation levels (configured at Registry level):
227
+
228
+ ```typescript
229
+ type IsolatorType = "none" | "srt" | "cloudflare" | "e2b";
230
+ ```
231
+
232
+ - `"none"`: No isolation, fastest (~10ms), for development
233
+ - `"srt"`: OS-level isolation (~50ms), secure local dev
234
+ - `"cloudflare"`: Container isolation (~100ms), local Docker or edge
235
+ - `"e2b"`: MicroVM isolation (~150ms), production (planned)
236
+
213
237
  ## Builtin Types
214
238
 
215
- All builtin types return structured results with `schema: undefined` (no args):
239
+ All builtin types have `schema: undefined` (no arguments):
216
240
 
217
241
  ### Text Type
218
242
 
219
243
  - **Name**: `text`
220
244
  - **Aliases**: `txt`, `plaintext`
221
- - **Storage**: tar.gz archive
222
- - **Resolves to**: `{ execute: () => Promise<string>, schema: undefined }`
245
+ - **Resolves to**: `string`
223
246
 
224
247
  ### JSON Type
225
248
 
226
249
  - **Name**: `json`
227
250
  - **Aliases**: `config`, `manifest`
228
- - **Storage**: tar.gz archive
229
- - **Resolves to**: `{ execute: () => Promise<unknown>, schema: undefined }`
251
+ - **Resolves to**: `unknown`
230
252
 
231
253
  ### Binary Type
232
254
 
233
255
  - **Name**: `binary`
234
256
  - **Aliases**: `bin`, `blob`, `raw`
235
- - **Storage**: tar.gz archive
236
- - **Resolves to**: `{ execute: () => Promise<Buffer>, schema: undefined }`
237
-
238
- ## Type System Architecture
239
-
240
- ```
241
- ┌─────────────────────────────────────────┐
242
- │ globalTypeHandlerChain (Singleton) │
243
- │ │
244
- │ Builtin: text, json, binary │
245
- │ Extensions: custom types... │
246
- └─────────────────────────────────────────┘
247
-
248
-
249
- All packages use
250
- global singleton
251
- ```
257
+ - **Resolves to**: `Uint8Array`
252
258
 
253
259
  ## Creating Custom Types
254
260
 
255
261
  ### Example: Prompt Type (No Arguments)
256
262
 
257
- ```typescript
258
- import type { ResourceType } from "@resourcexjs/type";
259
- import { createRXC, parseRXL } from "@resourcexjs/core";
263
+ **prompt.type.ts:**
260
264
 
261
- export const promptType: ResourceType<void, string> = {
265
+ ```typescript
266
+ export default {
262
267
  name: "prompt",
263
268
  aliases: ["deepractice-prompt"],
264
269
  description: "AI Prompt template",
265
-
266
- serializer: {
267
- async serialize(rxr) {
268
- return rxr.content.buffer();
269
- },
270
-
271
- async deserialize(data, manifest) {
272
- return {
273
- locator: parseRXL(manifest.toLocator()),
274
- manifest,
275
- content: await createRXC({ archive: data }),
276
- };
277
- },
278
- },
279
-
280
- resolver: {
281
- schema: undefined, // No args, schema is undefined
282
- async resolve(rxr) {
283
- return {
284
- schema: undefined,
285
- execute: async () => {
286
- const buffer = await rxr.content.file("content");
287
- return buffer.toString("utf-8");
288
- },
289
- };
290
- },
270
+ schema: undefined,
271
+ async resolve(ctx) {
272
+ const content = new TextDecoder().decode(ctx.files["content"]);
273
+ return content;
291
274
  },
292
275
  };
293
276
  ```
294
277
 
295
- ### Example: Tool Type (With Arguments and Schema)
278
+ ### Example: Tool Type (With Arguments)
296
279
 
297
- ```typescript
298
- import type { ResourceType, JSONSchema } from "@resourcexjs/type";
280
+ **tool.type.ts:**
299
281
 
300
- interface ToolArgs {
301
- query: string;
302
- limit?: number;
303
- }
304
-
305
- const toolSchema: JSONSchema = {
306
- type: "object",
307
- properties: {
308
- query: { type: "string", description: "Search keyword" },
309
- limit: { type: "number", description: "Max results", default: 10 },
310
- },
311
- required: ["query"],
312
- };
313
-
314
- export const toolType: ResourceType<ToolArgs, unknown> = {
282
+ ```typescript
283
+ export default {
315
284
  name: "tool",
316
285
  description: "Executable tool with arguments",
317
-
318
- serializer: {
319
- async serialize(rxr) {
320
- return rxr.content.buffer();
321
- },
322
- async deserialize(data, manifest) {
323
- // ... implementation
286
+ schema: {
287
+ type: "object",
288
+ properties: {
289
+ query: { type: "string", description: "Search keyword" },
290
+ limit: { type: "number", description: "Max results", default: 10 },
324
291
  },
292
+ required: ["query"],
325
293
  },
326
-
327
- resolver: {
328
- schema: toolSchema, // Required for types with args
329
- async resolve(rxr) {
330
- return {
331
- schema: toolSchema,
332
- execute: async (args) => {
333
- // Execute with args
334
- return { query: args?.query, limit: args?.limit ?? 10 };
335
- },
336
- };
337
- },
294
+ async resolve(ctx, args) {
295
+ // Execute with args
296
+ return { query: args?.query, limit: args?.limit ?? 10 };
338
297
  },
339
298
  };
340
-
341
- // Usage
342
- const result = await globalTypeHandlerChain.resolve<ToolArgs, unknown>(rxr);
343
- result.schema; // JSONSchema for UI form rendering
344
- await result.execute({ query: "test", limit: 5 });
345
299
  ```
346
300
 
347
301
  ## Error Handling
@@ -350,7 +304,7 @@ await result.execute({ query: "test", limit: 5 });
350
304
  import { ResourceTypeError } from "@resourcexjs/type";
351
305
 
352
306
  try {
353
- await globalTypeHandlerChain.serialize(rxr);
307
+ chain.getHandler("unknown");
354
308
  } catch (error) {
355
309
  if (error instanceof ResourceTypeError) {
356
310
  console.error("Type error:", error.message);
@@ -358,19 +312,6 @@ try {
358
312
  }
359
313
  ```
360
314
 
361
- ## Testing
362
-
363
- When testing, use `clearExtensions()` to reset extension types:
364
-
365
- ```typescript
366
- import { afterEach } from "bun:test";
367
- import { globalTypeHandlerChain } from "@resourcexjs/type";
368
-
369
- afterEach(() => {
370
- globalTypeHandlerChain.clearExtensions();
371
- });
372
- ```
373
-
374
315
  ## License
375
316
 
376
317
  MIT