@aigne/afs-mapping 1.11.0-beta.6

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 ADDED
@@ -0,0 +1,26 @@
1
+ # Proprietary License
2
+
3
+ Copyright (c) 2024-2025 ArcBlock, Inc. All Rights Reserved.
4
+
5
+ This software and associated documentation files (the "Software") are proprietary
6
+ and confidential. Unauthorized copying, modification, distribution, or use of
7
+ this Software, via any medium, is strictly prohibited.
8
+
9
+ The Software is provided for internal use only within ArcBlock, Inc. and its
10
+ authorized affiliates.
11
+
12
+ ## No License Granted
13
+
14
+ No license, express or implied, is granted to any party for any purpose.
15
+ All rights are reserved by ArcBlock, Inc.
16
+
17
+ ## Public Artifact Distribution
18
+
19
+ Portions of this Software may be released publicly under separate open-source
20
+ licenses (such as MIT License) through designated public repositories. Such
21
+ public releases are governed by their respective licenses and do not affect
22
+ the proprietary nature of this repository.
23
+
24
+ ## Contact
25
+
26
+ For licensing inquiries, contact: legal@arcblock.io
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # @aigne/afs-mapping
2
+
3
+ **@aigne/afs-mapping** is a DSL compiler for declarative path-to-API mapping. It converts YAML DSL definitions into compiled route matchers, enabling AFS providers to map virtual paths to external API calls.
4
+
5
+ ## Overview
6
+
7
+ AFS Mapping provides the infrastructure for building AFS providers that interact with external APIs. It allows you to declaratively define how AFS paths map to API endpoints, how parameters are extracted and bound, and how API responses are transformed into AFS entries.
8
+
9
+ ## Features
10
+
11
+ - **YAML DSL**: Declarative mapping configuration in YAML format
12
+ - **Path Resolution**: Pattern-based route matching with parameter extraction
13
+ - **Expression Binding**: Flexible parameter binding with Jinja-like expressions
14
+ - **Response Projection**: Transform API responses into AFS entries
15
+ - **Multi-Operation Support**: Define list, read, write, create, and delete operations
16
+ - **Modular Configuration**: Split mappings across multiple files with includes
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @aigne/afs-mapping
22
+ # or
23
+ yarn add @aigne/afs-mapping
24
+ # or
25
+ pnpm add @aigne/afs-mapping
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { MappingCompiler } from "@aigne/afs-mapping";
32
+
33
+ // Compile a mapping configuration
34
+ const compiler = new MappingCompiler();
35
+ const compiled = await compiler.compileDirectory("/path/to/mapping/");
36
+
37
+ // Resolve a path to route information
38
+ const resolved = compiled.resolve("/aigne/afs/issues/123");
39
+ // => { template: "/{owner}/{repo}/issues/{number}", params: { owner: "aigne", repo: "afs", number: "123" }, ... }
40
+
41
+ // Build an HTTP request
42
+ const request = compiled.buildRequest("/aigne/afs/issues", "list", {
43
+ query: { state: "open" },
44
+ });
45
+ // => { method: "GET", path: "/repos/aigne/afs/issues", params: { state: "open", per_page: 30 }, ... }
46
+
47
+ // Project API response to AFS entries
48
+ const entries = compiled.projectResponse("/aigne/afs/issues", "list", apiResponse);
49
+ ```
50
+
51
+ ## Mapping DSL
52
+
53
+ ### Configuration Structure
54
+
55
+ ```yaml
56
+ # mapping.yml
57
+ name: github
58
+ version: "1.0"
59
+ description: GitHub API mapping
60
+
61
+ defaults:
62
+ baseUrl: https://api.github.com
63
+ headers:
64
+ Accept: application/vnd.github+json
65
+
66
+ routes:
67
+ "/{owner}/{repo}/issues":
68
+ list:
69
+ method: GET
70
+ path: /repos/{owner}/{repo}/issues
71
+ params:
72
+ owner: path.owner
73
+ repo: path.repo
74
+ state: query.state | default("open")
75
+ per_page: query.limit | default(30)
76
+ transform:
77
+ items: "$"
78
+ entry:
79
+ id: "$.number | string"
80
+ path: "/{owner}/{repo}/issues/{$.number}"
81
+ summary: "$.title"
82
+ content: "$.body"
83
+ ```
84
+
85
+ ### Route Definition
86
+
87
+ Each route defines operations for a path pattern:
88
+
89
+ ```yaml
90
+ routes:
91
+ "/{owner}/{repo}/issues/{number}":
92
+ read:
93
+ method: GET
94
+ path: /repos/{owner}/{repo}/issues/{number}
95
+ params:
96
+ owner: path.owner
97
+ repo: path.repo
98
+ number: path.number
99
+ transform:
100
+ entry:
101
+ id: "$.number | string"
102
+ path: "/{owner}/{repo}/issues/{$.number}"
103
+ summary: "$.title"
104
+ content: "$.body"
105
+ metadata:
106
+ type: issue
107
+ state: "$.state"
108
+ author: "$.user.login"
109
+ ```
110
+
111
+ ### Operations
112
+
113
+ Each route can define these operations:
114
+
115
+ - **list**: Returns multiple entries (GET)
116
+ - **read**: Returns a single entry (GET)
117
+ - **write**: Updates an existing entry (PUT/PATCH)
118
+ - **create**: Creates a new entry (POST)
119
+ - **delete**: Removes an entry (DELETE)
120
+
121
+ ### Parameter Binding
122
+
123
+ Parameters can be bound from various sources:
124
+
125
+ ```yaml
126
+ params:
127
+ # From path parameters
128
+ owner: path.owner
129
+
130
+ # From query parameters with default
131
+ state: query.state | default("open")
132
+
133
+ # From request input
134
+ title: input.title
135
+
136
+ # Static values
137
+ per_page: "30"
138
+ ```
139
+
140
+ ### Response Transform
141
+
142
+ Transform API responses into AFS entries:
143
+
144
+ ```yaml
145
+ transform:
146
+ # JSONPath to items array (for list operations)
147
+ items: "$.data"
148
+
149
+ # Entry mapping
150
+ entry:
151
+ id: "$.id | string"
152
+ path: "/items/{$.id}"
153
+ summary: "$.title"
154
+ content: "$.body"
155
+ description: "$.description"
156
+ metadata:
157
+ type: "$.type"
158
+ status: "$.status"
159
+ ```
160
+
161
+ ## API Reference
162
+
163
+ ### MappingCompiler
164
+
165
+ ```typescript
166
+ const compiler = new MappingCompiler();
167
+
168
+ // Compile from a single file
169
+ const compiled = await compiler.compileFile("/path/to/mapping.yml");
170
+
171
+ // Compile from a directory (with includes)
172
+ const compiled = await compiler.compileDirectory("/path/to/mapping/");
173
+
174
+ // Compile from a config object (for testing)
175
+ const compiled = compiler.compileConfig(configObject);
176
+ ```
177
+
178
+ ### CompiledMapping
179
+
180
+ ```typescript
181
+ // Get mapping info
182
+ compiled.name; // Mapping name
183
+ compiled.version; // Version string
184
+ compiled.routeCount; // Number of routes
185
+ compiled.operationCount; // Total operations
186
+
187
+ // Resolve a path
188
+ const resolved = compiled.resolve("/owner/repo/issues/123");
189
+ // Returns: { template, params, operations }
190
+
191
+ // Build HTTP request
192
+ const request = compiled.buildRequest(path, operationType, { query, input });
193
+ // Returns: { method, path, params, headers, body }
194
+
195
+ // Project API response
196
+ const entries = compiled.projectResponse(path, operationType, apiResponse);
197
+ // Returns: AFSEntry[]
198
+ ```
199
+
200
+ ### ResolvedRoute
201
+
202
+ ```typescript
203
+ interface ResolvedRoute {
204
+ template: string; // Original template
205
+ params: Record<string, string>; // Extracted parameters
206
+ operations: { // Available operations
207
+ list?: Operation;
208
+ read?: Operation;
209
+ write?: Operation;
210
+ create?: Operation;
211
+ delete?: Operation;
212
+ };
213
+ }
214
+ ```
215
+
216
+ ### HttpRequest
217
+
218
+ ```typescript
219
+ interface HttpRequest {
220
+ method: string; // HTTP method
221
+ path: string; // Request path (interpolated)
222
+ params: Record<string, unknown>; // Query/path parameters
223
+ headers?: Record<string, string>; // Request headers
224
+ body?: Record<string, unknown>; // Request body
225
+ }
226
+ ```
227
+
228
+ ## Creating a Provider with Mapping
229
+
230
+ Here's how to use AFS Mapping in a custom provider:
231
+
232
+ ```typescript
233
+ import { AFSModule, AFSEntry } from "@aigne/afs";
234
+ import { MappingCompiler, CompiledMapping } from "@aigne/afs-mapping";
235
+
236
+ class MyAPIProvider implements AFSModule {
237
+ readonly name = "my-api";
238
+ private compiled: CompiledMapping;
239
+
240
+ constructor() {
241
+ const compiler = new MappingCompiler();
242
+ this.compiled = compiler.compileConfig({
243
+ name: "my-api",
244
+ version: "1.0",
245
+ routes: {
246
+ "/items": {
247
+ list: {
248
+ method: "GET",
249
+ path: "/api/items",
250
+ transform: {
251
+ items: "$",
252
+ entry: {
253
+ id: "$.id",
254
+ path: "/items/{$.id}",
255
+ summary: "$.name",
256
+ },
257
+ },
258
+ },
259
+ },
260
+ },
261
+ });
262
+ }
263
+
264
+ async list(path: string): Promise<{ data: AFSEntry[] }> {
265
+ const request = this.compiled.buildRequest(path, "list", {});
266
+ if (!request) return { data: [] };
267
+
268
+ // Make API call
269
+ const response = await fetch(`https://api.example.com${request.path}`);
270
+ const data = await response.json();
271
+
272
+ // Transform response
273
+ const entries = this.compiled.projectResponse(path, "list", data);
274
+ return { data: entries };
275
+ }
276
+ }
277
+ ```
278
+
279
+ ## Related Packages
280
+
281
+ - [@aigne/afs](../core/README.md) - AFS core package
282
+ - [@aigne/afs-github](../../providers/github/README.md) - GitHub provider (uses AFS Mapping)
283
+
284
+ ## TypeScript Support
285
+
286
+ This package includes full TypeScript type definitions.