@aigne/afs-http 1.11.0-beta.4 → 1.11.0-beta.5
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 +19 -19
- package/dist/client.cjs +13 -5
- package/dist/client.d.cts +3 -0
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.mts +3 -0
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs +14 -6
- package/dist/client.mjs.map +1 -1
- package/dist/errors.cjs +10 -0
- package/dist/errors.d.cts +7 -1
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts +7 -1
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +10 -1
- package/dist/errors.mjs.map +1 -1
- package/dist/handler.cjs +26 -1
- package/dist/handler.d.cts +12 -1
- package/dist/handler.d.cts.map +1 -1
- package/dist/handler.d.mts +12 -1
- package/dist/handler.d.mts.map +1 -1
- package/dist/handler.mjs +26 -1
- package/dist/handler.mjs.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/protocol.cjs +2 -0
- package/dist/protocol.d.cts +3 -1
- package/dist/protocol.d.cts.map +1 -1
- package/dist/protocol.d.mts +3 -1
- package/dist/protocol.d.mts.map +1 -1
- package/dist/protocol.mjs +2 -0
- package/dist/protocol.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -135,6 +135,18 @@ interface AFSHttpClientOptions {
|
|
|
135
135
|
/** Optional description */
|
|
136
136
|
description?: string;
|
|
137
137
|
|
|
138
|
+
/** Access mode: "readonly" or "readwrite" (default: "readwrite") */
|
|
139
|
+
accessMode?: AFSAccessMode;
|
|
140
|
+
|
|
141
|
+
/** Authorization token - sent as Bearer token in Authorization header */
|
|
142
|
+
token?: string;
|
|
143
|
+
|
|
144
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
145
|
+
timeout?: number;
|
|
146
|
+
|
|
147
|
+
/** Maximum request body size in bytes (default: 10MB) */
|
|
148
|
+
maxBodySize?: number;
|
|
149
|
+
|
|
138
150
|
/** Retry configuration */
|
|
139
151
|
retry?: {
|
|
140
152
|
maxAttempts?: number; // Default: 3
|
|
@@ -142,12 +154,6 @@ interface AFSHttpClientOptions {
|
|
|
142
154
|
maxDelay?: number; // Default: 10000ms
|
|
143
155
|
multiplier?: number; // Default: 2
|
|
144
156
|
};
|
|
145
|
-
|
|
146
|
-
/** Request timeout in milliseconds (default: 30000) */
|
|
147
|
-
timeout?: number;
|
|
148
|
-
|
|
149
|
-
/** Custom fetch implementation */
|
|
150
|
-
fetch?: typeof fetch;
|
|
151
157
|
}
|
|
152
158
|
```
|
|
153
159
|
|
|
@@ -260,22 +266,16 @@ const client = new AFSHttpClient({
|
|
|
260
266
|
|
|
261
267
|
## Advanced Usage
|
|
262
268
|
|
|
263
|
-
###
|
|
269
|
+
### Authentication
|
|
264
270
|
|
|
265
|
-
|
|
271
|
+
Use the built-in `token` option for Bearer token authentication:
|
|
266
272
|
|
|
267
273
|
```typescript
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
...options.headers,
|
|
274
|
-
"Authorization": `Bearer ${process.env.API_TOKEN}`,
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
}
|
|
274
|
+
const client = new AFSHttpClient({
|
|
275
|
+
url: "http://localhost:3000/afs",
|
|
276
|
+
name: "remote",
|
|
277
|
+
token: process.env.AFS_TOKEN, // Sent as "Authorization: Bearer <token>"
|
|
278
|
+
});
|
|
279
279
|
```
|
|
280
280
|
|
|
281
281
|
### Custom Error Handling
|
package/dist/client.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_protocol = require('./protocol.cjs');
|
|
1
2
|
const require_errors = require('./errors.cjs');
|
|
2
3
|
const require_retry = require('./retry.cjs');
|
|
3
4
|
|
|
@@ -38,6 +39,7 @@ var AFSHttpClient = class {
|
|
|
38
39
|
description;
|
|
39
40
|
accessMode;
|
|
40
41
|
url;
|
|
42
|
+
token;
|
|
41
43
|
timeout;
|
|
42
44
|
maxBodySize;
|
|
43
45
|
retryOptions;
|
|
@@ -48,6 +50,7 @@ var AFSHttpClient = class {
|
|
|
48
50
|
this.name = options.name;
|
|
49
51
|
this.description = options.description;
|
|
50
52
|
this.accessMode = options.accessMode ?? DEFAULT_CLIENT_OPTIONS.accessMode;
|
|
53
|
+
this.token = options.token;
|
|
51
54
|
this.timeout = options.timeout ?? DEFAULT_CLIENT_OPTIONS.timeout;
|
|
52
55
|
this.maxBodySize = options.maxBodySize ?? DEFAULT_CLIENT_OPTIONS.maxBodySize;
|
|
53
56
|
this.retryOptions = {
|
|
@@ -64,11 +67,13 @@ var AFSHttpClient = class {
|
|
|
64
67
|
params
|
|
65
68
|
});
|
|
66
69
|
if (body.length > this.maxBodySize) throw new require_errors.AFSRuntimeError(`Request body too large: ${body.length} bytes exceeds limit of ${this.maxBodySize} bytes`);
|
|
70
|
+
const headers = { "Content-Type": "application/json" };
|
|
71
|
+
if (this.token) headers.Authorization = `Bearer ${this.token}`;
|
|
67
72
|
let response;
|
|
68
73
|
try {
|
|
69
74
|
response = await require_retry.fetchWithRetry(this.url, {
|
|
70
75
|
method: "POST",
|
|
71
|
-
headers
|
|
76
|
+
headers,
|
|
72
77
|
body,
|
|
73
78
|
signal: AbortSignal.timeout(this.timeout)
|
|
74
79
|
}, this.retryOptions);
|
|
@@ -83,10 +88,13 @@ var AFSHttpClient = class {
|
|
|
83
88
|
}
|
|
84
89
|
if (!result.success) {
|
|
85
90
|
const error = result.error;
|
|
86
|
-
if (error)
|
|
87
|
-
code
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
if (error) {
|
|
92
|
+
if (error.code === require_protocol.AFSErrorCode.UNAUTHORIZED) throw new require_errors.AFSUnauthorizedError(error.message, error.details);
|
|
93
|
+
throw new require_errors.AFSRuntimeError(error.message || "Unknown error", {
|
|
94
|
+
code: error.code,
|
|
95
|
+
details: error.details
|
|
96
|
+
});
|
|
97
|
+
}
|
|
90
98
|
throw new require_errors.AFSRuntimeError("Request failed without error details");
|
|
91
99
|
}
|
|
92
100
|
return result.data;
|
package/dist/client.d.cts
CHANGED
|
@@ -14,6 +14,8 @@ interface AFSHttpClientOptions {
|
|
|
14
14
|
description?: string;
|
|
15
15
|
/** Access mode (default: "readwrite") */
|
|
16
16
|
accessMode?: AFSAccessMode;
|
|
17
|
+
/** Authorization token (optional) */
|
|
18
|
+
token?: string;
|
|
17
19
|
/** Request timeout in milliseconds (default: 30000) */
|
|
18
20
|
timeout?: number;
|
|
19
21
|
/** Maximum request body size in bytes (default: 10MB) */
|
|
@@ -49,6 +51,7 @@ declare class AFSHttpClient implements AFSModule {
|
|
|
49
51
|
readonly description?: string;
|
|
50
52
|
readonly accessMode: AFSAccessMode;
|
|
51
53
|
private readonly url;
|
|
54
|
+
private readonly token?;
|
|
52
55
|
private readonly timeout;
|
|
53
56
|
private readonly maxBodySize;
|
|
54
57
|
private readonly retryOptions;
|
package/dist/client.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"client.d.cts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;AA+BA;AAmDA;UAnDiB,oBAAA;EAAA;EAAA,GAAA;EAAA;EAAA,IAAA;EAAA;EAAA,WAAA;EAAA;EAAA,UAAA,GAQF,aAAA;EAAA;EAAA,KAAA;EAAA;EAAA,OAAA;EAAA;EAAA,WAAA;EAAA;EAAA,KAAA,GAQL,YAAA;AAAA;AAAA;AAmCV;;;;;;;;;;;;;;;;;;;;;;AAnCU,cAmCG,aAAA,YAAyB,SAAA;EAAA,SAAA,IAAA;EAAA,SAAA,WAAA;EAAA,SAAA,UAAA,EAGf,aAAA;EAAA,iBAAA,GAAA;EAAA,iBAAA,KAAA;EAAA,iBAAA,OAAA;EAAA,iBAAA,WAAA;EAAA,iBAAA,YAAA;EAAA,YAAA,OAAA,EAQA,oBAAA;EAAA;;;EAAA,QAAA,GAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GA+Fc,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GAIzB,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,MAAA,IAAA,UAAA,OAAA,EAMjD,oBAAA,EAAA,OAAA,GACC,eAAA,GACT,OAAA,CAAQ,cAAA;EAAA,OAAA,IAAA,UAAA,OAAA,GAI0B,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,OAAA,OAAA,UAAA,OAAA,UAAA,OAAA,GAOpD,gBAAA,GACT,OAAA,CAAQ,eAAA;EAAA,OAAA,IAAA,UAAA,KAAA,UAAA,OAAA,GAIyC,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,KAAA,IAAA,UAAA,IAAA,EAMvE,MAAA,mBAAA,OAAA,EACG,cAAA,GACR,OAAA,CAAQ,aAAA;AAAA"}
|
package/dist/client.d.mts
CHANGED
|
@@ -14,6 +14,8 @@ interface AFSHttpClientOptions {
|
|
|
14
14
|
description?: string;
|
|
15
15
|
/** Access mode (default: "readwrite") */
|
|
16
16
|
accessMode?: AFSAccessMode;
|
|
17
|
+
/** Authorization token (optional) */
|
|
18
|
+
token?: string;
|
|
17
19
|
/** Request timeout in milliseconds (default: 30000) */
|
|
18
20
|
timeout?: number;
|
|
19
21
|
/** Maximum request body size in bytes (default: 10MB) */
|
|
@@ -49,6 +51,7 @@ declare class AFSHttpClient implements AFSModule {
|
|
|
49
51
|
readonly description?: string;
|
|
50
52
|
readonly accessMode: AFSAccessMode;
|
|
51
53
|
private readonly url;
|
|
54
|
+
private readonly token?;
|
|
52
55
|
private readonly timeout;
|
|
53
56
|
private readonly maxBodySize;
|
|
54
57
|
private readonly retryOptions;
|
package/dist/client.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"mappings":";;;;;AA+BA;AAmDA;UAnDiB,oBAAA;EAAA;EAAA,GAAA;EAAA;EAAA,IAAA;EAAA;EAAA,WAAA;EAAA;EAAA,UAAA,GAQF,aAAA;EAAA;EAAA,KAAA;EAAA;EAAA,OAAA;EAAA;EAAA,WAAA;EAAA;EAAA,KAAA,GAQL,YAAA;AAAA;AAAA;AAmCV;;;;;;;;;;;;;;;;;;;;;;AAnCU,cAmCG,aAAA,YAAyB,SAAA;EAAA,SAAA,IAAA;EAAA,SAAA,WAAA;EAAA,SAAA,UAAA,EAGf,aAAA;EAAA,iBAAA,GAAA;EAAA,iBAAA,KAAA;EAAA,iBAAA,OAAA;EAAA,iBAAA,WAAA;EAAA,iBAAA,YAAA;EAAA,YAAA,OAAA,EAQA,oBAAA;EAAA;;;EAAA,QAAA,GAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GA+Fc,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GAIzB,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,MAAA,IAAA,UAAA,OAAA,EAMjD,oBAAA,EAAA,OAAA,GACC,eAAA,GACT,OAAA,CAAQ,cAAA;EAAA,OAAA,IAAA,UAAA,OAAA,GAI0B,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,OAAA,OAAA,UAAA,OAAA,UAAA,OAAA,GAOpD,gBAAA,GACT,OAAA,CAAQ,eAAA;EAAA,OAAA,IAAA,UAAA,KAAA,UAAA,OAAA,GAIyC,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,KAAA,IAAA,UAAA,IAAA,EAMvE,MAAA,mBAAA,OAAA,EACG,cAAA,GACR,OAAA,CAAQ,aAAA;AAAA"}
|
package/dist/client.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AFSErrorCode } from "./protocol.mjs";
|
|
2
|
+
import { AFSNetworkError, AFSRuntimeError, AFSUnauthorizedError } from "./errors.mjs";
|
|
2
3
|
import { DEFAULT_RETRY_OPTIONS, fetchWithRetry } from "./retry.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/client.ts
|
|
@@ -38,6 +39,7 @@ var AFSHttpClient = class {
|
|
|
38
39
|
description;
|
|
39
40
|
accessMode;
|
|
40
41
|
url;
|
|
42
|
+
token;
|
|
41
43
|
timeout;
|
|
42
44
|
maxBodySize;
|
|
43
45
|
retryOptions;
|
|
@@ -48,6 +50,7 @@ var AFSHttpClient = class {
|
|
|
48
50
|
this.name = options.name;
|
|
49
51
|
this.description = options.description;
|
|
50
52
|
this.accessMode = options.accessMode ?? DEFAULT_CLIENT_OPTIONS.accessMode;
|
|
53
|
+
this.token = options.token;
|
|
51
54
|
this.timeout = options.timeout ?? DEFAULT_CLIENT_OPTIONS.timeout;
|
|
52
55
|
this.maxBodySize = options.maxBodySize ?? DEFAULT_CLIENT_OPTIONS.maxBodySize;
|
|
53
56
|
this.retryOptions = {
|
|
@@ -64,11 +67,13 @@ var AFSHttpClient = class {
|
|
|
64
67
|
params
|
|
65
68
|
});
|
|
66
69
|
if (body.length > this.maxBodySize) throw new AFSRuntimeError(`Request body too large: ${body.length} bytes exceeds limit of ${this.maxBodySize} bytes`);
|
|
70
|
+
const headers = { "Content-Type": "application/json" };
|
|
71
|
+
if (this.token) headers.Authorization = `Bearer ${this.token}`;
|
|
67
72
|
let response;
|
|
68
73
|
try {
|
|
69
74
|
response = await fetchWithRetry(this.url, {
|
|
70
75
|
method: "POST",
|
|
71
|
-
headers
|
|
76
|
+
headers,
|
|
72
77
|
body,
|
|
73
78
|
signal: AbortSignal.timeout(this.timeout)
|
|
74
79
|
}, this.retryOptions);
|
|
@@ -83,10 +88,13 @@ var AFSHttpClient = class {
|
|
|
83
88
|
}
|
|
84
89
|
if (!result.success) {
|
|
85
90
|
const error = result.error;
|
|
86
|
-
if (error)
|
|
87
|
-
code
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
if (error) {
|
|
92
|
+
if (error.code === AFSErrorCode.UNAUTHORIZED) throw new AFSUnauthorizedError(error.message, error.details);
|
|
93
|
+
throw new AFSRuntimeError(error.message || "Unknown error", {
|
|
94
|
+
code: error.code,
|
|
95
|
+
details: error.details
|
|
96
|
+
});
|
|
97
|
+
}
|
|
90
98
|
throw new AFSRuntimeError("Request failed without error details");
|
|
91
99
|
}
|
|
92
100
|
return result.data;
|
package/dist/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type {\n AFSAccessMode,\n AFSDeleteOptions,\n AFSDeleteResult,\n AFSExecOptions,\n AFSExecResult,\n AFSListOptions,\n AFSListResult,\n AFSModule,\n AFSReadOptions,\n AFSReadResult,\n AFSRenameOptions,\n AFSRenameResult,\n AFSSearchOptions,\n AFSSearchResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n} from \"@aigne/afs\";\nimport { AFSNetworkError, AFSRuntimeError } from \"./errors.js\";\nimport type
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type {\n AFSAccessMode,\n AFSDeleteOptions,\n AFSDeleteResult,\n AFSExecOptions,\n AFSExecResult,\n AFSListOptions,\n AFSListResult,\n AFSModule,\n AFSReadOptions,\n AFSReadResult,\n AFSRenameOptions,\n AFSRenameResult,\n AFSSearchOptions,\n AFSSearchResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n} from \"@aigne/afs\";\nimport { AFSNetworkError, AFSRuntimeError, AFSUnauthorizedError } from \"./errors.js\";\nimport {\n AFSErrorCode,\n type AFSRpcMethod,\n type AFSRpcResponse,\n type AFSRpcResults,\n} from \"./protocol.js\";\nimport { DEFAULT_RETRY_OPTIONS, fetchWithRetry, type RetryOptions } from \"./retry.js\";\n\n/**\n * Options for AFSHttpClient\n */\nexport interface AFSHttpClientOptions {\n /** Server URL (required) */\n url: string;\n /** Module name for mounting to AFS (required) */\n name: string;\n /** Module description (optional) */\n description?: string;\n /** Access mode (default: \"readwrite\") */\n accessMode?: AFSAccessMode;\n /** Authorization token (optional) */\n token?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /** Maximum request body size in bytes (default: 10MB) */\n maxBodySize?: number;\n /** Retry configuration */\n retry?: RetryOptions;\n}\n\n/**\n * Default client options\n */\nconst DEFAULT_CLIENT_OPTIONS = {\n timeout: 30000,\n maxBodySize: 10 * 1024 * 1024, // 10MB\n accessMode: \"readwrite\" as AFSAccessMode,\n};\n\n/**\n * AFS HTTP Client\n *\n * Implements the AFSModule interface, forwarding all operations to a remote\n * AFS server via HTTP RPC calls.\n *\n * @example\n * ```typescript\n * import { AFS } from \"@aigne/afs\";\n * import { AFSHttpClient } from \"@aigne/afs-http\";\n *\n * const afs = new AFS();\n * afs.mount(\n * new AFSHttpClient({\n * url: \"https://remote-afs.example.com/afs/rpc\",\n * name: \"remote\",\n * })\n * );\n *\n * // Use like any local provider\n * const result = await afs.list(\"/modules/remote/some-path\");\n * ```\n */\nexport class AFSHttpClient implements AFSModule {\n readonly name: string;\n readonly description?: string;\n readonly accessMode: AFSAccessMode;\n\n private readonly url: string;\n private readonly token?: string;\n private readonly timeout: number;\n private readonly maxBodySize: number;\n private readonly retryOptions: RetryOptions;\n\n constructor(options: AFSHttpClientOptions) {\n if (!options.url) {\n throw new Error(\"AFSHttpClient requires a url option\");\n }\n if (!options.name) {\n throw new Error(\"AFSHttpClient requires a name option\");\n }\n\n this.url = options.url.endsWith(\"/rpc\") ? options.url : `${options.url}/rpc`;\n this.name = options.name;\n this.description = options.description;\n this.accessMode = options.accessMode ?? DEFAULT_CLIENT_OPTIONS.accessMode;\n this.token = options.token;\n this.timeout = options.timeout ?? DEFAULT_CLIENT_OPTIONS.timeout;\n this.maxBodySize = options.maxBodySize ?? DEFAULT_CLIENT_OPTIONS.maxBodySize;\n this.retryOptions = {\n ...DEFAULT_RETRY_OPTIONS,\n ...options.retry,\n };\n }\n\n /**\n * Make an RPC call to the remote server\n */\n private async rpc<M extends AFSRpcMethod>(\n method: M,\n params: Record<string, unknown>,\n ): Promise<AFSRpcResults[M]> {\n const body = JSON.stringify({ method, params });\n\n // Check body size before sending\n if (body.length > this.maxBodySize) {\n throw new AFSRuntimeError(\n `Request body too large: ${body.length} bytes exceeds limit of ${this.maxBodySize} bytes`,\n );\n }\n\n // Build headers\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.token) {\n headers.Authorization = `Bearer ${this.token}`;\n }\n\n let response: Response;\n try {\n response = await fetchWithRetry(\n this.url,\n {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(this.timeout),\n },\n this.retryOptions,\n );\n } catch (error) {\n throw new AFSNetworkError(\n `Failed to connect to ${this.url}: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined,\n );\n }\n\n // Parse response\n let result: AFSRpcResponse<AFSRpcResults[M]>;\n try {\n result = await response.json();\n } catch {\n throw new AFSRuntimeError(\n `Invalid response from server: expected JSON, got ${response.headers.get(\"content-type\")}`,\n );\n }\n\n // Check for RPC-level errors\n if (!result.success) {\n const error = result.error;\n if (error) {\n // Handle unauthorized error specifically\n if (error.code === AFSErrorCode.UNAUTHORIZED) {\n throw new AFSUnauthorizedError(error.message, error.details);\n }\n // Re-throw with the appropriate error type based on code\n const errorMessage = error.message || \"Unknown error\";\n throw new AFSRuntimeError(errorMessage, {\n code: error.code,\n details: error.details,\n });\n }\n throw new AFSRuntimeError(\"Request failed without error details\");\n }\n\n return result.data as AFSRpcResults[M];\n }\n\n async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n return this.rpc(\"list\", { path, options });\n }\n\n async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n return this.rpc(\"read\", { path, options });\n }\n\n async write(\n path: string,\n content: AFSWriteEntryPayload,\n options?: AFSWriteOptions,\n ): Promise<AFSWriteResult> {\n return this.rpc(\"write\", { path, content, options });\n }\n\n async delete(path: string, options?: AFSDeleteOptions): Promise<AFSDeleteResult> {\n return this.rpc(\"delete\", { path, options });\n }\n\n async rename(\n oldPath: string,\n newPath: string,\n options?: AFSRenameOptions,\n ): Promise<AFSRenameResult> {\n return this.rpc(\"rename\", { oldPath, newPath, options });\n }\n\n async search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult> {\n return this.rpc(\"search\", { path, query, options });\n }\n\n async exec(\n path: string,\n args: Record<string, unknown>,\n options: AFSExecOptions,\n ): Promise<AFSExecResult> {\n return this.rpc(\"exec\", { path, args, options });\n }\n}\n"],"mappings":";;;;;;;;AAqDA,MAAM,yBAAyB;CAC7B,SAAS;CACT,aAAa,KAAK,OAAO;CACzB,YAAY;CACb;;;;;;;;;;;;;;;;;;;;;;;;AAyBD,IAAa,gBAAb,MAAgD;CAC9C,AAAS;CACT,AAAS;CACT,AAAS;CAET,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAEjB,YAAY,SAA+B;AACzC,MAAI,CAAC,QAAQ,IACX,OAAM,IAAI,MAAM,sCAAsC;AAExD,MAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MAAM,uCAAuC;AAGzD,OAAK,MAAM,QAAQ,IAAI,SAAS,OAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,IAAI;AACvE,OAAK,OAAO,QAAQ;AACpB,OAAK,cAAc,QAAQ;AAC3B,OAAK,aAAa,QAAQ,cAAc,uBAAuB;AAC/D,OAAK,QAAQ,QAAQ;AACrB,OAAK,UAAU,QAAQ,WAAW,uBAAuB;AACzD,OAAK,cAAc,QAAQ,eAAe,uBAAuB;AACjE,OAAK,eAAe;GAClB,GAAG;GACH,GAAG,QAAQ;GACZ;;;;;CAMH,MAAc,IACZ,QACA,QAC2B;EAC3B,MAAM,OAAO,KAAK,UAAU;GAAE;GAAQ;GAAQ,CAAC;AAG/C,MAAI,KAAK,SAAS,KAAK,YACrB,OAAM,IAAI,gBACR,2BAA2B,KAAK,OAAO,0BAA0B,KAAK,YAAY,QACnF;EAIH,MAAM,UAAkC,EACtC,gBAAgB,oBACjB;AACD,MAAI,KAAK,MACP,SAAQ,gBAAgB,UAAU,KAAK;EAGzC,IAAI;AACJ,MAAI;AACF,cAAW,MAAM,eACf,KAAK,KACL;IACE,QAAQ;IACR;IACA;IACA,QAAQ,YAAY,QAAQ,KAAK,QAAQ;IAC1C,EACD,KAAK,aACN;WACM,OAAO;AACd,SAAM,IAAI,gBACR,wBAAwB,KAAK,IAAI,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC3F,iBAAiB,QAAQ,QAAQ,OAClC;;EAIH,IAAI;AACJ,MAAI;AACF,YAAS,MAAM,SAAS,MAAM;UACxB;AACN,SAAM,IAAI,gBACR,oDAAoD,SAAS,QAAQ,IAAI,eAAe,GACzF;;AAIH,MAAI,CAAC,OAAO,SAAS;GACnB,MAAM,QAAQ,OAAO;AACrB,OAAI,OAAO;AAET,QAAI,MAAM,SAAS,aAAa,aAC9B,OAAM,IAAI,qBAAqB,MAAM,SAAS,MAAM,QAAQ;AAI9D,UAAM,IAAI,gBADW,MAAM,WAAW,iBACE;KACtC,MAAM,MAAM;KACZ,SAAS,MAAM;KAChB,CAAC;;AAEJ,SAAM,IAAI,gBAAgB,uCAAuC;;AAGnE,SAAO,OAAO;;CAGhB,MAAM,KAAK,MAAc,SAAkD;AACzE,SAAO,KAAK,IAAI,QAAQ;GAAE;GAAM;GAAS,CAAC;;CAG5C,MAAM,KAAK,MAAc,SAAkD;AACzE,SAAO,KAAK,IAAI,QAAQ;GAAE;GAAM;GAAS,CAAC;;CAG5C,MAAM,MACJ,MACA,SACA,SACyB;AACzB,SAAO,KAAK,IAAI,SAAS;GAAE;GAAM;GAAS;GAAS,CAAC;;CAGtD,MAAM,OAAO,MAAc,SAAsD;AAC/E,SAAO,KAAK,IAAI,UAAU;GAAE;GAAM;GAAS,CAAC;;CAG9C,MAAM,OACJ,SACA,SACA,SAC0B;AAC1B,SAAO,KAAK,IAAI,UAAU;GAAE;GAAS;GAAS;GAAS,CAAC;;CAG1D,MAAM,OAAO,MAAc,OAAe,SAAsD;AAC9F,SAAO,KAAK,IAAI,UAAU;GAAE;GAAM;GAAO;GAAS,CAAC;;CAGrD,MAAM,KACJ,MACA,MACA,SACwB;AACxB,SAAO,KAAK,IAAI,QAAQ;GAAE;GAAM;GAAM;GAAS,CAAC"}
|
package/dist/errors.cjs
CHANGED
|
@@ -72,6 +72,15 @@ var AFSPayloadTooLargeError = class extends AFSHttpError {
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
/**
|
|
75
|
+
* Unauthorized error (missing or invalid token)
|
|
76
|
+
*/
|
|
77
|
+
var AFSUnauthorizedError = class extends AFSHttpError {
|
|
78
|
+
constructor(message = "Unauthorized", details) {
|
|
79
|
+
super(message, require_protocol.AFSErrorCode.UNAUTHORIZED, 401, details);
|
|
80
|
+
this.name = "AFSUnauthorizedError";
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
75
84
|
* Network error (for client-side use)
|
|
76
85
|
*/
|
|
77
86
|
var AFSNetworkError = class extends Error {
|
|
@@ -102,4 +111,5 @@ exports.AFSNotFoundError = AFSNotFoundError;
|
|
|
102
111
|
exports.AFSPayloadTooLargeError = AFSPayloadTooLargeError;
|
|
103
112
|
exports.AFSPermissionError = AFSPermissionError;
|
|
104
113
|
exports.AFSRuntimeError = AFSRuntimeError;
|
|
114
|
+
exports.AFSUnauthorizedError = AFSUnauthorizedError;
|
|
105
115
|
exports.mapErrorToCode = mapErrorToCode;
|
package/dist/errors.d.cts
CHANGED
|
@@ -46,6 +46,12 @@ declare class AFSInvalidRequestError extends AFSHttpError {
|
|
|
46
46
|
declare class AFSPayloadTooLargeError extends AFSHttpError {
|
|
47
47
|
constructor(maxSize: number, actualSize?: number);
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Unauthorized error (missing or invalid token)
|
|
51
|
+
*/
|
|
52
|
+
declare class AFSUnauthorizedError extends AFSHttpError {
|
|
53
|
+
constructor(message?: string, details?: unknown);
|
|
54
|
+
}
|
|
49
55
|
/**
|
|
50
56
|
* Network error (for client-side use)
|
|
51
57
|
*/
|
|
@@ -59,5 +65,5 @@ declare class AFSNetworkError extends Error {
|
|
|
59
65
|
*/
|
|
60
66
|
declare function mapErrorToCode(error: Error): AFSErrorCode;
|
|
61
67
|
//#endregion
|
|
62
|
-
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode };
|
|
68
|
+
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode };
|
|
63
69
|
//# sourceMappingURL=errors.d.cts.map
|
package/dist/errors.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.cts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;AAKA;;cAAa,YAAA,SAAqB,KAAA;EAAA,SAAA,IAAA,EAGR,YAAA;EAAA,SAAA,UAAA;EAAA,SAAA,OAAA;EAAA,YAAA,OAAA,UAAA,IAAA,EAAA,YAAA,EAAA,UAAA,WAAA,OAAA;AAAA;AAAA;;;AAAA,cAYb,gBAAA,SAAyB,YAAA;EAAA,YAAA,IAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,kBAAA,SAA2B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUxC;AAUA;AApBwC,cAU3B,gBAAA,SAAyB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,eAAA,SAAwB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUrC;AAUA;AApBqC,cAUxB,sBAAA,SAA+B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAU5C;AAaA;AAvB4C,cAU/B,uBAAA,SAAgC,YAAA;EAAA,YAAA,OAAA,UAAA,UAAA;AAAA;AAAA;AAa7C
|
|
1
|
+
{"version":3,"file":"errors.d.cts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;AAKA;;cAAa,YAAA,SAAqB,KAAA;EAAA,SAAA,IAAA,EAGR,YAAA;EAAA,SAAA,UAAA;EAAA,SAAA,OAAA;EAAA,YAAA,OAAA,UAAA,IAAA,EAAA,YAAA,EAAA,UAAA,WAAA,OAAA;AAAA;AAAA;;;AAAA,cAYb,gBAAA,SAAyB,YAAA;EAAA,YAAA,IAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,kBAAA,SAA2B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUxC;AAUA;AApBwC,cAU3B,gBAAA,SAAyB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,eAAA,SAAwB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUrC;AAUA;AApBqC,cAUxB,sBAAA,SAA+B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAU5C;AAaA;AAvB4C,cAU/B,uBAAA,SAAgC,YAAA;EAAA,YAAA,OAAA,UAAA,UAAA;AAAA;AAAA;AAa7C;AAUA;AAvB6C,cAahC,oBAAA,SAA6B,YAAA;EAAA,YAAA,OAAA,WAAA,OAAA;AAAA;AAAA;AAU1C;;AAV0C,cAU7B,eAAA,SAAwB,KAAA;EAAA,SAAA,KAAA,GAGT,KAAA;EAAA,SAAA,SAAA;EAAA,YAAA,OAAA,UAAA,KAAA,GAAA,KAAA,cAAA,SAAA;AAAA;AAAA;;;AAAA,iBAWZ,cAAA,CAAA,KAAA,EAAsB,KAAA,GAAQ,YAAA"}
|
package/dist/errors.d.mts
CHANGED
|
@@ -46,6 +46,12 @@ declare class AFSInvalidRequestError extends AFSHttpError {
|
|
|
46
46
|
declare class AFSPayloadTooLargeError extends AFSHttpError {
|
|
47
47
|
constructor(maxSize: number, actualSize?: number);
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Unauthorized error (missing or invalid token)
|
|
51
|
+
*/
|
|
52
|
+
declare class AFSUnauthorizedError extends AFSHttpError {
|
|
53
|
+
constructor(message?: string, details?: unknown);
|
|
54
|
+
}
|
|
49
55
|
/**
|
|
50
56
|
* Network error (for client-side use)
|
|
51
57
|
*/
|
|
@@ -59,5 +65,5 @@ declare class AFSNetworkError extends Error {
|
|
|
59
65
|
*/
|
|
60
66
|
declare function mapErrorToCode(error: Error): AFSErrorCode;
|
|
61
67
|
//#endregion
|
|
62
|
-
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode };
|
|
68
|
+
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode };
|
|
63
69
|
//# sourceMappingURL=errors.d.mts.map
|
package/dist/errors.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;AAKA;;cAAa,YAAA,SAAqB,KAAA;EAAA,SAAA,IAAA,EAGR,YAAA;EAAA,SAAA,UAAA;EAAA,SAAA,OAAA;EAAA,YAAA,OAAA,UAAA,IAAA,EAAA,YAAA,EAAA,UAAA,WAAA,OAAA;AAAA;AAAA;;;AAAA,cAYb,gBAAA,SAAyB,YAAA;EAAA,YAAA,IAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,kBAAA,SAA2B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUxC;AAUA;AApBwC,cAU3B,gBAAA,SAAyB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,eAAA,SAAwB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUrC;AAUA;AApBqC,cAUxB,sBAAA,SAA+B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAU5C;AAaA;AAvB4C,cAU/B,uBAAA,SAAgC,YAAA;EAAA,YAAA,OAAA,UAAA,UAAA;AAAA;AAAA;AAa7C
|
|
1
|
+
{"version":3,"file":"errors.d.mts","names":[],"sources":["../src/errors.ts"],"mappings":";;;;AAKA;;cAAa,YAAA,SAAqB,KAAA;EAAA,SAAA,IAAA,EAGR,YAAA;EAAA,SAAA,UAAA;EAAA,SAAA,OAAA;EAAA,YAAA,OAAA,UAAA,IAAA,EAAA,YAAA,EAAA,UAAA,WAAA,OAAA;AAAA;AAAA;;;AAAA,cAYb,gBAAA,SAAyB,YAAA;EAAA,YAAA,IAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,kBAAA,SAA2B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUxC;AAUA;AApBwC,cAU3B,gBAAA,SAAyB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUtC;AAUA;AApBsC,cAUzB,eAAA,SAAwB,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAUrC;AAUA;AApBqC,cAUxB,sBAAA,SAA+B,YAAA;EAAA,YAAA,OAAA,UAAA,OAAA;AAAA;AAAA;AAU5C;AAaA;AAvB4C,cAU/B,uBAAA,SAAgC,YAAA;EAAA,YAAA,OAAA,UAAA,UAAA;AAAA;AAAA;AAa7C;AAUA;AAvB6C,cAahC,oBAAA,SAA6B,YAAA;EAAA,YAAA,OAAA,WAAA,OAAA;AAAA;AAAA;AAU1C;;AAV0C,cAU7B,eAAA,SAAwB,KAAA;EAAA,SAAA,KAAA,GAGT,KAAA;EAAA,SAAA,SAAA;EAAA,YAAA,OAAA,UAAA,KAAA,GAAA,KAAA,cAAA,SAAA;AAAA;AAAA;;;AAAA,iBAWZ,cAAA,CAAA,KAAA,EAAsB,KAAA,GAAQ,YAAA"}
|
package/dist/errors.mjs
CHANGED
|
@@ -72,6 +72,15 @@ var AFSPayloadTooLargeError = class extends AFSHttpError {
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
/**
|
|
75
|
+
* Unauthorized error (missing or invalid token)
|
|
76
|
+
*/
|
|
77
|
+
var AFSUnauthorizedError = class extends AFSHttpError {
|
|
78
|
+
constructor(message = "Unauthorized", details) {
|
|
79
|
+
super(message, AFSErrorCode.UNAUTHORIZED, 401, details);
|
|
80
|
+
this.name = "AFSUnauthorizedError";
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
75
84
|
* Network error (for client-side use)
|
|
76
85
|
*/
|
|
77
86
|
var AFSNetworkError = class extends Error {
|
|
@@ -94,5 +103,5 @@ function mapErrorToCode(error) {
|
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
//#endregion
|
|
97
|
-
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode };
|
|
106
|
+
export { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode };
|
|
98
107
|
//# sourceMappingURL=errors.mjs.map
|
package/dist/errors.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { AFSErrorCode } from \"./protocol.js\";\n\n/**\n * Base class for AFS HTTP errors\n */\nexport class AFSHttpError extends Error {\n constructor(\n message: string,\n public readonly code: AFSErrorCode,\n public readonly httpStatus: number = 200,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = \"AFSHttpError\";\n }\n}\n\n/**\n * Path not found error\n */\nexport class AFSNotFoundError extends AFSHttpError {\n constructor(path: string, details?: unknown) {\n super(`Path not found: ${path}`, AFSErrorCode.NOT_FOUND, 200, details);\n this.name = \"AFSNotFoundError\";\n }\n}\n\n/**\n * Permission denied error (including readonly mode)\n */\nexport class AFSPermissionError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.PERMISSION_DENIED, 200, details);\n this.name = \"AFSPermissionError\";\n }\n}\n\n/**\n * Conflict error (concurrent modification)\n */\nexport class AFSConflictError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.CONFLICT, 200, details);\n this.name = \"AFSConflictError\";\n }\n}\n\n/**\n * Runtime error\n */\nexport class AFSRuntimeError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.RUNTIME_ERROR, 200, details);\n this.name = \"AFSRuntimeError\";\n }\n}\n\n/**\n * Invalid request error (bad JSON, invalid method, etc.)\n */\nexport class AFSInvalidRequestError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.RUNTIME_ERROR, 400, details);\n this.name = \"AFSInvalidRequestError\";\n }\n}\n\n/**\n * Payload too large error\n */\nexport class AFSPayloadTooLargeError extends AFSHttpError {\n constructor(maxSize: number, actualSize?: number) {\n const message = actualSize\n ? `Payload too large: ${actualSize} bytes exceeds limit of ${maxSize} bytes`\n : `Payload too large: exceeds limit of ${maxSize} bytes`;\n super(message, AFSErrorCode.RUNTIME_ERROR, 413, { maxSize, actualSize });\n this.name = \"AFSPayloadTooLargeError\";\n }\n}\n\n/**\n * Network error (for client-side use)\n */\nexport class AFSNetworkError extends Error {\n constructor(\n message: string,\n public readonly cause?: Error,\n public readonly retryable: boolean = true,\n ) {\n super(message);\n this.name = \"AFSNetworkError\";\n }\n}\n\n/**\n * Map common error messages to appropriate AFS error codes\n */\nexport function mapErrorToCode(error: Error): AFSErrorCode {\n const message = error.message.toLowerCase();\n\n if (\n message.includes(\"not found\") ||\n message.includes(\"enoent\") ||\n message.includes(\"does not exist\")\n ) {\n return AFSErrorCode.NOT_FOUND;\n }\n\n if (\n message.includes(\"permission\") ||\n message.includes(\"readonly\") ||\n message.includes(\"read-only\") ||\n message.includes(\"access denied\") ||\n message.includes(\"eacces\")\n ) {\n return AFSErrorCode.PERMISSION_DENIED;\n }\n\n if (\n message.includes(\"conflict\") ||\n message.includes(\"already exists\") ||\n message.includes(\"eexist\")\n ) {\n return AFSErrorCode.CONFLICT;\n }\n\n return AFSErrorCode.RUNTIME_ERROR;\n}\n"],"mappings":";;;;;;AAKA,IAAa,eAAb,cAAkC,MAAM;CACtC,YACE,SACA,AAAgB,MAChB,AAAgB,aAAqB,KACrC,AAAgB,SAChB;AACA,QAAM,QAAQ;EAJE;EACA;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,aAAa;CACjD,YAAY,MAAc,SAAmB;AAC3C,QAAM,mBAAmB,QAAQ,aAAa,WAAW,KAAK,QAAQ;AACtE,OAAK,OAAO;;;;;;AAOhB,IAAa,qBAAb,cAAwC,aAAa;CACnD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,mBAAmB,KAAK,QAAQ;AAC5D,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,aAAa;CACjD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,UAAU,KAAK,QAAQ;AACnD,OAAK,OAAO;;;;;;AAOhB,IAAa,kBAAb,cAAqC,aAAa;CAChD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,eAAe,KAAK,QAAQ;AACxD,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,aAAa;CACvD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,eAAe,KAAK,QAAQ;AACxD,OAAK,OAAO;;;;;;AAOhB,IAAa,0BAAb,cAA6C,aAAa;CACxD,YAAY,SAAiB,YAAqB;EAChD,MAAM,UAAU,aACZ,sBAAsB,WAAW,0BAA0B,QAAQ,UACnE,uCAAuC,QAAQ;AACnD,QAAM,SAAS,aAAa,eAAe,KAAK;GAAE;GAAS;GAAY,CAAC;AACxE,OAAK,OAAO;;;;;;AAOhB,IAAa,kBAAb,cAAqC,MAAM;CACzC,YACE,SACA,AAAgB,OAChB,AAAgB,YAAqB,MACrC;AACA,QAAM,QAAQ;EAHE;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,SAAgB,eAAe,OAA4B;CACzD,MAAM,UAAU,MAAM,QAAQ,aAAa;AAE3C,KACE,QAAQ,SAAS,YAAY,IAC7B,QAAQ,SAAS,SAAS,IAC1B,QAAQ,SAAS,iBAAiB,CAElC,QAAO,aAAa;AAGtB,KACE,QAAQ,SAAS,aAAa,IAC9B,QAAQ,SAAS,WAAW,IAC5B,QAAQ,SAAS,YAAY,IAC7B,QAAQ,SAAS,gBAAgB,IACjC,QAAQ,SAAS,SAAS,CAE1B,QAAO,aAAa;AAGtB,KACE,QAAQ,SAAS,WAAW,IAC5B,QAAQ,SAAS,iBAAiB,IAClC,QAAQ,SAAS,SAAS,CAE1B,QAAO,aAAa;AAGtB,QAAO,aAAa"}
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { AFSErrorCode } from \"./protocol.js\";\n\n/**\n * Base class for AFS HTTP errors\n */\nexport class AFSHttpError extends Error {\n constructor(\n message: string,\n public readonly code: AFSErrorCode,\n public readonly httpStatus: number = 200,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = \"AFSHttpError\";\n }\n}\n\n/**\n * Path not found error\n */\nexport class AFSNotFoundError extends AFSHttpError {\n constructor(path: string, details?: unknown) {\n super(`Path not found: ${path}`, AFSErrorCode.NOT_FOUND, 200, details);\n this.name = \"AFSNotFoundError\";\n }\n}\n\n/**\n * Permission denied error (including readonly mode)\n */\nexport class AFSPermissionError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.PERMISSION_DENIED, 200, details);\n this.name = \"AFSPermissionError\";\n }\n}\n\n/**\n * Conflict error (concurrent modification)\n */\nexport class AFSConflictError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.CONFLICT, 200, details);\n this.name = \"AFSConflictError\";\n }\n}\n\n/**\n * Runtime error\n */\nexport class AFSRuntimeError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.RUNTIME_ERROR, 200, details);\n this.name = \"AFSRuntimeError\";\n }\n}\n\n/**\n * Invalid request error (bad JSON, invalid method, etc.)\n */\nexport class AFSInvalidRequestError extends AFSHttpError {\n constructor(message: string, details?: unknown) {\n super(message, AFSErrorCode.RUNTIME_ERROR, 400, details);\n this.name = \"AFSInvalidRequestError\";\n }\n}\n\n/**\n * Payload too large error\n */\nexport class AFSPayloadTooLargeError extends AFSHttpError {\n constructor(maxSize: number, actualSize?: number) {\n const message = actualSize\n ? `Payload too large: ${actualSize} bytes exceeds limit of ${maxSize} bytes`\n : `Payload too large: exceeds limit of ${maxSize} bytes`;\n super(message, AFSErrorCode.RUNTIME_ERROR, 413, { maxSize, actualSize });\n this.name = \"AFSPayloadTooLargeError\";\n }\n}\n\n/**\n * Unauthorized error (missing or invalid token)\n */\nexport class AFSUnauthorizedError extends AFSHttpError {\n constructor(message = \"Unauthorized\", details?: unknown) {\n super(message, AFSErrorCode.UNAUTHORIZED, 401, details);\n this.name = \"AFSUnauthorizedError\";\n }\n}\n\n/**\n * Network error (for client-side use)\n */\nexport class AFSNetworkError extends Error {\n constructor(\n message: string,\n public readonly cause?: Error,\n public readonly retryable: boolean = true,\n ) {\n super(message);\n this.name = \"AFSNetworkError\";\n }\n}\n\n/**\n * Map common error messages to appropriate AFS error codes\n */\nexport function mapErrorToCode(error: Error): AFSErrorCode {\n const message = error.message.toLowerCase();\n\n if (\n message.includes(\"not found\") ||\n message.includes(\"enoent\") ||\n message.includes(\"does not exist\")\n ) {\n return AFSErrorCode.NOT_FOUND;\n }\n\n if (\n message.includes(\"permission\") ||\n message.includes(\"readonly\") ||\n message.includes(\"read-only\") ||\n message.includes(\"access denied\") ||\n message.includes(\"eacces\")\n ) {\n return AFSErrorCode.PERMISSION_DENIED;\n }\n\n if (\n message.includes(\"conflict\") ||\n message.includes(\"already exists\") ||\n message.includes(\"eexist\")\n ) {\n return AFSErrorCode.CONFLICT;\n }\n\n return AFSErrorCode.RUNTIME_ERROR;\n}\n"],"mappings":";;;;;;AAKA,IAAa,eAAb,cAAkC,MAAM;CACtC,YACE,SACA,AAAgB,MAChB,AAAgB,aAAqB,KACrC,AAAgB,SAChB;AACA,QAAM,QAAQ;EAJE;EACA;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,aAAa;CACjD,YAAY,MAAc,SAAmB;AAC3C,QAAM,mBAAmB,QAAQ,aAAa,WAAW,KAAK,QAAQ;AACtE,OAAK,OAAO;;;;;;AAOhB,IAAa,qBAAb,cAAwC,aAAa;CACnD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,mBAAmB,KAAK,QAAQ;AAC5D,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,aAAa;CACjD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,UAAU,KAAK,QAAQ;AACnD,OAAK,OAAO;;;;;;AAOhB,IAAa,kBAAb,cAAqC,aAAa;CAChD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,eAAe,KAAK,QAAQ;AACxD,OAAK,OAAO;;;;;;AAOhB,IAAa,yBAAb,cAA4C,aAAa;CACvD,YAAY,SAAiB,SAAmB;AAC9C,QAAM,SAAS,aAAa,eAAe,KAAK,QAAQ;AACxD,OAAK,OAAO;;;;;;AAOhB,IAAa,0BAAb,cAA6C,aAAa;CACxD,YAAY,SAAiB,YAAqB;EAChD,MAAM,UAAU,aACZ,sBAAsB,WAAW,0BAA0B,QAAQ,UACnE,uCAAuC,QAAQ;AACnD,QAAM,SAAS,aAAa,eAAe,KAAK;GAAE;GAAS;GAAY,CAAC;AACxE,OAAK,OAAO;;;;;;AAOhB,IAAa,uBAAb,cAA0C,aAAa;CACrD,YAAY,UAAU,gBAAgB,SAAmB;AACvD,QAAM,SAAS,aAAa,cAAc,KAAK,QAAQ;AACvD,OAAK,OAAO;;;;;;AAOhB,IAAa,kBAAb,cAAqC,MAAM;CACzC,YACE,SACA,AAAgB,OAChB,AAAgB,YAAqB,MACrC;AACA,QAAM,QAAQ;EAHE;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,SAAgB,eAAe,OAA4B;CACzD,MAAM,UAAU,MAAM,QAAQ,aAAa;AAE3C,KACE,QAAQ,SAAS,YAAY,IAC7B,QAAQ,SAAS,SAAS,IAC1B,QAAQ,SAAS,iBAAiB,CAElC,QAAO,aAAa;AAGtB,KACE,QAAQ,SAAS,aAAa,IAC9B,QAAQ,SAAS,WAAW,IAC5B,QAAQ,SAAS,YAAY,IAC7B,QAAQ,SAAS,gBAAgB,IACjC,QAAQ,SAAS,SAAS,CAE1B,QAAO,aAAa;AAGtB,KACE,QAAQ,SAAS,WAAW,IAC5B,QAAQ,SAAS,iBAAiB,IAClC,QAAQ,SAAS,SAAS,CAE1B,QAAO,aAAa;AAGtB,QAAO,aAAa"}
|
package/dist/handler.cjs
CHANGED
|
@@ -35,10 +35,13 @@ const DEFAULT_OPTIONS = {
|
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
37
|
function createAFSHttpHandler(options) {
|
|
38
|
-
const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize } = options;
|
|
38
|
+
const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize, token: tokenConfig } = options;
|
|
39
39
|
return async (request) => {
|
|
40
40
|
try {
|
|
41
41
|
if (request.method !== "POST") return createJsonResponse(require_protocol.createErrorResponse(require_protocol.AFSErrorCode.RUNTIME_ERROR, `Method not allowed: ${request.method}`), 405);
|
|
42
|
+
if (tokenConfig) {
|
|
43
|
+
if (!validateToken(request, tokenConfig).valid) return createJsonResponse(require_protocol.createErrorResponse(require_protocol.AFSErrorCode.UNAUTHORIZED, "Unauthorized"), 401);
|
|
44
|
+
}
|
|
42
45
|
if (!request.headers.get("content-type")?.includes("application/json")) return createJsonResponse(require_protocol.createErrorResponse(require_protocol.AFSErrorCode.RUNTIME_ERROR, "Content-Type must be application/json"), 400);
|
|
43
46
|
const contentLength = request.headers.get("content-length");
|
|
44
47
|
if (contentLength && Number.parseInt(contentLength, 10) > maxBodySize) {
|
|
@@ -113,6 +116,28 @@ async function executeRpcMethod(module, method, params) {
|
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
/**
|
|
119
|
+
* Extract Bearer token from Authorization header
|
|
120
|
+
*/
|
|
121
|
+
function extractBearerToken(request) {
|
|
122
|
+
const authHeader = request.headers.get("authorization");
|
|
123
|
+
if (!authHeader) return null;
|
|
124
|
+
if (!authHeader.toLowerCase().startsWith("bearer ")) return null;
|
|
125
|
+
return authHeader.slice(7).trim();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Validate token against configuration
|
|
129
|
+
*/
|
|
130
|
+
function validateToken(request, tokenConfig) {
|
|
131
|
+
const token = extractBearerToken(request);
|
|
132
|
+
if (!token) return { valid: false };
|
|
133
|
+
if (typeof tokenConfig === "string") return { valid: token === tokenConfig };
|
|
134
|
+
try {
|
|
135
|
+
return { valid: tokenConfig(token) };
|
|
136
|
+
} catch {
|
|
137
|
+
return { valid: false };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
116
141
|
* Create a JSON Response with proper headers
|
|
117
142
|
*/
|
|
118
143
|
function createJsonResponse(body, status) {
|
package/dist/handler.d.cts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { AFSModule } from "@aigne/afs";
|
|
2
2
|
|
|
3
3
|
//#region src/handler.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Token validator function type
|
|
6
|
+
*/
|
|
7
|
+
type TokenValidator = (token: string) => boolean;
|
|
4
8
|
/**
|
|
5
9
|
* Options for creating an AFS HTTP handler
|
|
6
10
|
*/
|
|
@@ -11,6 +15,13 @@ interface AFSHttpHandlerOptions {
|
|
|
11
15
|
maxBodySize?: number;
|
|
12
16
|
/** Request timeout in milliseconds (default: 30000) */
|
|
13
17
|
timeout?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Token validation configuration (optional)
|
|
20
|
+
* - Not configured: No authorization required (backward compatible)
|
|
21
|
+
* - String: Static token, requests must carry matching Bearer token
|
|
22
|
+
* - Function: Custom validation logic, returns true if valid
|
|
23
|
+
*/
|
|
24
|
+
token?: string | TokenValidator;
|
|
14
25
|
}
|
|
15
26
|
/**
|
|
16
27
|
* Create an AFS HTTP handler function
|
|
@@ -39,5 +50,5 @@ interface AFSHttpHandlerOptions {
|
|
|
39
50
|
*/
|
|
40
51
|
declare function createAFSHttpHandler(options: AFSHttpHandlerOptions): (request: Request) => Promise<Response>;
|
|
41
52
|
//#endregion
|
|
42
|
-
export { AFSHttpHandlerOptions, createAFSHttpHandler };
|
|
53
|
+
export { AFSHttpHandlerOptions, TokenValidator, createAFSHttpHandler };
|
|
43
54
|
//# sourceMappingURL=handler.d.cts.map
|
package/dist/handler.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.cts","names":[],"sources":["../src/handler.ts"],"mappings":";;;;AAoBA;
|
|
1
|
+
{"version":3,"file":"handler.d.cts","names":[],"sources":["../src/handler.ts"],"mappings":";;;;AAoBA;AAKA;KALY,cAAA,IAAA,KAAA;AAAA;AAKZ;AAiDA;AAtDY,UAKK,qBAAA;EAAA;EAAA,MAAA,EAEP,SAAA;EAAA;EAAA,WAAA;EAAA;EAAA,OAAA;EAAA;AA+CV;;;;;EA/CU,KAAA,YAWS,cAAA;AAAA;AAAA;AAoCnB;;;;;;;;;;;;;;;;;;;;;;;;AApCmB,iBAoCH,oBAAA,CAAA,OAAA,EACL,qBAAA,IAAA,OAAA,EACE,OAAA,KAAY,OAAA,CAAQ,QAAA"}
|
package/dist/handler.d.mts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { AFSModule } from "@aigne/afs";
|
|
2
2
|
|
|
3
3
|
//#region src/handler.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Token validator function type
|
|
6
|
+
*/
|
|
7
|
+
type TokenValidator = (token: string) => boolean;
|
|
4
8
|
/**
|
|
5
9
|
* Options for creating an AFS HTTP handler
|
|
6
10
|
*/
|
|
@@ -11,6 +15,13 @@ interface AFSHttpHandlerOptions {
|
|
|
11
15
|
maxBodySize?: number;
|
|
12
16
|
/** Request timeout in milliseconds (default: 30000) */
|
|
13
17
|
timeout?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Token validation configuration (optional)
|
|
20
|
+
* - Not configured: No authorization required (backward compatible)
|
|
21
|
+
* - String: Static token, requests must carry matching Bearer token
|
|
22
|
+
* - Function: Custom validation logic, returns true if valid
|
|
23
|
+
*/
|
|
24
|
+
token?: string | TokenValidator;
|
|
14
25
|
}
|
|
15
26
|
/**
|
|
16
27
|
* Create an AFS HTTP handler function
|
|
@@ -39,5 +50,5 @@ interface AFSHttpHandlerOptions {
|
|
|
39
50
|
*/
|
|
40
51
|
declare function createAFSHttpHandler(options: AFSHttpHandlerOptions): (request: Request) => Promise<Response>;
|
|
41
52
|
//#endregion
|
|
42
|
-
export { AFSHttpHandlerOptions, createAFSHttpHandler };
|
|
53
|
+
export { AFSHttpHandlerOptions, TokenValidator, createAFSHttpHandler };
|
|
43
54
|
//# sourceMappingURL=handler.d.mts.map
|
package/dist/handler.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.mts","names":[],"sources":["../src/handler.ts"],"mappings":";;;;AAoBA;
|
|
1
|
+
{"version":3,"file":"handler.d.mts","names":[],"sources":["../src/handler.ts"],"mappings":";;;;AAoBA;AAKA;KALY,cAAA,IAAA,KAAA;AAAA;AAKZ;AAiDA;AAtDY,UAKK,qBAAA;EAAA;EAAA,MAAA,EAEP,SAAA;EAAA;EAAA,WAAA;EAAA;EAAA,OAAA;EAAA;AA+CV;;;;;EA/CU,KAAA,YAWS,cAAA;AAAA;AAAA;AAoCnB;;;;;;;;;;;;;;;;;;;;;;;;AApCmB,iBAoCH,oBAAA,CAAA,OAAA,EACL,qBAAA,IAAA,OAAA,EACE,OAAA,KAAY,OAAA,CAAQ,QAAA"}
|
package/dist/handler.mjs
CHANGED
|
@@ -35,10 +35,13 @@ const DEFAULT_OPTIONS = {
|
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
37
|
function createAFSHttpHandler(options) {
|
|
38
|
-
const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize } = options;
|
|
38
|
+
const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize, token: tokenConfig } = options;
|
|
39
39
|
return async (request) => {
|
|
40
40
|
try {
|
|
41
41
|
if (request.method !== "POST") return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Method not allowed: ${request.method}`), 405);
|
|
42
|
+
if (tokenConfig) {
|
|
43
|
+
if (!validateToken(request, tokenConfig).valid) return createJsonResponse(createErrorResponse(AFSErrorCode.UNAUTHORIZED, "Unauthorized"), 401);
|
|
44
|
+
}
|
|
42
45
|
if (!request.headers.get("content-type")?.includes("application/json")) return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Content-Type must be application/json"), 400);
|
|
43
46
|
const contentLength = request.headers.get("content-length");
|
|
44
47
|
if (contentLength && Number.parseInt(contentLength, 10) > maxBodySize) {
|
|
@@ -113,6 +116,28 @@ async function executeRpcMethod(module, method, params) {
|
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
/**
|
|
119
|
+
* Extract Bearer token from Authorization header
|
|
120
|
+
*/
|
|
121
|
+
function extractBearerToken(request) {
|
|
122
|
+
const authHeader = request.headers.get("authorization");
|
|
123
|
+
if (!authHeader) return null;
|
|
124
|
+
if (!authHeader.toLowerCase().startsWith("bearer ")) return null;
|
|
125
|
+
return authHeader.slice(7).trim();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Validate token against configuration
|
|
129
|
+
*/
|
|
130
|
+
function validateToken(request, tokenConfig) {
|
|
131
|
+
const token = extractBearerToken(request);
|
|
132
|
+
if (!token) return { valid: false };
|
|
133
|
+
if (typeof tokenConfig === "string") return { valid: token === tokenConfig };
|
|
134
|
+
try {
|
|
135
|
+
return { valid: tokenConfig(token) };
|
|
136
|
+
} catch {
|
|
137
|
+
return { valid: false };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
116
141
|
* Create a JSON Response with proper headers
|
|
117
142
|
*/
|
|
118
143
|
function createJsonResponse(body, status) {
|
package/dist/handler.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.mjs","names":[],"sources":["../src/handler.ts"],"sourcesContent":["import type { AFSModule } from \"@aigne/afs\";\nimport {\n AFSHttpError,\n AFSInvalidRequestError,\n AFSPayloadTooLargeError,\n mapErrorToCode,\n} from \"./errors.js\";\nimport {\n AFSErrorCode,\n type AFSRpcMethod,\n type AFSRpcRequest,\n type AFSRpcResponse,\n createErrorResponse,\n createSuccessResponse,\n isValidRpcMethod,\n} from \"./protocol.js\";\n\n/**\n * Options for creating an AFS HTTP handler\n */\nexport interface AFSHttpHandlerOptions {\n /** The AFS module to expose */\n module: AFSModule;\n /** Maximum request body size in bytes (default: 10MB) */\n maxBodySize?: number;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\n/**\n * Default handler options\n */\nconst DEFAULT_OPTIONS = {\n maxBodySize: 10 * 1024 * 1024, // 10MB\n timeout: 30000, // 30 seconds\n};\n\n/**\n * Create an AFS HTTP handler function\n *\n * This function creates a pure handler that accepts a Web Standard Request\n * and returns a Web Standard Response. It can be used with any HTTP framework\n * that supports these standards (Hono, Bun, Deno, etc.) or adapted for\n * frameworks like Express and Koa.\n *\n * @param options - Handler options\n * @returns A handler function that processes AFS RPC requests\n *\n * @example\n * ```typescript\n * // With Hono\n * const handler = createAFSHttpHandler({ module: provider });\n * app.post(\"/afs/rpc\", (c) => handler(c.req.raw));\n *\n * // With Bun\n * Bun.serve({\n * fetch(req) {\n * if (url.pathname === \"/afs/rpc\") return handler(req);\n * }\n * });\n * ```\n */\nexport function createAFSHttpHandler(\n options: AFSHttpHandlerOptions,\n): (request: Request) => Promise<Response> {\n const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize } = options;\n\n return async (request: Request): Promise<Response> => {\n try {\n // Validate HTTP method\n if (request.method !== \"POST\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Method not allowed: ${request.method}`),\n 405,\n );\n }\n\n // Check Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Content-Type must be application/json\"),\n 400,\n );\n }\n\n // Check Content-Length if available\n const contentLength = request.headers.get(\"content-length\");\n if (contentLength && Number.parseInt(contentLength, 10) > maxBodySize) {\n const error = new AFSPayloadTooLargeError(maxBodySize, Number.parseInt(contentLength, 10));\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n\n // Parse request body\n let body: AFSRpcRequest;\n try {\n const text = await request.text();\n if (text.length > maxBodySize) {\n const error = new AFSPayloadTooLargeError(maxBodySize, text.length);\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n body = JSON.parse(text);\n } catch {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Invalid JSON body\"),\n 400,\n );\n }\n\n // Validate request structure\n if (!body || typeof body !== \"object\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Request body must be an object\"),\n 400,\n );\n }\n\n const { method, params } = body;\n\n // Validate method\n if (!method || typeof method !== \"string\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Missing or invalid method\"),\n 400,\n );\n }\n\n if (!isValidRpcMethod(method)) {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Unknown method: ${method}`),\n 400,\n );\n }\n\n // Validate params\n if (!params || typeof params !== \"object\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Missing or invalid params\"),\n 400,\n );\n }\n\n // Execute the RPC method\n const result = await executeRpcMethod(module, method, params);\n return createJsonResponse(createSuccessResponse(result), 200);\n } catch (error) {\n // Handle known AFS errors\n if (error instanceof AFSHttpError) {\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n\n // Handle unknown errors\n const message = error instanceof Error ? error.message : String(error);\n const code = error instanceof Error ? mapErrorToCode(error) : AFSErrorCode.RUNTIME_ERROR;\n return createJsonResponse(createErrorResponse(code, message), 200);\n }\n };\n}\n\n/**\n * Execute an RPC method on the module\n */\nasync function executeRpcMethod(\n module: AFSModule,\n method: AFSRpcMethod,\n params: Record<string, unknown>,\n): Promise<unknown> {\n switch (method) {\n case \"list\": {\n if (!module.list) {\n throw new AFSInvalidRequestError(\"Module does not support list operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.list(path, options as any);\n }\n\n case \"read\": {\n if (!module.read) {\n throw new AFSInvalidRequestError(\"Module does not support read operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.read(path, options as any);\n }\n\n case \"write\": {\n if (!module.write) {\n throw new AFSInvalidRequestError(\"Module does not support write operation\");\n }\n const { path, content, options } = params as {\n path: string;\n content: unknown;\n options?: unknown;\n };\n return await module.write(path, content as any, options as any);\n }\n\n case \"delete\": {\n if (!module.delete) {\n throw new AFSInvalidRequestError(\"Module does not support delete operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.delete(path, options as any);\n }\n\n case \"rename\": {\n if (!module.rename) {\n throw new AFSInvalidRequestError(\"Module does not support rename operation\");\n }\n const { oldPath, newPath, options } = params as {\n oldPath: string;\n newPath: string;\n options?: unknown;\n };\n return await module.rename(oldPath, newPath, options as any);\n }\n\n case \"search\": {\n if (!module.search) {\n throw new AFSInvalidRequestError(\"Module does not support search operation\");\n }\n const { path, query, options } = params as {\n path: string;\n query: string;\n options?: unknown;\n };\n return await module.search(path, query, options as any);\n }\n\n case \"exec\": {\n if (!module.exec) {\n throw new AFSInvalidRequestError(\"Module does not support exec operation\");\n }\n const { path, args, options } = params as {\n path: string;\n args: Record<string, unknown>;\n options?: unknown;\n };\n return await module.exec(path, args, options as any);\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = method;\n throw new AFSInvalidRequestError(`Unknown method: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Create a JSON Response with proper headers\n */\nfunction createJsonResponse(body: AFSRpcResponse, status: number): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"handler.mjs","names":[],"sources":["../src/handler.ts"],"sourcesContent":["import type { AFSModule } from \"@aigne/afs\";\nimport {\n AFSHttpError,\n AFSInvalidRequestError,\n AFSPayloadTooLargeError,\n mapErrorToCode,\n} from \"./errors.js\";\nimport {\n AFSErrorCode,\n type AFSRpcMethod,\n type AFSRpcRequest,\n type AFSRpcResponse,\n createErrorResponse,\n createSuccessResponse,\n isValidRpcMethod,\n} from \"./protocol.js\";\n\n/**\n * Token validator function type\n */\nexport type TokenValidator = (token: string) => boolean;\n\n/**\n * Options for creating an AFS HTTP handler\n */\nexport interface AFSHttpHandlerOptions {\n /** The AFS module to expose */\n module: AFSModule;\n /** Maximum request body size in bytes (default: 10MB) */\n maxBodySize?: number;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /**\n * Token validation configuration (optional)\n * - Not configured: No authorization required (backward compatible)\n * - String: Static token, requests must carry matching Bearer token\n * - Function: Custom validation logic, returns true if valid\n */\n token?: string | TokenValidator;\n}\n\n/**\n * Default handler options\n */\nconst DEFAULT_OPTIONS = {\n maxBodySize: 10 * 1024 * 1024, // 10MB\n timeout: 30000, // 30 seconds\n};\n\n/**\n * Create an AFS HTTP handler function\n *\n * This function creates a pure handler that accepts a Web Standard Request\n * and returns a Web Standard Response. It can be used with any HTTP framework\n * that supports these standards (Hono, Bun, Deno, etc.) or adapted for\n * frameworks like Express and Koa.\n *\n * @param options - Handler options\n * @returns A handler function that processes AFS RPC requests\n *\n * @example\n * ```typescript\n * // With Hono\n * const handler = createAFSHttpHandler({ module: provider });\n * app.post(\"/afs/rpc\", (c) => handler(c.req.raw));\n *\n * // With Bun\n * Bun.serve({\n * fetch(req) {\n * if (url.pathname === \"/afs/rpc\") return handler(req);\n * }\n * });\n * ```\n */\nexport function createAFSHttpHandler(\n options: AFSHttpHandlerOptions,\n): (request: Request) => Promise<Response> {\n const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize, token: tokenConfig } = options;\n\n return async (request: Request): Promise<Response> => {\n try {\n // Validate HTTP method\n if (request.method !== \"POST\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Method not allowed: ${request.method}`),\n 405,\n );\n }\n\n // Validate token if configured\n if (tokenConfig) {\n const authResult = validateToken(request, tokenConfig);\n if (!authResult.valid) {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.UNAUTHORIZED, \"Unauthorized\"),\n 401,\n );\n }\n }\n\n // Check Content-Type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Content-Type must be application/json\"),\n 400,\n );\n }\n\n // Check Content-Length if available\n const contentLength = request.headers.get(\"content-length\");\n if (contentLength && Number.parseInt(contentLength, 10) > maxBodySize) {\n const error = new AFSPayloadTooLargeError(maxBodySize, Number.parseInt(contentLength, 10));\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n\n // Parse request body\n let body: AFSRpcRequest;\n try {\n const text = await request.text();\n if (text.length > maxBodySize) {\n const error = new AFSPayloadTooLargeError(maxBodySize, text.length);\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n body = JSON.parse(text);\n } catch {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Invalid JSON body\"),\n 400,\n );\n }\n\n // Validate request structure\n if (!body || typeof body !== \"object\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Request body must be an object\"),\n 400,\n );\n }\n\n const { method, params } = body;\n\n // Validate method\n if (!method || typeof method !== \"string\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Missing or invalid method\"),\n 400,\n );\n }\n\n if (!isValidRpcMethod(method)) {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Unknown method: ${method}`),\n 400,\n );\n }\n\n // Validate params\n if (!params || typeof params !== \"object\") {\n return createJsonResponse(\n createErrorResponse(AFSErrorCode.RUNTIME_ERROR, \"Missing or invalid params\"),\n 400,\n );\n }\n\n // Execute the RPC method\n const result = await executeRpcMethod(module, method, params);\n return createJsonResponse(createSuccessResponse(result), 200);\n } catch (error) {\n // Handle known AFS errors\n if (error instanceof AFSHttpError) {\n return createJsonResponse(\n createErrorResponse(error.code, error.message, error.details),\n error.httpStatus,\n );\n }\n\n // Handle unknown errors\n const message = error instanceof Error ? error.message : String(error);\n const code = error instanceof Error ? mapErrorToCode(error) : AFSErrorCode.RUNTIME_ERROR;\n return createJsonResponse(createErrorResponse(code, message), 200);\n }\n };\n}\n\n/**\n * Execute an RPC method on the module\n */\nasync function executeRpcMethod(\n module: AFSModule,\n method: AFSRpcMethod,\n params: Record<string, unknown>,\n): Promise<unknown> {\n switch (method) {\n case \"list\": {\n if (!module.list) {\n throw new AFSInvalidRequestError(\"Module does not support list operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.list(path, options as any);\n }\n\n case \"read\": {\n if (!module.read) {\n throw new AFSInvalidRequestError(\"Module does not support read operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.read(path, options as any);\n }\n\n case \"write\": {\n if (!module.write) {\n throw new AFSInvalidRequestError(\"Module does not support write operation\");\n }\n const { path, content, options } = params as {\n path: string;\n content: unknown;\n options?: unknown;\n };\n return await module.write(path, content as any, options as any);\n }\n\n case \"delete\": {\n if (!module.delete) {\n throw new AFSInvalidRequestError(\"Module does not support delete operation\");\n }\n const { path, options } = params as { path: string; options?: unknown };\n return await module.delete(path, options as any);\n }\n\n case \"rename\": {\n if (!module.rename) {\n throw new AFSInvalidRequestError(\"Module does not support rename operation\");\n }\n const { oldPath, newPath, options } = params as {\n oldPath: string;\n newPath: string;\n options?: unknown;\n };\n return await module.rename(oldPath, newPath, options as any);\n }\n\n case \"search\": {\n if (!module.search) {\n throw new AFSInvalidRequestError(\"Module does not support search operation\");\n }\n const { path, query, options } = params as {\n path: string;\n query: string;\n options?: unknown;\n };\n return await module.search(path, query, options as any);\n }\n\n case \"exec\": {\n if (!module.exec) {\n throw new AFSInvalidRequestError(\"Module does not support exec operation\");\n }\n const { path, args, options } = params as {\n path: string;\n args: Record<string, unknown>;\n options?: unknown;\n };\n return await module.exec(path, args, options as any);\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = method;\n throw new AFSInvalidRequestError(`Unknown method: ${_exhaustive}`);\n }\n }\n}\n\n/**\n * Extract Bearer token from Authorization header\n */\nfunction extractBearerToken(request: Request): string | null {\n const authHeader = request.headers.get(\"authorization\");\n if (!authHeader) {\n return null;\n }\n\n // Case-insensitive check for \"Bearer \" prefix\n const lowerHeader = authHeader.toLowerCase();\n if (!lowerHeader.startsWith(\"bearer \")) {\n return null;\n }\n\n // Extract and trim the token\n return authHeader.slice(7).trim();\n}\n\n/**\n * Validate token against configuration\n */\nfunction validateToken(request: Request, tokenConfig: string | TokenValidator): { valid: boolean } {\n const token = extractBearerToken(request);\n\n // No token provided\n if (!token) {\n return { valid: false };\n }\n\n // Static token comparison\n if (typeof tokenConfig === \"string\") {\n return { valid: token === tokenConfig };\n }\n\n // Custom validator function\n try {\n return { valid: tokenConfig(token) };\n } catch {\n // Validator threw an exception, treat as invalid\n return { valid: false };\n }\n}\n\n/**\n * Create a JSON Response with proper headers\n */\nfunction createJsonResponse(body: AFSRpcResponse, status: number): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -16,6 +16,7 @@ exports.AFSNotFoundError = require_errors.AFSNotFoundError;
|
|
|
16
16
|
exports.AFSPayloadTooLargeError = require_errors.AFSPayloadTooLargeError;
|
|
17
17
|
exports.AFSPermissionError = require_errors.AFSPermissionError;
|
|
18
18
|
exports.AFSRuntimeError = require_errors.AFSRuntimeError;
|
|
19
|
+
exports.AFSUnauthorizedError = require_errors.AFSUnauthorizedError;
|
|
19
20
|
exports.DEFAULT_RETRY_OPTIONS = require_retry.DEFAULT_RETRY_OPTIONS;
|
|
20
21
|
exports.VALID_RPC_METHODS = require_protocol.VALID_RPC_METHODS;
|
|
21
22
|
exports.calculateDelay = require_retry.calculateDelay;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,6 @@ import { koaAdapter } from "./adapters/koa.cjs";
|
|
|
3
3
|
import { DEFAULT_RETRY_OPTIONS, RetryOptions, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.cjs";
|
|
4
4
|
import { AFSHttpClient, AFSHttpClientOptions } from "./client.cjs";
|
|
5
5
|
import { AFSErrorCode, AFSRpcError, AFSRpcMethod, AFSRpcParams, AFSRpcRequest, AFSRpcResponse, AFSRpcResults, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod } from "./protocol.cjs";
|
|
6
|
-
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode } from "./errors.cjs";
|
|
7
|
-
import { AFSHttpHandlerOptions, createAFSHttpHandler } from "./handler.cjs";
|
|
8
|
-
export { AFSConflictError, AFSErrorCode, AFSHttpClient, type AFSHttpClientOptions, AFSHttpError, type AFSHttpHandlerOptions, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, type AFSRpcError, type AFSRpcMethod, type AFSRpcParams, type AFSRpcRequest, type AFSRpcResponse, type AFSRpcResults, AFSRuntimeError, DEFAULT_RETRY_OPTIONS, type RetryOptions, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
|
6
|
+
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode } from "./errors.cjs";
|
|
7
|
+
import { AFSHttpHandlerOptions, TokenValidator, createAFSHttpHandler } from "./handler.cjs";
|
|
8
|
+
export { AFSConflictError, AFSErrorCode, AFSHttpClient, type AFSHttpClientOptions, AFSHttpError, type AFSHttpHandlerOptions, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, type AFSRpcError, type AFSRpcMethod, type AFSRpcParams, type AFSRpcRequest, type AFSRpcResponse, type AFSRpcResults, AFSRuntimeError, AFSUnauthorizedError, DEFAULT_RETRY_OPTIONS, type RetryOptions, type TokenValidator, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,6 @@ import { koaAdapter } from "./adapters/koa.mjs";
|
|
|
3
3
|
import { DEFAULT_RETRY_OPTIONS, RetryOptions, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.mjs";
|
|
4
4
|
import { AFSHttpClient, AFSHttpClientOptions } from "./client.mjs";
|
|
5
5
|
import { AFSErrorCode, AFSRpcError, AFSRpcMethod, AFSRpcParams, AFSRpcRequest, AFSRpcResponse, AFSRpcResults, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod } from "./protocol.mjs";
|
|
6
|
-
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode } from "./errors.mjs";
|
|
7
|
-
import { AFSHttpHandlerOptions, createAFSHttpHandler } from "./handler.mjs";
|
|
8
|
-
export { AFSConflictError, AFSErrorCode, AFSHttpClient, type AFSHttpClientOptions, AFSHttpError, type AFSHttpHandlerOptions, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, type AFSRpcError, type AFSRpcMethod, type AFSRpcParams, type AFSRpcRequest, type AFSRpcResponse, type AFSRpcResults, AFSRuntimeError, DEFAULT_RETRY_OPTIONS, type RetryOptions, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
|
6
|
+
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode } from "./errors.mjs";
|
|
7
|
+
import { AFSHttpHandlerOptions, TokenValidator, createAFSHttpHandler } from "./handler.mjs";
|
|
8
|
+
export { AFSConflictError, AFSErrorCode, AFSHttpClient, type AFSHttpClientOptions, AFSHttpError, type AFSHttpHandlerOptions, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, type AFSRpcError, type AFSRpcMethod, type AFSRpcParams, type AFSRpcRequest, type AFSRpcResponse, type AFSRpcResults, AFSRuntimeError, AFSUnauthorizedError, DEFAULT_RETRY_OPTIONS, type RetryOptions, type TokenValidator, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { expressAdapter } from "./adapters/express.mjs";
|
|
2
2
|
import { koaAdapter } from "./adapters/koa.mjs";
|
|
3
3
|
import { AFSErrorCode, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod } from "./protocol.mjs";
|
|
4
|
-
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, mapErrorToCode } from "./errors.mjs";
|
|
4
|
+
import { AFSConflictError, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, mapErrorToCode } from "./errors.mjs";
|
|
5
5
|
import { DEFAULT_RETRY_OPTIONS, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.mjs";
|
|
6
6
|
import { AFSHttpClient } from "./client.mjs";
|
|
7
7
|
import { createAFSHttpHandler } from "./handler.mjs";
|
|
8
8
|
|
|
9
|
-
export { AFSConflictError, AFSErrorCode, AFSHttpClient, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, DEFAULT_RETRY_OPTIONS, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
|
9
|
+
export { AFSConflictError, AFSErrorCode, AFSHttpClient, AFSHttpError, AFSInvalidRequestError, AFSNetworkError, AFSNotFoundError, AFSPayloadTooLargeError, AFSPermissionError, AFSRuntimeError, AFSUnauthorizedError, DEFAULT_RETRY_OPTIONS, VALID_RPC_METHODS, calculateDelay, createAFSHttpHandler, createErrorResponse, createSuccessResponse, expressAdapter, fetchWithRetry, isRetryableError, isRetryableStatus, isValidRpcMethod, koaAdapter, mapErrorToCode, sleep, withRetry };
|
package/dist/protocol.cjs
CHANGED
|
@@ -17,6 +17,8 @@ let AFSErrorCode = /* @__PURE__ */ function(AFSErrorCode) {
|
|
|
17
17
|
AFSErrorCode[AFSErrorCode["PARTIAL"] = 4] = "PARTIAL";
|
|
18
18
|
/** Runtime error */
|
|
19
19
|
AFSErrorCode[AFSErrorCode["RUNTIME_ERROR"] = 5] = "RUNTIME_ERROR";
|
|
20
|
+
/** Unauthorized access */
|
|
21
|
+
AFSErrorCode[AFSErrorCode["UNAUTHORIZED"] = 6] = "UNAUTHORIZED";
|
|
20
22
|
return AFSErrorCode;
|
|
21
23
|
}({});
|
|
22
24
|
/**
|
package/dist/protocol.d.cts
CHANGED
|
@@ -24,7 +24,7 @@ interface AFSRpcResponse<T = unknown> {
|
|
|
24
24
|
* RPC error object
|
|
25
25
|
*/
|
|
26
26
|
interface AFSRpcError {
|
|
27
|
-
/** CLI error code (0-
|
|
27
|
+
/** CLI error code (0-6), compatible with AFS CLI */
|
|
28
28
|
code: AFSErrorCode;
|
|
29
29
|
/** Human-readable error message */
|
|
30
30
|
message: string;
|
|
@@ -48,6 +48,8 @@ declare enum AFSErrorCode {
|
|
|
48
48
|
PARTIAL = 4,
|
|
49
49
|
/** Runtime error */
|
|
50
50
|
RUNTIME_ERROR = 5,
|
|
51
|
+
/** Unauthorized access */
|
|
52
|
+
UNAUTHORIZED = 6,
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* Parameter types for each RPC method
|
package/dist/protocol.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.cts","names":[],"sources":["../src/protocol.ts"],"mappings":";;;;AAqBA;AAKA;KALY,YAAA;AAAA;AAKZ;;AALY,UAKK,aAAA,WAAwB,YAAA,GAAe,YAAA;EAAA,MAAA,EAC9C,CAAA;EAAA,MAAA,EACA,YAAA,CAAa,CAAA;AAAA;AAAA;;AAMvB;AANuB,UAMN,cAAA;EAAA,OAAA;EAAA,IAAA,GAER,CAAA;EAAA,KAAA,GACC,WAAA;AAAA;AAAA;AAMV;AAaA;AAnBU,UAMO,WAAA;EAAA;EAAA,IAAA,EAET,YAAA;EAAA;EAAA,OAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAWR;
|
|
1
|
+
{"version":3,"file":"protocol.d.cts","names":[],"sources":["../src/protocol.ts"],"mappings":";;;;AAqBA;AAKA;KALY,YAAA;AAAA;AAKZ;;AALY,UAKK,aAAA,WAAwB,YAAA,GAAe,YAAA;EAAA,MAAA,EAC9C,CAAA;EAAA,MAAA,EACA,YAAA,CAAa,CAAA;AAAA;AAAA;;AAMvB;AANuB,UAMN,cAAA;EAAA,OAAA;EAAA,IAAA,GAER,CAAA;EAAA,KAAA,GACC,WAAA;AAAA;AAAA;AAMV;AAaA;AAnBU,UAMO,WAAA;EAAA;EAAA,IAAA,EAET,YAAA;EAAA;EAAA,OAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAWR;AAoBA;;AA/BQ,aAWI,YAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;EAAA;EAAA,iBAAA;EAAA;EAAA,QAAA;EAAA;EAAA,OAAA;EAAA;EAAA,aAAA;EAAA;EAAA,YAAA;AAAA;AAAA;AAoBZ;;AApBY,UAoBK,YAAA;EAAA,IAAA;IAAA,IAAA;IAAA,OAAA,GAGH,cAAA;EAAA;EAAA,IAAA;IAAA,IAAA;IAAA,OAAA,GAIA,cAAA;EAAA;EAAA,KAAA;IAAA,IAAA;IAAA,OAAA,EAID,oBAAA;IAAA,OAAA,GACC,eAAA;EAAA;EAAA,MAAA;IAAA,IAAA;IAAA,OAAA,GAIA,gBAAA;EAAA;EAAA,MAAA;IAAA,OAAA;IAAA,OAAA;IAAA,OAAA,GAKA,gBAAA;EAAA;EAAA,MAAA;IAAA,IAAA;IAAA,KAAA;IAAA,OAAA,GAKA,gBAAA;EAAA;EAAA,IAAA;IAAA,IAAA;IAAA,IAAA,EAIJ,MAAA;IAAA,OAAA,GACI,cAAA;EAAA;AAAA;AAAA;;AAOd;AAPc,UAOG,aAAA;EAAA,IAAA,EACT,aAAA;EAAA,IAAA,EACA,aAAA;EAAA,KAAA,EACC,cAAA;EAAA,MAAA,EACC,eAAA;EAAA,MAAA,EACA,eAAA;EAAA,MAAA,EACA,eAAA;EAAA,IAAA,EACF,aAAA;AAAA;AAAA;;AAMR;AANQ,cAMK,iBAAA,EAAmB,GAAA,CAAI,YAAA;AAAA;AAapC;AAOA;AApBoC,iBAapB,gBAAA,CAAA,MAAA,WAAA,MAAA,IAA4C,YAAA;AAAA;AAO5D;;AAP4D,iBAO5C,qBAAA,GAAA,CAAA,IAAA,EAA+B,CAAA,GAAI,cAAA,CAAe,CAAA;AAAA;;;AAAA,iBAUlD,mBAAA,CAAA,IAAA,EACR,YAAA,EAAA,OAAA,UAAA,OAAA,aAGL,cAAA"}
|
package/dist/protocol.d.mts
CHANGED
|
@@ -24,7 +24,7 @@ interface AFSRpcResponse<T = unknown> {
|
|
|
24
24
|
* RPC error object
|
|
25
25
|
*/
|
|
26
26
|
interface AFSRpcError {
|
|
27
|
-
/** CLI error code (0-
|
|
27
|
+
/** CLI error code (0-6), compatible with AFS CLI */
|
|
28
28
|
code: AFSErrorCode;
|
|
29
29
|
/** Human-readable error message */
|
|
30
30
|
message: string;
|
|
@@ -48,6 +48,8 @@ declare enum AFSErrorCode {
|
|
|
48
48
|
PARTIAL = 4,
|
|
49
49
|
/** Runtime error */
|
|
50
50
|
RUNTIME_ERROR = 5,
|
|
51
|
+
/** Unauthorized access */
|
|
52
|
+
UNAUTHORIZED = 6,
|
|
51
53
|
}
|
|
52
54
|
/**
|
|
53
55
|
* Parameter types for each RPC method
|
package/dist/protocol.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.mts","names":[],"sources":["../src/protocol.ts"],"mappings":";;;;AAqBA;AAKA;KALY,YAAA;AAAA;AAKZ;;AALY,UAKK,aAAA,WAAwB,YAAA,GAAe,YAAA;EAAA,MAAA,EAC9C,CAAA;EAAA,MAAA,EACA,YAAA,CAAa,CAAA;AAAA;AAAA;;AAMvB;AANuB,UAMN,cAAA;EAAA,OAAA;EAAA,IAAA,GAER,CAAA;EAAA,KAAA,GACC,WAAA;AAAA;AAAA;AAMV;AAaA;AAnBU,UAMO,WAAA;EAAA;EAAA,IAAA,EAET,YAAA;EAAA;EAAA,OAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAWR;
|
|
1
|
+
{"version":3,"file":"protocol.d.mts","names":[],"sources":["../src/protocol.ts"],"mappings":";;;;AAqBA;AAKA;KALY,YAAA;AAAA;AAKZ;;AALY,UAKK,aAAA,WAAwB,YAAA,GAAe,YAAA;EAAA,MAAA,EAC9C,CAAA;EAAA,MAAA,EACA,YAAA,CAAa,CAAA;AAAA;AAAA;;AAMvB;AANuB,UAMN,cAAA;EAAA,OAAA;EAAA,IAAA,GAER,CAAA;EAAA,KAAA,GACC,WAAA;AAAA;AAAA;AAMV;AAaA;AAnBU,UAMO,WAAA;EAAA;EAAA,IAAA,EAET,YAAA;EAAA;EAAA,OAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAWR;AAoBA;;AA/BQ,aAWI,YAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;EAAA;EAAA,iBAAA;EAAA;EAAA,QAAA;EAAA;EAAA,OAAA;EAAA;EAAA,aAAA;EAAA;EAAA,YAAA;AAAA;AAAA;AAoBZ;;AApBY,UAoBK,YAAA;EAAA,IAAA;IAAA,IAAA;IAAA,OAAA,GAGH,cAAA;EAAA;EAAA,IAAA;IAAA,IAAA;IAAA,OAAA,GAIA,cAAA;EAAA;EAAA,KAAA;IAAA,IAAA;IAAA,OAAA,EAID,oBAAA;IAAA,OAAA,GACC,eAAA;EAAA;EAAA,MAAA;IAAA,IAAA;IAAA,OAAA,GAIA,gBAAA;EAAA;EAAA,MAAA;IAAA,OAAA;IAAA,OAAA;IAAA,OAAA,GAKA,gBAAA;EAAA;EAAA,MAAA;IAAA,IAAA;IAAA,KAAA;IAAA,OAAA,GAKA,gBAAA;EAAA;EAAA,IAAA;IAAA,IAAA;IAAA,IAAA,EAIJ,MAAA;IAAA,OAAA,GACI,cAAA;EAAA;AAAA;AAAA;;AAOd;AAPc,UAOG,aAAA;EAAA,IAAA,EACT,aAAA;EAAA,IAAA,EACA,aAAA;EAAA,KAAA,EACC,cAAA;EAAA,MAAA,EACC,eAAA;EAAA,MAAA,EACA,eAAA;EAAA,MAAA,EACA,eAAA;EAAA,IAAA,EACF,aAAA;AAAA;AAAA;;AAMR;AANQ,cAMK,iBAAA,EAAmB,GAAA,CAAI,YAAA;AAAA;AAapC;AAOA;AApBoC,iBAapB,gBAAA,CAAA,MAAA,WAAA,MAAA,IAA4C,YAAA;AAAA;AAO5D;;AAP4D,iBAO5C,qBAAA,GAAA,CAAA,IAAA,EAA+B,CAAA,GAAI,cAAA,CAAe,CAAA;AAAA;;;AAAA,iBAUlD,mBAAA,CAAA,IAAA,EACR,YAAA,EAAA,OAAA,UAAA,OAAA,aAGL,cAAA"}
|
package/dist/protocol.mjs
CHANGED
|
@@ -16,6 +16,8 @@ let AFSErrorCode = /* @__PURE__ */ function(AFSErrorCode) {
|
|
|
16
16
|
AFSErrorCode[AFSErrorCode["PARTIAL"] = 4] = "PARTIAL";
|
|
17
17
|
/** Runtime error */
|
|
18
18
|
AFSErrorCode[AFSErrorCode["RUNTIME_ERROR"] = 5] = "RUNTIME_ERROR";
|
|
19
|
+
/** Unauthorized access */
|
|
20
|
+
AFSErrorCode[AFSErrorCode["UNAUTHORIZED"] = 6] = "UNAUTHORIZED";
|
|
19
21
|
return AFSErrorCode;
|
|
20
22
|
}({});
|
|
21
23
|
/**
|
package/dist/protocol.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.mjs","names":[],"sources":["../src/protocol.ts"],"sourcesContent":["import type {\n AFSDeleteOptions,\n AFSDeleteResult,\n AFSExecOptions,\n AFSExecResult,\n AFSListOptions,\n AFSListResult,\n AFSReadOptions,\n AFSReadResult,\n AFSRenameOptions,\n AFSRenameResult,\n AFSSearchOptions,\n AFSSearchResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n} from \"@aigne/afs\";\n\n/**\n * AFS HTTP RPC method names\n */\nexport type AFSRpcMethod = \"list\" | \"read\" | \"write\" | \"delete\" | \"rename\" | \"search\" | \"exec\";\n\n/**\n * RPC request body\n */\nexport interface AFSRpcRequest<M extends AFSRpcMethod = AFSRpcMethod> {\n method: M;\n params: AFSRpcParams[M];\n}\n\n/**\n * RPC response body\n */\nexport interface AFSRpcResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: AFSRpcError;\n}\n\n/**\n * RPC error object\n */\nexport interface AFSRpcError {\n /** CLI error code (0-
|
|
1
|
+
{"version":3,"file":"protocol.mjs","names":[],"sources":["../src/protocol.ts"],"sourcesContent":["import type {\n AFSDeleteOptions,\n AFSDeleteResult,\n AFSExecOptions,\n AFSExecResult,\n AFSListOptions,\n AFSListResult,\n AFSReadOptions,\n AFSReadResult,\n AFSRenameOptions,\n AFSRenameResult,\n AFSSearchOptions,\n AFSSearchResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n} from \"@aigne/afs\";\n\n/**\n * AFS HTTP RPC method names\n */\nexport type AFSRpcMethod = \"list\" | \"read\" | \"write\" | \"delete\" | \"rename\" | \"search\" | \"exec\";\n\n/**\n * RPC request body\n */\nexport interface AFSRpcRequest<M extends AFSRpcMethod = AFSRpcMethod> {\n method: M;\n params: AFSRpcParams[M];\n}\n\n/**\n * RPC response body\n */\nexport interface AFSRpcResponse<T = unknown> {\n success: boolean;\n data?: T;\n error?: AFSRpcError;\n}\n\n/**\n * RPC error object\n */\nexport interface AFSRpcError {\n /** CLI error code (0-6), compatible with AFS CLI */\n code: AFSErrorCode;\n /** Human-readable error message */\n message: string;\n /** Additional error details */\n details?: unknown;\n}\n\n/**\n * CLI-compatible error codes\n * @see https://github.com/arcblock/afs/blob/main/intent/specs/afs-cli-spec.md\n */\nexport enum AFSErrorCode {\n /** Operation successful */\n OK = 0,\n /** Path not found */\n NOT_FOUND = 1,\n /** Permission denied (including readonly mode) */\n PERMISSION_DENIED = 2,\n /** Concurrent modification conflict */\n CONFLICT = 3,\n /** Partial success */\n PARTIAL = 4,\n /** Runtime error */\n RUNTIME_ERROR = 5,\n /** Unauthorized access */\n UNAUTHORIZED = 6,\n}\n\n/**\n * Parameter types for each RPC method\n */\nexport interface AFSRpcParams {\n list: {\n path: string;\n options?: AFSListOptions;\n };\n read: {\n path: string;\n options?: AFSReadOptions;\n };\n write: {\n path: string;\n content: AFSWriteEntryPayload;\n options?: AFSWriteOptions;\n };\n delete: {\n path: string;\n options?: AFSDeleteOptions;\n };\n rename: {\n oldPath: string;\n newPath: string;\n options?: AFSRenameOptions;\n };\n search: {\n path: string;\n query: string;\n options?: AFSSearchOptions;\n };\n exec: {\n path: string;\n args: Record<string, unknown>;\n options?: AFSExecOptions;\n };\n}\n\n/**\n * Result types for each RPC method\n */\nexport interface AFSRpcResults {\n list: AFSListResult;\n read: AFSReadResult;\n write: AFSWriteResult;\n delete: AFSDeleteResult;\n rename: AFSRenameResult;\n search: AFSSearchResult;\n exec: AFSExecResult;\n}\n\n/**\n * Valid RPC methods set for validation\n */\nexport const VALID_RPC_METHODS: Set<AFSRpcMethod> = new Set([\n \"list\",\n \"read\",\n \"write\",\n \"delete\",\n \"rename\",\n \"search\",\n \"exec\",\n]);\n\n/**\n * Check if a string is a valid RPC method\n */\nexport function isValidRpcMethod(method: string): method is AFSRpcMethod {\n return VALID_RPC_METHODS.has(method as AFSRpcMethod);\n}\n\n/**\n * Create a success response\n */\nexport function createSuccessResponse<T>(data: T): AFSRpcResponse<T> {\n return {\n success: true,\n data,\n };\n}\n\n/**\n * Create an error response\n */\nexport function createErrorResponse(\n code: AFSErrorCode,\n message: string,\n details?: unknown,\n): AFSRpcResponse<never> {\n return {\n success: false,\n error: {\n code,\n message,\n details,\n },\n };\n}\n"],"mappings":";;;;;AAwDA,IAAY,sDAAL;;AAEL;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;;;;;AAyDF,MAAa,oBAAuC,IAAI,IAAI;CAC1D;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,SAAgB,iBAAiB,QAAwC;AACvE,QAAO,kBAAkB,IAAI,OAAuB;;;;;AAMtD,SAAgB,sBAAyB,MAA4B;AACnE,QAAO;EACL,SAAS;EACT;EACD;;;;;AAMH,SAAgB,oBACd,MACA,SACA,SACuB;AACvB,QAAO;EACL,SAAS;EACT,OAAO;GACL;GACA;GACA;GACD;EACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/afs-http",
|
|
3
|
-
"version": "1.11.0-beta.
|
|
3
|
+
"version": "1.11.0-beta.5",
|
|
4
4
|
"description": "AIGNE AFS HTTP transport provider for remote AFS access",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"zod": "^3.25.67",
|
|
37
|
-
"@aigne/afs": "^1.11.0-beta.
|
|
37
|
+
"@aigne/afs": "^1.11.0-beta.5"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/bun": "^1.3.6",
|