@aigne/afs-http 1.11.0-beta.3
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/LICENSE.md +26 -0
- package/README.md +318 -0
- package/dist/adapters/express.cjs +74 -0
- package/dist/adapters/express.d.cts +56 -0
- package/dist/adapters/express.d.cts.map +1 -0
- package/dist/adapters/express.d.mts +56 -0
- package/dist/adapters/express.d.mts.map +1 -0
- package/dist/adapters/express.mjs +74 -0
- package/dist/adapters/express.mjs.map +1 -0
- package/dist/adapters/koa.cjs +73 -0
- package/dist/adapters/koa.d.cts +56 -0
- package/dist/adapters/koa.d.cts.map +1 -0
- package/dist/adapters/koa.d.mts +56 -0
- package/dist/adapters/koa.d.mts.map +1 -0
- package/dist/adapters/koa.mjs +73 -0
- package/dist/adapters/koa.mjs.map +1 -0
- package/dist/client.cjs +143 -0
- package/dist/client.d.cts +70 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +70 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +144 -0
- package/dist/client.mjs.map +1 -0
- package/dist/errors.cjs +105 -0
- package/dist/errors.d.cts +63 -0
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.mts +63 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +98 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/handler.cjs +126 -0
- package/dist/handler.d.cts +43 -0
- package/dist/handler.d.cts.map +1 -0
- package/dist/handler.d.mts +43 -0
- package/dist/handler.d.mts.map +1 -0
- package/dist/handler.mjs +127 -0
- package/dist/handler.mjs.map +1 -0
- package/dist/index.cjs +33 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +9 -0
- package/dist/protocol.cjs +68 -0
- package/dist/protocol.d.cts +119 -0
- package/dist/protocol.d.cts.map +1 -0
- package/dist/protocol.d.mts +119 -0
- package/dist/protocol.d.mts.map +1 -0
- package/dist/protocol.mjs +64 -0
- package/dist/protocol.mjs.map +1 -0
- package/dist/retry.cjs +111 -0
- package/dist/retry.d.cts +57 -0
- package/dist/retry.d.cts.map +1 -0
- package/dist/retry.d.mts +57 -0
- package/dist/retry.d.mts.map +1 -0
- package/dist/retry.mjs +105 -0
- package/dist/retry.mjs.map +1 -0
- package/package.json +55 -0
package/dist/handler.mjs
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { AFSErrorCode, createErrorResponse, createSuccessResponse, isValidRpcMethod } from "./protocol.mjs";
|
|
2
|
+
import { AFSHttpError, AFSInvalidRequestError, AFSPayloadTooLargeError, mapErrorToCode } from "./errors.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/handler.ts
|
|
5
|
+
/**
|
|
6
|
+
* Default handler options
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_OPTIONS = {
|
|
9
|
+
maxBodySize: 10 * 1024 * 1024,
|
|
10
|
+
timeout: 3e4
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Create an AFS HTTP handler function
|
|
14
|
+
*
|
|
15
|
+
* This function creates a pure handler that accepts a Web Standard Request
|
|
16
|
+
* and returns a Web Standard Response. It can be used with any HTTP framework
|
|
17
|
+
* that supports these standards (Hono, Bun, Deno, etc.) or adapted for
|
|
18
|
+
* frameworks like Express and Koa.
|
|
19
|
+
*
|
|
20
|
+
* @param options - Handler options
|
|
21
|
+
* @returns A handler function that processes AFS RPC requests
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // With Hono
|
|
26
|
+
* const handler = createAFSHttpHandler({ module: provider });
|
|
27
|
+
* app.post("/afs/rpc", (c) => handler(c.req.raw));
|
|
28
|
+
*
|
|
29
|
+
* // With Bun
|
|
30
|
+
* Bun.serve({
|
|
31
|
+
* fetch(req) {
|
|
32
|
+
* if (url.pathname === "/afs/rpc") return handler(req);
|
|
33
|
+
* }
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function createAFSHttpHandler(options) {
|
|
38
|
+
const { module, maxBodySize = DEFAULT_OPTIONS.maxBodySize } = options;
|
|
39
|
+
return async (request) => {
|
|
40
|
+
try {
|
|
41
|
+
if (request.method !== "POST") return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Method not allowed: ${request.method}`), 405);
|
|
42
|
+
if (!request.headers.get("content-type")?.includes("application/json")) return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Content-Type must be application/json"), 400);
|
|
43
|
+
const contentLength = request.headers.get("content-length");
|
|
44
|
+
if (contentLength && Number.parseInt(contentLength, 10) > maxBodySize) {
|
|
45
|
+
const error = new AFSPayloadTooLargeError(maxBodySize, Number.parseInt(contentLength, 10));
|
|
46
|
+
return createJsonResponse(createErrorResponse(error.code, error.message, error.details), error.httpStatus);
|
|
47
|
+
}
|
|
48
|
+
let body;
|
|
49
|
+
try {
|
|
50
|
+
const text = await request.text();
|
|
51
|
+
if (text.length > maxBodySize) {
|
|
52
|
+
const error = new AFSPayloadTooLargeError(maxBodySize, text.length);
|
|
53
|
+
return createJsonResponse(createErrorResponse(error.code, error.message, error.details), error.httpStatus);
|
|
54
|
+
}
|
|
55
|
+
body = JSON.parse(text);
|
|
56
|
+
} catch {
|
|
57
|
+
return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Invalid JSON body"), 400);
|
|
58
|
+
}
|
|
59
|
+
if (!body || typeof body !== "object") return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Request body must be an object"), 400);
|
|
60
|
+
const { method, params } = body;
|
|
61
|
+
if (!method || typeof method !== "string") return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Missing or invalid method"), 400);
|
|
62
|
+
if (!isValidRpcMethod(method)) return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, `Unknown method: ${method}`), 400);
|
|
63
|
+
if (!params || typeof params !== "object") return createJsonResponse(createErrorResponse(AFSErrorCode.RUNTIME_ERROR, "Missing or invalid params"), 400);
|
|
64
|
+
return createJsonResponse(createSuccessResponse(await executeRpcMethod(module, method, params)), 200);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error instanceof AFSHttpError) return createJsonResponse(createErrorResponse(error.code, error.message, error.details), error.httpStatus);
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
return createJsonResponse(createErrorResponse(error instanceof Error ? mapErrorToCode(error) : AFSErrorCode.RUNTIME_ERROR, message), 200);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Execute an RPC method on the module
|
|
74
|
+
*/
|
|
75
|
+
async function executeRpcMethod(module, method, params) {
|
|
76
|
+
switch (method) {
|
|
77
|
+
case "list": {
|
|
78
|
+
if (!module.list) throw new AFSInvalidRequestError("Module does not support list operation");
|
|
79
|
+
const { path, options } = params;
|
|
80
|
+
return await module.list(path, options);
|
|
81
|
+
}
|
|
82
|
+
case "read": {
|
|
83
|
+
if (!module.read) throw new AFSInvalidRequestError("Module does not support read operation");
|
|
84
|
+
const { path, options } = params;
|
|
85
|
+
return await module.read(path, options);
|
|
86
|
+
}
|
|
87
|
+
case "write": {
|
|
88
|
+
if (!module.write) throw new AFSInvalidRequestError("Module does not support write operation");
|
|
89
|
+
const { path, content, options } = params;
|
|
90
|
+
return await module.write(path, content, options);
|
|
91
|
+
}
|
|
92
|
+
case "delete": {
|
|
93
|
+
if (!module.delete) throw new AFSInvalidRequestError("Module does not support delete operation");
|
|
94
|
+
const { path, options } = params;
|
|
95
|
+
return await module.delete(path, options);
|
|
96
|
+
}
|
|
97
|
+
case "rename": {
|
|
98
|
+
if (!module.rename) throw new AFSInvalidRequestError("Module does not support rename operation");
|
|
99
|
+
const { oldPath, newPath, options } = params;
|
|
100
|
+
return await module.rename(oldPath, newPath, options);
|
|
101
|
+
}
|
|
102
|
+
case "search": {
|
|
103
|
+
if (!module.search) throw new AFSInvalidRequestError("Module does not support search operation");
|
|
104
|
+
const { path, query, options } = params;
|
|
105
|
+
return await module.search(path, query, options);
|
|
106
|
+
}
|
|
107
|
+
case "exec": {
|
|
108
|
+
if (!module.exec) throw new AFSInvalidRequestError("Module does not support exec operation");
|
|
109
|
+
const { path, args, options } = params;
|
|
110
|
+
return await module.exec(path, args, options);
|
|
111
|
+
}
|
|
112
|
+
default: throw new AFSInvalidRequestError(`Unknown method: ${method}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Create a JSON Response with proper headers
|
|
117
|
+
*/
|
|
118
|
+
function createJsonResponse(body, status) {
|
|
119
|
+
return new Response(JSON.stringify(body), {
|
|
120
|
+
status,
|
|
121
|
+
headers: { "Content-Type": "application/json" }
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { createAFSHttpHandler };
|
|
127
|
+
//# sourceMappingURL=handler.mjs.map
|
|
@@ -0,0 +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":";;;;;;;AAgCA,MAAM,kBAAkB;CACtB,aAAa,KAAK,OAAO;CACzB,SAAS;CACV;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BD,SAAgB,qBACd,SACyC;CACzC,MAAM,EAAE,QAAQ,cAAc,gBAAgB,gBAAgB;AAE9D,QAAO,OAAO,YAAwC;AACpD,MAAI;AAEF,OAAI,QAAQ,WAAW,OACrB,QAAO,mBACL,oBAAoB,aAAa,eAAe,uBAAuB,QAAQ,SAAS,EACxF,IACD;AAKH,OAAI,CADgB,QAAQ,QAAQ,IAAI,eAAe,EACrC,SAAS,mBAAmB,CAC5C,QAAO,mBACL,oBAAoB,aAAa,eAAe,wCAAwC,EACxF,IACD;GAIH,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,OAAI,iBAAiB,OAAO,SAAS,eAAe,GAAG,GAAG,aAAa;IACrE,MAAM,QAAQ,IAAI,wBAAwB,aAAa,OAAO,SAAS,eAAe,GAAG,CAAC;AAC1F,WAAO,mBACL,oBAAoB,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,EAC7D,MAAM,WACP;;GAIH,IAAI;AACJ,OAAI;IACF,MAAM,OAAO,MAAM,QAAQ,MAAM;AACjC,QAAI,KAAK,SAAS,aAAa;KAC7B,MAAM,QAAQ,IAAI,wBAAwB,aAAa,KAAK,OAAO;AACnE,YAAO,mBACL,oBAAoB,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,EAC7D,MAAM,WACP;;AAEH,WAAO,KAAK,MAAM,KAAK;WACjB;AACN,WAAO,mBACL,oBAAoB,aAAa,eAAe,oBAAoB,EACpE,IACD;;AAIH,OAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,QAAO,mBACL,oBAAoB,aAAa,eAAe,iCAAiC,EACjF,IACD;GAGH,MAAM,EAAE,QAAQ,WAAW;AAG3B,OAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,QAAO,mBACL,oBAAoB,aAAa,eAAe,4BAA4B,EAC5E,IACD;AAGH,OAAI,CAAC,iBAAiB,OAAO,CAC3B,QAAO,mBACL,oBAAoB,aAAa,eAAe,mBAAmB,SAAS,EAC5E,IACD;AAIH,OAAI,CAAC,UAAU,OAAO,WAAW,SAC/B,QAAO,mBACL,oBAAoB,aAAa,eAAe,4BAA4B,EAC5E,IACD;AAKH,UAAO,mBAAmB,sBADX,MAAM,iBAAiB,QAAQ,QAAQ,OAAO,CACN,EAAE,IAAI;WACtD,OAAO;AAEd,OAAI,iBAAiB,aACnB,QAAO,mBACL,oBAAoB,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ,EAC7D,MAAM,WACP;GAIH,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAEtE,UAAO,mBAAmB,oBADb,iBAAiB,QAAQ,eAAe,MAAM,GAAG,aAAa,eACvB,QAAQ,EAAE,IAAI;;;;;;;AAQxE,eAAe,iBACb,QACA,QACA,QACkB;AAClB,SAAQ,QAAR;EACE,KAAK,QAAQ;AACX,OAAI,CAAC,OAAO,KACV,OAAM,IAAI,uBAAuB,yCAAyC;GAE5E,MAAM,EAAE,MAAM,YAAY;AAC1B,UAAO,MAAM,OAAO,KAAK,MAAM,QAAe;;EAGhD,KAAK,QAAQ;AACX,OAAI,CAAC,OAAO,KACV,OAAM,IAAI,uBAAuB,yCAAyC;GAE5E,MAAM,EAAE,MAAM,YAAY;AAC1B,UAAO,MAAM,OAAO,KAAK,MAAM,QAAe;;EAGhD,KAAK,SAAS;AACZ,OAAI,CAAC,OAAO,MACV,OAAM,IAAI,uBAAuB,0CAA0C;GAE7E,MAAM,EAAE,MAAM,SAAS,YAAY;AAKnC,UAAO,MAAM,OAAO,MAAM,MAAM,SAAgB,QAAe;;EAGjE,KAAK,UAAU;AACb,OAAI,CAAC,OAAO,OACV,OAAM,IAAI,uBAAuB,2CAA2C;GAE9E,MAAM,EAAE,MAAM,YAAY;AAC1B,UAAO,MAAM,OAAO,OAAO,MAAM,QAAe;;EAGlD,KAAK,UAAU;AACb,OAAI,CAAC,OAAO,OACV,OAAM,IAAI,uBAAuB,2CAA2C;GAE9E,MAAM,EAAE,SAAS,SAAS,YAAY;AAKtC,UAAO,MAAM,OAAO,OAAO,SAAS,SAAS,QAAe;;EAG9D,KAAK,UAAU;AACb,OAAI,CAAC,OAAO,OACV,OAAM,IAAI,uBAAuB,2CAA2C;GAE9E,MAAM,EAAE,MAAM,OAAO,YAAY;AAKjC,UAAO,MAAM,OAAO,OAAO,MAAM,OAAO,QAAe;;EAGzD,KAAK,QAAQ;AACX,OAAI,CAAC,OAAO,KACV,OAAM,IAAI,uBAAuB,yCAAyC;GAE5E,MAAM,EAAE,MAAM,MAAM,YAAY;AAKhC,UAAO,MAAM,OAAO,KAAK,MAAM,MAAM,QAAe;;EAGtD,QAGE,OAAM,IAAI,uBAAuB,mBADN,SACuC;;;;;;AAQxE,SAAS,mBAAmB,MAAsB,QAA0B;AAC1E,QAAO,IAAI,SAAS,KAAK,UAAU,KAAK,EAAE;EACxC;EACA,SAAS,EACP,gBAAgB,oBACjB;EACF,CAAC"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_express = require('./adapters/express.cjs');
|
|
2
|
+
const require_koa = require('./adapters/koa.cjs');
|
|
3
|
+
const require_protocol = require('./protocol.cjs');
|
|
4
|
+
const require_errors = require('./errors.cjs');
|
|
5
|
+
const require_retry = require('./retry.cjs');
|
|
6
|
+
const require_client = require('./client.cjs');
|
|
7
|
+
const require_handler = require('./handler.cjs');
|
|
8
|
+
|
|
9
|
+
exports.AFSConflictError = require_errors.AFSConflictError;
|
|
10
|
+
exports.AFSErrorCode = require_protocol.AFSErrorCode;
|
|
11
|
+
exports.AFSHttpClient = require_client.AFSHttpClient;
|
|
12
|
+
exports.AFSHttpError = require_errors.AFSHttpError;
|
|
13
|
+
exports.AFSInvalidRequestError = require_errors.AFSInvalidRequestError;
|
|
14
|
+
exports.AFSNetworkError = require_errors.AFSNetworkError;
|
|
15
|
+
exports.AFSNotFoundError = require_errors.AFSNotFoundError;
|
|
16
|
+
exports.AFSPayloadTooLargeError = require_errors.AFSPayloadTooLargeError;
|
|
17
|
+
exports.AFSPermissionError = require_errors.AFSPermissionError;
|
|
18
|
+
exports.AFSRuntimeError = require_errors.AFSRuntimeError;
|
|
19
|
+
exports.DEFAULT_RETRY_OPTIONS = require_retry.DEFAULT_RETRY_OPTIONS;
|
|
20
|
+
exports.VALID_RPC_METHODS = require_protocol.VALID_RPC_METHODS;
|
|
21
|
+
exports.calculateDelay = require_retry.calculateDelay;
|
|
22
|
+
exports.createAFSHttpHandler = require_handler.createAFSHttpHandler;
|
|
23
|
+
exports.createErrorResponse = require_protocol.createErrorResponse;
|
|
24
|
+
exports.createSuccessResponse = require_protocol.createSuccessResponse;
|
|
25
|
+
exports.expressAdapter = require_express.expressAdapter;
|
|
26
|
+
exports.fetchWithRetry = require_retry.fetchWithRetry;
|
|
27
|
+
exports.isRetryableError = require_retry.isRetryableError;
|
|
28
|
+
exports.isRetryableStatus = require_retry.isRetryableStatus;
|
|
29
|
+
exports.isValidRpcMethod = require_protocol.isValidRpcMethod;
|
|
30
|
+
exports.koaAdapter = require_koa.koaAdapter;
|
|
31
|
+
exports.mapErrorToCode = require_errors.mapErrorToCode;
|
|
32
|
+
exports.sleep = require_retry.sleep;
|
|
33
|
+
exports.withRetry = require_retry.withRetry;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { expressAdapter } from "./adapters/express.cjs";
|
|
2
|
+
import { koaAdapter } from "./adapters/koa.cjs";
|
|
3
|
+
import { DEFAULT_RETRY_OPTIONS, RetryOptions, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.cjs";
|
|
4
|
+
import { AFSHttpClient, AFSHttpClientOptions } from "./client.cjs";
|
|
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 };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { expressAdapter } from "./adapters/express.mjs";
|
|
2
|
+
import { koaAdapter } from "./adapters/koa.mjs";
|
|
3
|
+
import { DEFAULT_RETRY_OPTIONS, RetryOptions, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.mjs";
|
|
4
|
+
import { AFSHttpClient, AFSHttpClientOptions } from "./client.mjs";
|
|
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 };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { expressAdapter } from "./adapters/express.mjs";
|
|
2
|
+
import { koaAdapter } from "./adapters/koa.mjs";
|
|
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";
|
|
5
|
+
import { DEFAULT_RETRY_OPTIONS, calculateDelay, fetchWithRetry, isRetryableError, isRetryableStatus, sleep, withRetry } from "./retry.mjs";
|
|
6
|
+
import { AFSHttpClient } from "./client.mjs";
|
|
7
|
+
import { createAFSHttpHandler } from "./handler.mjs";
|
|
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 };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/protocol.ts
|
|
3
|
+
/**
|
|
4
|
+
* CLI-compatible error codes
|
|
5
|
+
* @see https://github.com/arcblock/afs/blob/main/intent/specs/afs-cli-spec.md
|
|
6
|
+
*/
|
|
7
|
+
let AFSErrorCode = /* @__PURE__ */ function(AFSErrorCode) {
|
|
8
|
+
/** Operation successful */
|
|
9
|
+
AFSErrorCode[AFSErrorCode["OK"] = 0] = "OK";
|
|
10
|
+
/** Path not found */
|
|
11
|
+
AFSErrorCode[AFSErrorCode["NOT_FOUND"] = 1] = "NOT_FOUND";
|
|
12
|
+
/** Permission denied (including readonly mode) */
|
|
13
|
+
AFSErrorCode[AFSErrorCode["PERMISSION_DENIED"] = 2] = "PERMISSION_DENIED";
|
|
14
|
+
/** Concurrent modification conflict */
|
|
15
|
+
AFSErrorCode[AFSErrorCode["CONFLICT"] = 3] = "CONFLICT";
|
|
16
|
+
/** Partial success */
|
|
17
|
+
AFSErrorCode[AFSErrorCode["PARTIAL"] = 4] = "PARTIAL";
|
|
18
|
+
/** Runtime error */
|
|
19
|
+
AFSErrorCode[AFSErrorCode["RUNTIME_ERROR"] = 5] = "RUNTIME_ERROR";
|
|
20
|
+
return AFSErrorCode;
|
|
21
|
+
}({});
|
|
22
|
+
/**
|
|
23
|
+
* Valid RPC methods set for validation
|
|
24
|
+
*/
|
|
25
|
+
const VALID_RPC_METHODS = new Set([
|
|
26
|
+
"list",
|
|
27
|
+
"read",
|
|
28
|
+
"write",
|
|
29
|
+
"delete",
|
|
30
|
+
"rename",
|
|
31
|
+
"search",
|
|
32
|
+
"exec"
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* Check if a string is a valid RPC method
|
|
36
|
+
*/
|
|
37
|
+
function isValidRpcMethod(method) {
|
|
38
|
+
return VALID_RPC_METHODS.has(method);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a success response
|
|
42
|
+
*/
|
|
43
|
+
function createSuccessResponse(data) {
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
data
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create an error response
|
|
51
|
+
*/
|
|
52
|
+
function createErrorResponse(code, message, details) {
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
error: {
|
|
56
|
+
code,
|
|
57
|
+
message,
|
|
58
|
+
details
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
exports.AFSErrorCode = AFSErrorCode;
|
|
65
|
+
exports.VALID_RPC_METHODS = VALID_RPC_METHODS;
|
|
66
|
+
exports.createErrorResponse = createErrorResponse;
|
|
67
|
+
exports.createSuccessResponse = createSuccessResponse;
|
|
68
|
+
exports.isValidRpcMethod = isValidRpcMethod;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { AFSDeleteOptions, AFSDeleteResult, AFSExecOptions, AFSExecResult, AFSListOptions, AFSListResult, AFSReadOptions, AFSReadResult, AFSRenameOptions, AFSRenameResult, AFSSearchOptions, AFSSearchResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/protocol.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* AFS HTTP RPC method names
|
|
6
|
+
*/
|
|
7
|
+
type AFSRpcMethod = "list" | "read" | "write" | "delete" | "rename" | "search" | "exec";
|
|
8
|
+
/**
|
|
9
|
+
* RPC request body
|
|
10
|
+
*/
|
|
11
|
+
interface AFSRpcRequest<M extends AFSRpcMethod = AFSRpcMethod> {
|
|
12
|
+
method: M;
|
|
13
|
+
params: AFSRpcParams[M];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* RPC response body
|
|
17
|
+
*/
|
|
18
|
+
interface AFSRpcResponse<T = unknown> {
|
|
19
|
+
success: boolean;
|
|
20
|
+
data?: T;
|
|
21
|
+
error?: AFSRpcError;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* RPC error object
|
|
25
|
+
*/
|
|
26
|
+
interface AFSRpcError {
|
|
27
|
+
/** CLI error code (0-5), compatible with AFS CLI */
|
|
28
|
+
code: AFSErrorCode;
|
|
29
|
+
/** Human-readable error message */
|
|
30
|
+
message: string;
|
|
31
|
+
/** Additional error details */
|
|
32
|
+
details?: unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* CLI-compatible error codes
|
|
36
|
+
* @see https://github.com/arcblock/afs/blob/main/intent/specs/afs-cli-spec.md
|
|
37
|
+
*/
|
|
38
|
+
declare enum AFSErrorCode {
|
|
39
|
+
/** Operation successful */
|
|
40
|
+
OK = 0,
|
|
41
|
+
/** Path not found */
|
|
42
|
+
NOT_FOUND = 1,
|
|
43
|
+
/** Permission denied (including readonly mode) */
|
|
44
|
+
PERMISSION_DENIED = 2,
|
|
45
|
+
/** Concurrent modification conflict */
|
|
46
|
+
CONFLICT = 3,
|
|
47
|
+
/** Partial success */
|
|
48
|
+
PARTIAL = 4,
|
|
49
|
+
/** Runtime error */
|
|
50
|
+
RUNTIME_ERROR = 5,
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parameter types for each RPC method
|
|
54
|
+
*/
|
|
55
|
+
interface AFSRpcParams {
|
|
56
|
+
list: {
|
|
57
|
+
path: string;
|
|
58
|
+
options?: AFSListOptions;
|
|
59
|
+
};
|
|
60
|
+
read: {
|
|
61
|
+
path: string;
|
|
62
|
+
options?: AFSReadOptions;
|
|
63
|
+
};
|
|
64
|
+
write: {
|
|
65
|
+
path: string;
|
|
66
|
+
content: AFSWriteEntryPayload;
|
|
67
|
+
options?: AFSWriteOptions;
|
|
68
|
+
};
|
|
69
|
+
delete: {
|
|
70
|
+
path: string;
|
|
71
|
+
options?: AFSDeleteOptions;
|
|
72
|
+
};
|
|
73
|
+
rename: {
|
|
74
|
+
oldPath: string;
|
|
75
|
+
newPath: string;
|
|
76
|
+
options?: AFSRenameOptions;
|
|
77
|
+
};
|
|
78
|
+
search: {
|
|
79
|
+
path: string;
|
|
80
|
+
query: string;
|
|
81
|
+
options?: AFSSearchOptions;
|
|
82
|
+
};
|
|
83
|
+
exec: {
|
|
84
|
+
path: string;
|
|
85
|
+
args: Record<string, unknown>;
|
|
86
|
+
options?: AFSExecOptions;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Result types for each RPC method
|
|
91
|
+
*/
|
|
92
|
+
interface AFSRpcResults {
|
|
93
|
+
list: AFSListResult;
|
|
94
|
+
read: AFSReadResult;
|
|
95
|
+
write: AFSWriteResult;
|
|
96
|
+
delete: AFSDeleteResult;
|
|
97
|
+
rename: AFSRenameResult;
|
|
98
|
+
search: AFSSearchResult;
|
|
99
|
+
exec: AFSExecResult;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Valid RPC methods set for validation
|
|
103
|
+
*/
|
|
104
|
+
declare const VALID_RPC_METHODS: Set<AFSRpcMethod>;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a string is a valid RPC method
|
|
107
|
+
*/
|
|
108
|
+
declare function isValidRpcMethod(method: string): method is AFSRpcMethod;
|
|
109
|
+
/**
|
|
110
|
+
* Create a success response
|
|
111
|
+
*/
|
|
112
|
+
declare function createSuccessResponse<T>(data: T): AFSRpcResponse<T>;
|
|
113
|
+
/**
|
|
114
|
+
* Create an error response
|
|
115
|
+
*/
|
|
116
|
+
declare function createErrorResponse(code: AFSErrorCode, message: string, details?: unknown): AFSRpcResponse<never>;
|
|
117
|
+
//#endregion
|
|
118
|
+
export { AFSErrorCode, AFSRpcError, AFSRpcMethod, AFSRpcParams, AFSRpcRequest, AFSRpcResponse, AFSRpcResults, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod };
|
|
119
|
+
//# sourceMappingURL=protocol.d.cts.map
|
|
@@ -0,0 +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;AAkBA;;AA7BQ,aAWI,YAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;EAAA;EAAA,iBAAA;EAAA;EAAA,QAAA;EAAA;EAAA,OAAA;EAAA;EAAA,aAAA;AAAA;AAAA;AAkBZ;;AAlBY,UAkBK,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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { AFSDeleteOptions, AFSDeleteResult, AFSExecOptions, AFSExecResult, AFSListOptions, AFSListResult, AFSReadOptions, AFSReadResult, AFSRenameOptions, AFSRenameResult, AFSSearchOptions, AFSSearchResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/protocol.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* AFS HTTP RPC method names
|
|
6
|
+
*/
|
|
7
|
+
type AFSRpcMethod = "list" | "read" | "write" | "delete" | "rename" | "search" | "exec";
|
|
8
|
+
/**
|
|
9
|
+
* RPC request body
|
|
10
|
+
*/
|
|
11
|
+
interface AFSRpcRequest<M extends AFSRpcMethod = AFSRpcMethod> {
|
|
12
|
+
method: M;
|
|
13
|
+
params: AFSRpcParams[M];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* RPC response body
|
|
17
|
+
*/
|
|
18
|
+
interface AFSRpcResponse<T = unknown> {
|
|
19
|
+
success: boolean;
|
|
20
|
+
data?: T;
|
|
21
|
+
error?: AFSRpcError;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* RPC error object
|
|
25
|
+
*/
|
|
26
|
+
interface AFSRpcError {
|
|
27
|
+
/** CLI error code (0-5), compatible with AFS CLI */
|
|
28
|
+
code: AFSErrorCode;
|
|
29
|
+
/** Human-readable error message */
|
|
30
|
+
message: string;
|
|
31
|
+
/** Additional error details */
|
|
32
|
+
details?: unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* CLI-compatible error codes
|
|
36
|
+
* @see https://github.com/arcblock/afs/blob/main/intent/specs/afs-cli-spec.md
|
|
37
|
+
*/
|
|
38
|
+
declare enum AFSErrorCode {
|
|
39
|
+
/** Operation successful */
|
|
40
|
+
OK = 0,
|
|
41
|
+
/** Path not found */
|
|
42
|
+
NOT_FOUND = 1,
|
|
43
|
+
/** Permission denied (including readonly mode) */
|
|
44
|
+
PERMISSION_DENIED = 2,
|
|
45
|
+
/** Concurrent modification conflict */
|
|
46
|
+
CONFLICT = 3,
|
|
47
|
+
/** Partial success */
|
|
48
|
+
PARTIAL = 4,
|
|
49
|
+
/** Runtime error */
|
|
50
|
+
RUNTIME_ERROR = 5,
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parameter types for each RPC method
|
|
54
|
+
*/
|
|
55
|
+
interface AFSRpcParams {
|
|
56
|
+
list: {
|
|
57
|
+
path: string;
|
|
58
|
+
options?: AFSListOptions;
|
|
59
|
+
};
|
|
60
|
+
read: {
|
|
61
|
+
path: string;
|
|
62
|
+
options?: AFSReadOptions;
|
|
63
|
+
};
|
|
64
|
+
write: {
|
|
65
|
+
path: string;
|
|
66
|
+
content: AFSWriteEntryPayload;
|
|
67
|
+
options?: AFSWriteOptions;
|
|
68
|
+
};
|
|
69
|
+
delete: {
|
|
70
|
+
path: string;
|
|
71
|
+
options?: AFSDeleteOptions;
|
|
72
|
+
};
|
|
73
|
+
rename: {
|
|
74
|
+
oldPath: string;
|
|
75
|
+
newPath: string;
|
|
76
|
+
options?: AFSRenameOptions;
|
|
77
|
+
};
|
|
78
|
+
search: {
|
|
79
|
+
path: string;
|
|
80
|
+
query: string;
|
|
81
|
+
options?: AFSSearchOptions;
|
|
82
|
+
};
|
|
83
|
+
exec: {
|
|
84
|
+
path: string;
|
|
85
|
+
args: Record<string, unknown>;
|
|
86
|
+
options?: AFSExecOptions;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Result types for each RPC method
|
|
91
|
+
*/
|
|
92
|
+
interface AFSRpcResults {
|
|
93
|
+
list: AFSListResult;
|
|
94
|
+
read: AFSReadResult;
|
|
95
|
+
write: AFSWriteResult;
|
|
96
|
+
delete: AFSDeleteResult;
|
|
97
|
+
rename: AFSRenameResult;
|
|
98
|
+
search: AFSSearchResult;
|
|
99
|
+
exec: AFSExecResult;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Valid RPC methods set for validation
|
|
103
|
+
*/
|
|
104
|
+
declare const VALID_RPC_METHODS: Set<AFSRpcMethod>;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a string is a valid RPC method
|
|
107
|
+
*/
|
|
108
|
+
declare function isValidRpcMethod(method: string): method is AFSRpcMethod;
|
|
109
|
+
/**
|
|
110
|
+
* Create a success response
|
|
111
|
+
*/
|
|
112
|
+
declare function createSuccessResponse<T>(data: T): AFSRpcResponse<T>;
|
|
113
|
+
/**
|
|
114
|
+
* Create an error response
|
|
115
|
+
*/
|
|
116
|
+
declare function createErrorResponse(code: AFSErrorCode, message: string, details?: unknown): AFSRpcResponse<never>;
|
|
117
|
+
//#endregion
|
|
118
|
+
export { AFSErrorCode, AFSRpcError, AFSRpcMethod, AFSRpcParams, AFSRpcRequest, AFSRpcResponse, AFSRpcResults, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod };
|
|
119
|
+
//# sourceMappingURL=protocol.d.mts.map
|
|
@@ -0,0 +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;AAkBA;;AA7BQ,aAWI,YAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;EAAA;EAAA,iBAAA;EAAA;EAAA,QAAA;EAAA;EAAA,OAAA;EAAA;EAAA,aAAA;AAAA;AAAA;AAkBZ;;AAlBY,UAkBK,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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/protocol.ts
|
|
2
|
+
/**
|
|
3
|
+
* CLI-compatible error codes
|
|
4
|
+
* @see https://github.com/arcblock/afs/blob/main/intent/specs/afs-cli-spec.md
|
|
5
|
+
*/
|
|
6
|
+
let AFSErrorCode = /* @__PURE__ */ function(AFSErrorCode) {
|
|
7
|
+
/** Operation successful */
|
|
8
|
+
AFSErrorCode[AFSErrorCode["OK"] = 0] = "OK";
|
|
9
|
+
/** Path not found */
|
|
10
|
+
AFSErrorCode[AFSErrorCode["NOT_FOUND"] = 1] = "NOT_FOUND";
|
|
11
|
+
/** Permission denied (including readonly mode) */
|
|
12
|
+
AFSErrorCode[AFSErrorCode["PERMISSION_DENIED"] = 2] = "PERMISSION_DENIED";
|
|
13
|
+
/** Concurrent modification conflict */
|
|
14
|
+
AFSErrorCode[AFSErrorCode["CONFLICT"] = 3] = "CONFLICT";
|
|
15
|
+
/** Partial success */
|
|
16
|
+
AFSErrorCode[AFSErrorCode["PARTIAL"] = 4] = "PARTIAL";
|
|
17
|
+
/** Runtime error */
|
|
18
|
+
AFSErrorCode[AFSErrorCode["RUNTIME_ERROR"] = 5] = "RUNTIME_ERROR";
|
|
19
|
+
return AFSErrorCode;
|
|
20
|
+
}({});
|
|
21
|
+
/**
|
|
22
|
+
* Valid RPC methods set for validation
|
|
23
|
+
*/
|
|
24
|
+
const VALID_RPC_METHODS = new Set([
|
|
25
|
+
"list",
|
|
26
|
+
"read",
|
|
27
|
+
"write",
|
|
28
|
+
"delete",
|
|
29
|
+
"rename",
|
|
30
|
+
"search",
|
|
31
|
+
"exec"
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* Check if a string is a valid RPC method
|
|
35
|
+
*/
|
|
36
|
+
function isValidRpcMethod(method) {
|
|
37
|
+
return VALID_RPC_METHODS.has(method);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a success response
|
|
41
|
+
*/
|
|
42
|
+
function createSuccessResponse(data) {
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
data
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create an error response
|
|
50
|
+
*/
|
|
51
|
+
function createErrorResponse(code, message, details) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
error: {
|
|
55
|
+
code,
|
|
56
|
+
message,
|
|
57
|
+
details
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { AFSErrorCode, VALID_RPC_METHODS, createErrorResponse, createSuccessResponse, isValidRpcMethod };
|
|
64
|
+
//# sourceMappingURL=protocol.mjs.map
|
|
@@ -0,0 +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-5), 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}\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;;;;;;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"}
|