@resourcexjs/type 2.3.0 → 2.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.
- package/README.md +166 -225
- package/dist/index.d.ts +112 -63
- package/dist/index.js +79 -1278
- package/dist/index.js.map +6 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @resourcexjs/type
|
|
2
2
|
|
|
3
|
-
Type system for ResourceX with
|
|
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
|
|
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
|
-
- **
|
|
18
|
-
- **TypeHandlerChain**:
|
|
19
|
-
- **
|
|
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
|
|
24
|
-
|
|
25
|
-
Builtin types are automatically available:
|
|
25
|
+
### Using TypeHandlerChain
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
|
-
import {
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
chain.canHandle("text"); // true
|
|
35
|
+
chain.canHandle("json"); // true
|
|
36
|
+
chain.canHandle("binary"); // true
|
|
34
37
|
|
|
35
38
|
// Builtin aliases
|
|
36
|
-
|
|
37
|
-
|
|
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 {
|
|
44
|
-
import type {
|
|
54
|
+
import { TypeHandlerChain, bundleResourceType } from "@resourcexjs/type";
|
|
55
|
+
import type { BundledType } from "@resourcexjs/type";
|
|
45
56
|
|
|
46
|
-
//
|
|
47
|
-
const promptType
|
|
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
|
|
71
|
-
|
|
60
|
+
// Register with chain
|
|
61
|
+
const chain = TypeHandlerChain.create();
|
|
62
|
+
chain.register(promptType);
|
|
72
63
|
```
|
|
73
64
|
|
|
74
|
-
###
|
|
65
|
+
### Bundling Resource Types
|
|
75
66
|
|
|
76
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
// ["text", "txt", "plaintext", "json", "config", "manifest", "binary", "bin", "blob", "raw"]
|
|
69
|
+
```typescript
|
|
70
|
+
import { bundleResourceType } from "@resourcexjs/type";
|
|
82
71
|
|
|
83
|
-
//
|
|
84
|
-
const
|
|
85
|
-
|
|
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
|
-
|
|
77
|
+
**Source file format (`my-resource.type.ts`):**
|
|
89
78
|
|
|
90
79
|
```typescript
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
import { globalTypeHandlerChain } from "@resourcexjs/type";
|
|
94
|
+
## API Reference
|
|
120
95
|
|
|
121
|
-
|
|
122
|
-
const result = await globalTypeHandlerChain.resolve<void, string>(rxr);
|
|
96
|
+
### `TypeHandlerChain`
|
|
123
97
|
|
|
124
|
-
|
|
125
|
-
console.log(result.schema); // undefined
|
|
98
|
+
Type registry managing type lookup and registration.
|
|
126
99
|
|
|
127
|
-
|
|
128
|
-
const text = await result.execute();
|
|
129
|
-
console.log(text); // "Hello, World!"
|
|
130
|
-
```
|
|
100
|
+
#### Static Methods
|
|
131
101
|
|
|
132
|
-
|
|
102
|
+
##### `TypeHandlerChain.create(): TypeHandlerChain`
|
|
133
103
|
|
|
134
|
-
|
|
104
|
+
Create a new TypeHandlerChain instance with builtin types.
|
|
135
105
|
|
|
136
|
-
|
|
106
|
+
```typescript
|
|
107
|
+
const chain = TypeHandlerChain.create();
|
|
108
|
+
```
|
|
137
109
|
|
|
138
|
-
#### Methods
|
|
110
|
+
#### Instance Methods
|
|
139
111
|
|
|
140
|
-
##### `register(type:
|
|
112
|
+
##### `register(type: BundledType): void`
|
|
141
113
|
|
|
142
|
-
Register
|
|
114
|
+
Register a custom type.
|
|
143
115
|
|
|
144
116
|
**Throws**: `ResourceTypeError` if type name or alias already exists.
|
|
145
117
|
|
|
146
118
|
```typescript
|
|
147
|
-
|
|
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
|
-
|
|
127
|
+
chain.canHandle("text"); // true
|
|
156
128
|
```
|
|
157
129
|
|
|
158
|
-
##### `getHandler(typeName: string):
|
|
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 =
|
|
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 =
|
|
153
|
+
const types = chain.getSupportedTypes();
|
|
172
154
|
```
|
|
173
155
|
|
|
174
|
-
##### `
|
|
156
|
+
##### `clear(): void`
|
|
175
157
|
|
|
176
|
-
|
|
158
|
+
Clear all registered types (for testing).
|
|
177
159
|
|
|
178
|
-
|
|
160
|
+
```typescript
|
|
161
|
+
chain.clear();
|
|
162
|
+
```
|
|
179
163
|
|
|
180
|
-
|
|
164
|
+
### `bundleResourceType(sourcePath, basePath?)`
|
|
181
165
|
|
|
182
|
-
|
|
166
|
+
Bundle a resource type from a source file.
|
|
183
167
|
|
|
184
|
-
**
|
|
168
|
+
**Parameters:**
|
|
185
169
|
|
|
186
|
-
|
|
170
|
+
- `sourcePath: string` - Path to the .type.ts file
|
|
171
|
+
- `basePath?: string` - Base path for resolving relative paths (defaults to cwd)
|
|
187
172
|
|
|
188
|
-
|
|
173
|
+
**Returns**: `Promise<BundledType>`
|
|
189
174
|
|
|
190
|
-
|
|
175
|
+
```typescript
|
|
176
|
+
const myType = await bundleResourceType("./my-resource.type.ts");
|
|
177
|
+
```
|
|
191
178
|
|
|
192
|
-
|
|
179
|
+
## Types
|
|
180
|
+
|
|
181
|
+
### BundledType
|
|
182
|
+
|
|
183
|
+
Pre-bundled resource type ready for execution:
|
|
193
184
|
|
|
194
185
|
```typescript
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
-
|
|
207
|
+
### ResolveContext
|
|
206
208
|
|
|
207
|
-
|
|
209
|
+
Context passed to resolver in sandbox:
|
|
208
210
|
|
|
209
211
|
```typescript
|
|
210
|
-
|
|
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
|
|
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
|
-
- **
|
|
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
|
-
- **
|
|
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
|
-
- **
|
|
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
|
-
|
|
258
|
-
import type { ResourceType } from "@resourcexjs/type";
|
|
259
|
-
import { createRXC, parseRXL } from "@resourcexjs/core";
|
|
263
|
+
**prompt.type.ts:**
|
|
260
264
|
|
|
261
|
-
|
|
265
|
+
```typescript
|
|
266
|
+
export default {
|
|
262
267
|
name: "prompt",
|
|
263
268
|
aliases: ["deepractice-prompt"],
|
|
264
269
|
description: "AI Prompt template",
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
278
|
+
### Example: Tool Type (With Arguments)
|
|
296
279
|
|
|
297
|
-
|
|
298
|
-
import type { ResourceType, JSONSchema } from "@resourcexjs/type";
|
|
280
|
+
**tool.type.ts:**
|
|
299
281
|
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
-
|
|
328
|
-
|
|
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
|
-
|
|
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
|