@aigne/afs 1.11.0-beta → 1.11.0-beta.10
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 +17 -84
- package/README.md +4 -13
- package/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/afs.cjs +1330 -0
- package/dist/afs.d.cts +275 -0
- package/dist/afs.d.cts.map +1 -0
- package/dist/afs.d.mts +275 -0
- package/dist/afs.d.mts.map +1 -0
- package/dist/afs.mjs +1331 -0
- package/dist/afs.mjs.map +1 -0
- package/dist/capabilities/index.d.mts +2 -0
- package/dist/capabilities/types.d.cts +100 -0
- package/dist/capabilities/types.d.cts.map +1 -0
- package/dist/capabilities/types.d.mts +100 -0
- package/dist/capabilities/types.d.mts.map +1 -0
- package/dist/capabilities/world-mapping.cjs +20 -0
- package/dist/capabilities/world-mapping.d.cts +139 -0
- package/dist/capabilities/world-mapping.d.cts.map +1 -0
- package/dist/capabilities/world-mapping.d.mts +139 -0
- package/dist/capabilities/world-mapping.d.mts.map +1 -0
- package/dist/capabilities/world-mapping.mjs +20 -0
- package/dist/capabilities/world-mapping.mjs.map +1 -0
- package/dist/error.cjs +63 -0
- package/dist/error.d.cts +39 -0
- package/dist/error.d.cts.map +1 -0
- package/dist/error.d.mts +39 -0
- package/dist/error.d.mts.map +1 -0
- package/dist/error.mjs +59 -0
- package/dist/error.mjs.map +1 -0
- package/dist/index.cjs +72 -345
- package/dist/index.d.cts +18 -300
- package/dist/index.d.mts +20 -300
- package/dist/index.mjs +16 -342
- package/dist/loader/index.cjs +110 -0
- package/dist/loader/index.d.cts +48 -0
- package/dist/loader/index.d.cts.map +1 -0
- package/dist/loader/index.d.mts +48 -0
- package/dist/loader/index.d.mts.map +1 -0
- package/dist/loader/index.mjs +110 -0
- package/dist/loader/index.mjs.map +1 -0
- package/dist/meta/index.cjs +4 -0
- package/dist/meta/index.mjs +6 -0
- package/dist/meta/kind.cjs +161 -0
- package/dist/meta/kind.d.cts +134 -0
- package/dist/meta/kind.d.cts.map +1 -0
- package/dist/meta/kind.d.mts +134 -0
- package/dist/meta/kind.d.mts.map +1 -0
- package/dist/meta/kind.mjs +157 -0
- package/dist/meta/kind.mjs.map +1 -0
- package/dist/meta/path.cjs +116 -0
- package/dist/meta/path.d.cts +43 -0
- package/dist/meta/path.d.cts.map +1 -0
- package/dist/meta/path.d.mts +43 -0
- package/dist/meta/path.d.mts.map +1 -0
- package/dist/meta/path.mjs +112 -0
- package/dist/meta/path.mjs.map +1 -0
- package/dist/meta/type.d.cts +96 -0
- package/dist/meta/type.d.cts.map +1 -0
- package/dist/meta/type.d.mts +96 -0
- package/dist/meta/type.d.mts.map +1 -0
- package/dist/meta/validation.cjs +77 -0
- package/dist/meta/validation.d.cts +19 -0
- package/dist/meta/validation.d.cts.map +1 -0
- package/dist/meta/validation.d.mts +19 -0
- package/dist/meta/validation.d.mts.map +1 -0
- package/dist/meta/validation.mjs +77 -0
- package/dist/meta/validation.mjs.map +1 -0
- package/dist/meta/well-known-kinds.cjs +228 -0
- package/dist/meta/well-known-kinds.d.cts +52 -0
- package/dist/meta/well-known-kinds.d.cts.map +1 -0
- package/dist/meta/well-known-kinds.d.mts +52 -0
- package/dist/meta/well-known-kinds.d.mts.map +1 -0
- package/dist/meta/well-known-kinds.mjs +219 -0
- package/dist/meta/well-known-kinds.mjs.map +1 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.cts +141 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.mts +141 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.mts.map +1 -0
- package/dist/path.cjs +255 -0
- package/dist/path.d.cts +93 -0
- package/dist/path.d.cts.map +1 -0
- package/dist/path.d.mts +93 -0
- package/dist/path.d.mts.map +1 -0
- package/dist/path.mjs +249 -0
- package/dist/path.mjs.map +1 -0
- package/dist/provider/base.cjs +425 -0
- package/dist/provider/base.d.cts +175 -0
- package/dist/provider/base.d.cts.map +1 -0
- package/dist/provider/base.d.mts +175 -0
- package/dist/provider/base.d.mts.map +1 -0
- package/dist/provider/base.mjs +426 -0
- package/dist/provider/base.mjs.map +1 -0
- package/dist/provider/decorators.cjs +268 -0
- package/dist/provider/decorators.d.cts +244 -0
- package/dist/provider/decorators.d.cts.map +1 -0
- package/dist/provider/decorators.d.mts +244 -0
- package/dist/provider/decorators.d.mts.map +1 -0
- package/dist/provider/decorators.mjs +256 -0
- package/dist/provider/decorators.mjs.map +1 -0
- package/dist/provider/index.cjs +19 -0
- package/dist/provider/index.d.cts +5 -0
- package/dist/provider/index.d.mts +5 -0
- package/dist/provider/index.mjs +5 -0
- package/dist/provider/router.cjs +185 -0
- package/dist/provider/router.d.cts +50 -0
- package/dist/provider/router.d.cts.map +1 -0
- package/dist/provider/router.d.mts +50 -0
- package/dist/provider/router.d.mts.map +1 -0
- package/dist/provider/router.mjs +185 -0
- package/dist/provider/router.mjs.map +1 -0
- package/dist/provider/types.d.cts +113 -0
- package/dist/provider/types.d.cts.map +1 -0
- package/dist/provider/types.d.mts +113 -0
- package/dist/provider/types.d.mts.map +1 -0
- package/dist/registry.cjs +358 -0
- package/dist/registry.d.cts +96 -0
- package/dist/registry.d.cts.map +1 -0
- package/dist/registry.d.mts +96 -0
- package/dist/registry.d.mts.map +1 -0
- package/dist/registry.mjs +360 -0
- package/dist/registry.mjs.map +1 -0
- package/dist/type.cjs +34 -0
- package/dist/type.d.cts +420 -0
- package/dist/type.d.cts.map +1 -0
- package/dist/type.d.mts +420 -0
- package/dist/type.d.mts.map +1 -0
- package/dist/type.mjs +33 -0
- package/dist/type.mjs.map +1 -0
- package/dist/utils/camelize.d.cts.map +1 -1
- package/dist/utils/camelize.d.mts.map +1 -1
- package/dist/utils/schema.cjs +129 -0
- package/dist/utils/schema.d.cts +65 -0
- package/dist/utils/schema.d.cts.map +1 -0
- package/dist/utils/schema.d.mts +65 -0
- package/dist/utils/schema.d.mts.map +1 -0
- package/dist/utils/schema.mjs +124 -0
- package/dist/utils/schema.mjs.map +1 -0
- package/dist/utils/type-utils.d.cts.map +1 -1
- package/dist/utils/type-utils.d.mts.map +1 -1
- package/dist/utils/uri-template.cjs +123 -0
- package/dist/utils/uri-template.d.cts +48 -0
- package/dist/utils/uri-template.d.cts.map +1 -0
- package/dist/utils/uri-template.d.mts +48 -0
- package/dist/utils/uri-template.d.mts.map +1 -0
- package/dist/utils/uri-template.mjs +120 -0
- package/dist/utils/uri-template.mjs.map +1 -0
- package/dist/utils/uri.cjs +49 -0
- package/dist/utils/uri.d.cts +34 -0
- package/dist/utils/uri.d.cts.map +1 -0
- package/dist/utils/uri.d.mts +34 -0
- package/dist/utils/uri.d.mts.map +1 -0
- package/dist/utils/uri.mjs +49 -0
- package/dist/utils/uri.mjs.map +1 -0
- package/dist/utils/zod.cjs +6 -8
- package/dist/utils/zod.d.cts +2 -2
- package/dist/utils/zod.d.cts.map +1 -1
- package/dist/utils/zod.d.mts +2 -2
- package/dist/utils/zod.d.mts.map +1 -1
- package/dist/utils/zod.mjs +6 -8
- package/dist/utils/zod.mjs.map +1 -1
- package/package.json +27 -4
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,343 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { AFSError, AFSMountError, AFSNotFoundError, AFSReadonlyError, AFSValidationError } from "./error.mjs";
|
|
2
|
+
import { AFSPathError, isCanonicalPath, normalizePath, parseCanonicalPath, toCanonicalPath, validateModuleName, validatePath } from "./path.mjs";
|
|
3
|
+
import { AFS } from "./afs.mjs";
|
|
4
|
+
import { isWorldMappingCapable } from "./capabilities/world-mapping.mjs";
|
|
5
|
+
import { combineValidationResults, validateNodes } from "./meta/validation.mjs";
|
|
6
|
+
import { WELL_KNOWN_KINDS, WELL_KNOWN_KINDS_MAP, afsDocument, afsExecutable, afsImage, afsLink, afsNode, commonMetaSchema, getWellKnownKind, isWellKnownKind } from "./meta/well-known-kinds.mjs";
|
|
7
|
+
import { KindError, createKindResolver, defaultKindResolver, defineKind, getInheritanceChain, resolveKindSchema } from "./meta/kind.mjs";
|
|
8
|
+
import { KINDS_SEGMENT, META_SEGMENT, getNodePathFromMetaPath, isKindsPath, isMetaPath, parseMetaPath } from "./meta/path.mjs";
|
|
9
|
+
import "./meta/index.mjs";
|
|
10
|
+
import { Actions, Delete, Exec, Explain, List, Meta, Read, Rename, Search, Stat, Write, clearRoutes, getRoutes } from "./provider/decorators.mjs";
|
|
11
|
+
import { ProviderRouter } from "./provider/router.mjs";
|
|
12
|
+
import { AFSBaseProvider } from "./provider/base.mjs";
|
|
13
|
+
import "./provider/index.mjs";
|
|
14
|
+
import { ProviderRegistry } from "./registry.mjs";
|
|
15
|
+
import { accessModeSchema, actionSummarySchema, afsEntrySchema } from "./type.mjs";
|
|
5
16
|
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Base error class for all AFS errors.
|
|
9
|
-
*/
|
|
10
|
-
var AFSError = class extends Error {
|
|
11
|
-
code;
|
|
12
|
-
constructor(message, code) {
|
|
13
|
-
super(message);
|
|
14
|
-
this.name = "AFSError";
|
|
15
|
-
this.code = code;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* Error thrown when attempting write operations on a readonly AFS or module.
|
|
20
|
-
*/
|
|
21
|
-
var AFSReadonlyError = class extends AFSError {
|
|
22
|
-
constructor(message) {
|
|
23
|
-
super(message, "AFS_READONLY");
|
|
24
|
-
this.name = "AFSReadonlyError";
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/type.ts
|
|
30
|
-
/**
|
|
31
|
-
* Zod schema for access mode validation.
|
|
32
|
-
* Can be reused across modules that support access mode configuration.
|
|
33
|
-
*/
|
|
34
|
-
const accessModeSchema = z.enum(["readonly", "readwrite"]).describe("Access mode for this module").optional();
|
|
35
|
-
const afsEntrySchema = z.object({
|
|
36
|
-
id: z.string(),
|
|
37
|
-
createdAt: z.date().optional(),
|
|
38
|
-
updatedAt: z.date().optional(),
|
|
39
|
-
path: z.string(),
|
|
40
|
-
userId: z.string().nullable().optional(),
|
|
41
|
-
sessionId: z.string().nullable().optional(),
|
|
42
|
-
summary: z.string().nullable().optional(),
|
|
43
|
-
description: z.string().nullable().optional(),
|
|
44
|
-
metadata: z.record(z.any()).nullable().optional(),
|
|
45
|
-
linkTo: z.string().nullable().optional(),
|
|
46
|
-
content: z.any().optional()
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/afs.ts
|
|
51
|
-
const DEFAULT_MAX_DEPTH = 1;
|
|
52
|
-
const MODULES_ROOT_DIR = "/modules";
|
|
53
|
-
var AFS = class extends Emitter {
|
|
54
|
-
name = "AFSRoot";
|
|
55
|
-
constructor(options = {}) {
|
|
56
|
-
super();
|
|
57
|
-
this.options = options;
|
|
58
|
-
for (const module of options?.modules ?? []) this.mount(module);
|
|
59
|
-
}
|
|
60
|
-
modules = /* @__PURE__ */ new Map();
|
|
61
|
-
/**
|
|
62
|
-
* Check if write operations are allowed for the given module.
|
|
63
|
-
* Throws AFSReadonlyError if not allowed.
|
|
64
|
-
*/
|
|
65
|
-
checkWritePermission(module, operation, path) {
|
|
66
|
-
if (module.accessMode !== "readwrite") throw new AFSReadonlyError(`Module '${module.name}' is readonly, cannot perform ${operation} to ${path}`);
|
|
67
|
-
}
|
|
68
|
-
mount(module) {
|
|
69
|
-
if (module.name.includes("/")) throw new Error(`Invalid module name: ${module.name}. Module name must not contain '/'`);
|
|
70
|
-
const path = joinURL(MODULES_ROOT_DIR, module.name);
|
|
71
|
-
if (this.modules.has(path)) throw new Error(`Module already mounted at path: ${path}`);
|
|
72
|
-
this.modules.set(path, module);
|
|
73
|
-
module.onMount?.(this);
|
|
74
|
-
return this;
|
|
75
|
-
}
|
|
76
|
-
async listModules() {
|
|
77
|
-
return Array.from(this.modules.entries()).map(([path, module]) => ({
|
|
78
|
-
path,
|
|
79
|
-
name: module.name,
|
|
80
|
-
description: module.description,
|
|
81
|
-
module
|
|
82
|
-
}));
|
|
83
|
-
}
|
|
84
|
-
async list(path, options = {}) {
|
|
85
|
-
let preset;
|
|
86
|
-
if (options.preset) {
|
|
87
|
-
preset = this.options?.context?.list?.presets?.[options.preset];
|
|
88
|
-
if (!preset) throw new Error(`Preset not found: ${options.preset}`);
|
|
89
|
-
}
|
|
90
|
-
return await this.processWithPreset(path, void 0, preset, {
|
|
91
|
-
...options,
|
|
92
|
-
defaultSelect: () => this._list(path, options)
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
async _list(path, options = {}) {
|
|
96
|
-
const results = [];
|
|
97
|
-
if (path === "/" && this.modules.size > 0) {
|
|
98
|
-
const maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
99
|
-
results.push({
|
|
100
|
-
id: "modules",
|
|
101
|
-
path: MODULES_ROOT_DIR,
|
|
102
|
-
summary: "All mounted modules"
|
|
103
|
-
});
|
|
104
|
-
if (maxDepth === 1) return { data: results };
|
|
105
|
-
const childrenResult = await this._list(MODULES_ROOT_DIR, {
|
|
106
|
-
...options,
|
|
107
|
-
maxDepth: maxDepth - 1
|
|
108
|
-
});
|
|
109
|
-
results.push(...childrenResult.data);
|
|
110
|
-
return { data: results };
|
|
111
|
-
}
|
|
112
|
-
const matches = this.findModules(path, options);
|
|
113
|
-
for (const matched of matches) {
|
|
114
|
-
if (matched.maxDepth === 0) {
|
|
115
|
-
const moduleEntry = {
|
|
116
|
-
id: matched.module.name,
|
|
117
|
-
path: matched.modulePath,
|
|
118
|
-
summary: matched.module.description
|
|
119
|
-
};
|
|
120
|
-
results.push(moduleEntry);
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (!matched.module.list) continue;
|
|
124
|
-
try {
|
|
125
|
-
const { data } = await matched.module.list(matched.subpath, {
|
|
126
|
-
...options,
|
|
127
|
-
maxDepth: matched.maxDepth
|
|
128
|
-
});
|
|
129
|
-
const children = data.map((entry) => ({
|
|
130
|
-
...entry,
|
|
131
|
-
path: joinURL(matched.modulePath, entry.path)
|
|
132
|
-
}));
|
|
133
|
-
results.push(...children);
|
|
134
|
-
} catch (error) {
|
|
135
|
-
throw new Error(`Error listing from module at ${matched.modulePath}: ${error.message}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return { data: results };
|
|
139
|
-
}
|
|
140
|
-
async read(path, _options) {
|
|
141
|
-
const modules = this.findModules(path, { exactMatch: true });
|
|
142
|
-
for (const { module, modulePath, subpath } of modules) {
|
|
143
|
-
const res = await module.read?.(subpath);
|
|
144
|
-
if (res?.data) return {
|
|
145
|
-
...res,
|
|
146
|
-
data: {
|
|
147
|
-
...res.data,
|
|
148
|
-
path: joinURL(modulePath, res.data.path)
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
data: void 0,
|
|
154
|
-
message: "File not found"
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
async write(path, content, options) {
|
|
158
|
-
const module = this.findModules(path, { exactMatch: true })[0];
|
|
159
|
-
if (!module?.module.write) throw new Error(`No module found for path: ${path}`);
|
|
160
|
-
this.checkWritePermission(module.module, "write", path);
|
|
161
|
-
const res = await module.module.write(module.subpath, content, options);
|
|
162
|
-
return {
|
|
163
|
-
...res,
|
|
164
|
-
data: {
|
|
165
|
-
...res.data,
|
|
166
|
-
path: joinURL(module.modulePath, res.data.path)
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
async delete(path, options) {
|
|
171
|
-
const module = this.findModules(path, { exactMatch: true })[0];
|
|
172
|
-
if (!module?.module.delete) throw new Error(`No module found for path: ${path}`);
|
|
173
|
-
this.checkWritePermission(module.module, "delete", path);
|
|
174
|
-
return await module.module.delete(module.subpath, options);
|
|
175
|
-
}
|
|
176
|
-
async rename(oldPath, newPath, options) {
|
|
177
|
-
const oldModule = this.findModules(oldPath, { exactMatch: true })[0];
|
|
178
|
-
const newModule = this.findModules(newPath, { exactMatch: true })[0];
|
|
179
|
-
if (!oldModule || !newModule || oldModule.modulePath !== newModule.modulePath) throw new Error(`Cannot rename across different modules. Both paths must be in the same module.`);
|
|
180
|
-
if (!oldModule.module.rename) throw new Error(`Module does not support rename operation: ${oldModule.modulePath}`);
|
|
181
|
-
this.checkWritePermission(oldModule.module, "rename", oldPath);
|
|
182
|
-
return await oldModule.module.rename(oldModule.subpath, newModule.subpath, options);
|
|
183
|
-
}
|
|
184
|
-
async search(path, query, options = {}) {
|
|
185
|
-
let preset;
|
|
186
|
-
if (options.preset) {
|
|
187
|
-
preset = this.options?.context?.search?.presets?.[options.preset];
|
|
188
|
-
if (!preset) throw new Error(`Preset not found: ${options.preset}`);
|
|
189
|
-
}
|
|
190
|
-
return await this.processWithPreset(path, query, preset, {
|
|
191
|
-
...options,
|
|
192
|
-
defaultSelect: () => this._search(path, query, options)
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
async processWithPreset(path, query, preset, options) {
|
|
196
|
-
const select = options.select || preset?.select;
|
|
197
|
-
const per = options.per || preset?.per;
|
|
198
|
-
const dedupe = options.dedupe || preset?.dedupe;
|
|
199
|
-
const format = options.format || preset?.format;
|
|
200
|
-
const entries = select ? (await this._select(path, query, select, options)).data : (await options.defaultSelect()).data;
|
|
201
|
-
const mapped = per ? await Promise.all(entries.map((data) => per.invoke({ data }, options).then((res) => res.data))) : entries;
|
|
202
|
-
const deduped = dedupe ? await dedupe.invoke({ data: mapped }, options).then((res) => res.data) : mapped;
|
|
203
|
-
let formatted = deduped;
|
|
204
|
-
if (format === "simple-list" || format === "tree") {
|
|
205
|
-
const valid = z.array(afsEntrySchema).safeParse(deduped);
|
|
206
|
-
if (!valid.data) throw new Error("Tree format requires entries to be AFSEntry objects");
|
|
207
|
-
if (format === "tree") formatted = this.buildTreeView(valid.data);
|
|
208
|
-
else if (format === "simple-list") formatted = this.buildSimpleListView(valid.data);
|
|
209
|
-
} else if (typeof format === "object" && typeof format.invoke === "function") formatted = await format.invoke({ data: deduped }, options).then((res) => res.data);
|
|
210
|
-
return { data: formatted };
|
|
211
|
-
}
|
|
212
|
-
async _select(path, query, select, options) {
|
|
213
|
-
const { data } = await select.invoke({
|
|
214
|
-
path,
|
|
215
|
-
query
|
|
216
|
-
}, options);
|
|
217
|
-
return { data: (await Promise.all(data.map((p) => this.read(p).then((res) => res.data)))).filter((i) => !!i) };
|
|
218
|
-
}
|
|
219
|
-
async _search(path, query, options) {
|
|
220
|
-
const results = [];
|
|
221
|
-
const messages = [];
|
|
222
|
-
for (const { module, modulePath, subpath } of this.findModules(path)) {
|
|
223
|
-
if (!module.search) continue;
|
|
224
|
-
try {
|
|
225
|
-
const { data, message } = await module.search(subpath, query, options);
|
|
226
|
-
results.push(...data.map((entry) => ({
|
|
227
|
-
...entry,
|
|
228
|
-
path: joinURL(modulePath, entry.path)
|
|
229
|
-
})));
|
|
230
|
-
if (message) messages.push(message);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
throw new Error(`Error searching in module at ${modulePath}: ${error.message}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return {
|
|
236
|
-
data: results,
|
|
237
|
-
message: messages.join("; ")
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
findModules(path, options) {
|
|
241
|
-
const maxDepth = Math.max(options?.maxDepth ?? DEFAULT_MAX_DEPTH, 1);
|
|
242
|
-
const matched = [];
|
|
243
|
-
for (const [modulePath, module] of this.modules) {
|
|
244
|
-
const pathSegments = path.split("/").filter(Boolean);
|
|
245
|
-
const modulePathSegments = modulePath.split("/").filter(Boolean);
|
|
246
|
-
let newMaxDepth;
|
|
247
|
-
let subpath;
|
|
248
|
-
let remainedModulePath;
|
|
249
|
-
if (!options?.exactMatch && modulePath.startsWith(path)) {
|
|
250
|
-
newMaxDepth = Math.max(0, maxDepth - (modulePathSegments.length - pathSegments.length));
|
|
251
|
-
subpath = "/";
|
|
252
|
-
remainedModulePath = joinURL("/", ...modulePathSegments.slice(pathSegments.length).slice(0, maxDepth));
|
|
253
|
-
} else if (path.startsWith(modulePath)) {
|
|
254
|
-
newMaxDepth = maxDepth;
|
|
255
|
-
subpath = joinURL("/", ...pathSegments.slice(modulePathSegments.length));
|
|
256
|
-
remainedModulePath = "/";
|
|
257
|
-
} else continue;
|
|
258
|
-
if (newMaxDepth < 0) continue;
|
|
259
|
-
matched.push({
|
|
260
|
-
module,
|
|
261
|
-
modulePath,
|
|
262
|
-
maxDepth: newMaxDepth,
|
|
263
|
-
subpath,
|
|
264
|
-
remainedModulePath
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
return matched;
|
|
268
|
-
}
|
|
269
|
-
async exec(path, args, options) {
|
|
270
|
-
const module = this.findModules(path)[0];
|
|
271
|
-
if (!module?.module.exec) throw new Error(`No module found for path: ${path}`);
|
|
272
|
-
return await module.module.exec(module.subpath, args, options);
|
|
273
|
-
}
|
|
274
|
-
buildSimpleListView(entries) {
|
|
275
|
-
return entries.map((entry) => `${entry.path}${this.buildMetadataSuffix(entry)}`);
|
|
276
|
-
}
|
|
277
|
-
buildTreeView(entries) {
|
|
278
|
-
const tree = {};
|
|
279
|
-
const entryMap = /* @__PURE__ */ new Map();
|
|
280
|
-
for (const entry of entries) {
|
|
281
|
-
entryMap.set(entry.path, entry);
|
|
282
|
-
const parts = entry.path.split("/").filter(Boolean);
|
|
283
|
-
let current = tree;
|
|
284
|
-
for (const part of parts) {
|
|
285
|
-
if (!current[part]) current[part] = {};
|
|
286
|
-
current = current[part];
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
const renderTree = (node, prefix = "", currentPath = "") => {
|
|
290
|
-
let result = "";
|
|
291
|
-
const keys = Object.keys(node);
|
|
292
|
-
keys.forEach((key, index) => {
|
|
293
|
-
const isLast = index === keys.length - 1;
|
|
294
|
-
const fullPath = currentPath ? `${currentPath}/${key}` : `/${key}`;
|
|
295
|
-
const entry = entryMap.get(fullPath);
|
|
296
|
-
result += `${prefix}${isLast ? "└── " : "├── "}${key}${entry ? this.buildMetadataSuffix(entry) : ""}`;
|
|
297
|
-
result += `\n`;
|
|
298
|
-
result += renderTree(node[key], `${prefix}${isLast ? " " : "│ "}`, fullPath);
|
|
299
|
-
});
|
|
300
|
-
return result;
|
|
301
|
-
};
|
|
302
|
-
return renderTree(tree);
|
|
303
|
-
}
|
|
304
|
-
buildMetadataSuffix(entry) {
|
|
305
|
-
const metadataParts = [];
|
|
306
|
-
const childrenCount = entry?.metadata?.childrenCount;
|
|
307
|
-
if (typeof childrenCount === "number") metadataParts.push(`${childrenCount} items`);
|
|
308
|
-
if (entry?.metadata?.childrenTruncated) metadataParts.push("truncated");
|
|
309
|
-
if (entry?.metadata?.gitignored) metadataParts.push("gitignored");
|
|
310
|
-
if (entry?.metadata?.execute) metadataParts.push("executable");
|
|
311
|
-
return metadataParts.length > 0 ? ` [${metadataParts.join(", ")}]` : "";
|
|
312
|
-
}
|
|
313
|
-
physicalPath;
|
|
314
|
-
async initializePhysicalPath() {
|
|
315
|
-
this.physicalPath ??= (async () => {
|
|
316
|
-
const path = await import("node:path");
|
|
317
|
-
const os = await import("node:os");
|
|
318
|
-
const fs = await import("node:fs/promises");
|
|
319
|
-
const rootDir = path.join(os.tmpdir(), v7());
|
|
320
|
-
await fs.mkdir(rootDir, { recursive: true });
|
|
321
|
-
for (const [modulePath, module] of this.modules) {
|
|
322
|
-
const physicalModulePath = path.join(rootDir, modulePath);
|
|
323
|
-
await fs.mkdir(path.dirname(physicalModulePath), { recursive: true });
|
|
324
|
-
await module.symlinkToPhysical?.(physicalModulePath);
|
|
325
|
-
}
|
|
326
|
-
return rootDir;
|
|
327
|
-
})();
|
|
328
|
-
return this.physicalPath;
|
|
329
|
-
}
|
|
330
|
-
async cleanupPhysicalPath() {
|
|
331
|
-
if (this.physicalPath) {
|
|
332
|
-
await (await import("node:fs/promises")).rm(await this.physicalPath, {
|
|
333
|
-
recursive: true,
|
|
334
|
-
force: true
|
|
335
|
-
});
|
|
336
|
-
this.physicalPath = void 0;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
//#endregion
|
|
342
|
-
export { AFS, AFSError, AFSReadonlyError, accessModeSchema, afsEntrySchema };
|
|
343
|
-
//# sourceMappingURL=index.mjs.map
|
|
17
|
+
export { AFS, AFSBaseProvider, AFSError, AFSMountError, AFSNotFoundError, AFSPathError, AFSReadonlyError, AFSValidationError, Actions, Delete, Exec, Explain, KINDS_SEGMENT, KindError, List, META_SEGMENT, Meta, ProviderRegistry, ProviderRouter, Read, Rename, Search, Stat, WELL_KNOWN_KINDS, WELL_KNOWN_KINDS_MAP, Write, accessModeSchema, actionSummarySchema, afsDocument, afsEntrySchema, afsExecutable, afsImage, afsLink, afsNode, clearRoutes, combineValidationResults, commonMetaSchema, createKindResolver, defaultKindResolver, defineKind, getInheritanceChain, getNodePathFromMetaPath, getRoutes, getWellKnownKind, isCanonicalPath, isKindsPath, isMetaPath, isWellKnownKind, isWorldMappingCapable, normalizePath, parseCanonicalPath, parseMetaPath, resolveKindSchema, toCanonicalPath, validateModuleName, validateNodes, validatePath };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
let node_fs = require("node:fs");
|
|
2
|
+
let node_path = require("node:path");
|
|
3
|
+
|
|
4
|
+
//#region src/loader/index.ts
|
|
5
|
+
/**
|
|
6
|
+
* AFS Provider Dynamic Loader
|
|
7
|
+
*
|
|
8
|
+
* Provides utilities for dynamically loading AFS providers at runtime.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { loadProvider, getProviderSchema } from "@aigne/afs/loader";
|
|
13
|
+
*
|
|
14
|
+
* // Load a provider with configuration
|
|
15
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
16
|
+
* config: { localPath: "./data" },
|
|
17
|
+
* basePath: "/path/to/config/dir"
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Get provider schema for validation
|
|
21
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a package specifier to an importable path.
|
|
26
|
+
* If the specifier is a directory path (e.g. from npm install),
|
|
27
|
+
* read its package.json to find the ESM entry point.
|
|
28
|
+
* We must use the ESM (.mjs) entry, not CJS (.cjs), because
|
|
29
|
+
* importing CJS from ESM wraps module.exports in an extra default layer
|
|
30
|
+
* which breaks the expected export shape.
|
|
31
|
+
*/
|
|
32
|
+
function resolveImportPath(specifier) {
|
|
33
|
+
if (!specifier.startsWith("/")) return specifier;
|
|
34
|
+
const pkgJsonPath = (0, node_path.join)(specifier, "package.json");
|
|
35
|
+
if (!(0, node_fs.existsSync)(pkgJsonPath)) return specifier;
|
|
36
|
+
try {
|
|
37
|
+
const pkg = JSON.parse((0, node_fs.readFileSync)(pkgJsonPath, "utf-8"));
|
|
38
|
+
const esmEntry = typeof pkg.exports === "object" && pkg.exports["."]?.import || pkg.module;
|
|
39
|
+
if (esmEntry) return (0, node_path.join)(specifier, esmEntry);
|
|
40
|
+
if (pkg.main) return (0, node_path.join)(specifier, pkg.main);
|
|
41
|
+
} catch {}
|
|
42
|
+
return specifier;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Dynamically load an AFS Provider from a package.
|
|
46
|
+
*
|
|
47
|
+
* @param packageName - Package name or subpath (e.g., "@aigne/afs-fs" or "@aigne/afs-cloud/s3")
|
|
48
|
+
* @param options - Load options (optional)
|
|
49
|
+
* @returns Provider instance
|
|
50
|
+
*
|
|
51
|
+
* @throws Error if package doesn't exist or doesn't export a valid AFS Provider
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
56
|
+
* config: { localPath: "./data" },
|
|
57
|
+
* basePath: "/path/to/config/dir"
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
async function loadProvider(packageName, options) {
|
|
62
|
+
const importPath = resolveImportPath(packageName);
|
|
63
|
+
let module;
|
|
64
|
+
try {
|
|
65
|
+
module = await import(importPath);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`Failed to import package "${packageName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
const ProviderClass = module.default;
|
|
70
|
+
if (!ProviderClass || typeof ProviderClass.load !== "function") throw new Error(`Package "${packageName}" does not export a valid AFS Provider. Expected default export with static load() method.`);
|
|
71
|
+
return ProviderClass.load(options ?? {});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the configuration schema for an AFS Provider without creating an instance.
|
|
75
|
+
*
|
|
76
|
+
* Useful for:
|
|
77
|
+
* - Configuration validation
|
|
78
|
+
* - Documentation generation
|
|
79
|
+
* - IDE integration
|
|
80
|
+
*
|
|
81
|
+
* @param packageName - Package name or subpath
|
|
82
|
+
* @returns Zod schema for the provider's configuration
|
|
83
|
+
*
|
|
84
|
+
* @throws Error if package doesn't export schema() method
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
89
|
+
* const result = schema.safeParse(config);
|
|
90
|
+
* if (!result.success) {
|
|
91
|
+
* console.error(result.error);
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async function getProviderSchema(packageName) {
|
|
96
|
+
const importPath = resolveImportPath(packageName);
|
|
97
|
+
let module;
|
|
98
|
+
try {
|
|
99
|
+
module = await import(importPath);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new Error(`Failed to import package "${packageName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
}
|
|
103
|
+
const ProviderClass = module.default;
|
|
104
|
+
if (!ProviderClass || typeof ProviderClass.schema !== "function") throw new Error(`Package "${packageName}" does not export schema() method.`);
|
|
105
|
+
return ProviderClass.schema();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
exports.getProviderSchema = getProviderSchema;
|
|
110
|
+
exports.loadProvider = loadProvider;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AFSModule, AFSModuleLoadParams } from "../type.cjs";
|
|
2
|
+
import { ZodType } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/loader/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Dynamically load an AFS Provider from a package.
|
|
7
|
+
*
|
|
8
|
+
* @param packageName - Package name or subpath (e.g., "@aigne/afs-fs" or "@aigne/afs-cloud/s3")
|
|
9
|
+
* @param options - Load options (optional)
|
|
10
|
+
* @returns Provider instance
|
|
11
|
+
*
|
|
12
|
+
* @throws Error if package doesn't exist or doesn't export a valid AFS Provider
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
17
|
+
* config: { localPath: "./data" },
|
|
18
|
+
* basePath: "/path/to/config/dir"
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function loadProvider<T extends AFSModule = AFSModule>(packageName: string, options?: AFSModuleLoadParams): Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the configuration schema for an AFS Provider without creating an instance.
|
|
25
|
+
*
|
|
26
|
+
* Useful for:
|
|
27
|
+
* - Configuration validation
|
|
28
|
+
* - Documentation generation
|
|
29
|
+
* - IDE integration
|
|
30
|
+
*
|
|
31
|
+
* @param packageName - Package name or subpath
|
|
32
|
+
* @returns Zod schema for the provider's configuration
|
|
33
|
+
*
|
|
34
|
+
* @throws Error if package doesn't export schema() method
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
39
|
+
* const result = schema.safeParse(config);
|
|
40
|
+
* if (!result.success) {
|
|
41
|
+
* console.error(result.error);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function getProviderSchema(packageName: string): Promise<ZodType<unknown>>;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { type AFSModuleLoadParams, getProviderSchema, loadProvider };
|
|
48
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/loader/index.ts"],"mappings":";;;;;;AA6HA;;;;;;;;;;;;;;;iBArDsB,YAAA,WAAuB,SAAA,GAAY,SAAA,CAAA,CACvD,WAAA,UACA,OAAA,GAAU,mBAAA,GACT,OAAA,CAAQ,CAAA;;;;;;;;;;;;;;;;;;;;;;;iBAkDW,iBAAA,CAAkB,WAAA,WAAsB,OAAA,CAAQ,OAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AFSModule, AFSModuleLoadParams } from "../type.mjs";
|
|
2
|
+
import { ZodType } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/loader/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Dynamically load an AFS Provider from a package.
|
|
7
|
+
*
|
|
8
|
+
* @param packageName - Package name or subpath (e.g., "@aigne/afs-fs" or "@aigne/afs-cloud/s3")
|
|
9
|
+
* @param options - Load options (optional)
|
|
10
|
+
* @returns Provider instance
|
|
11
|
+
*
|
|
12
|
+
* @throws Error if package doesn't exist or doesn't export a valid AFS Provider
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
17
|
+
* config: { localPath: "./data" },
|
|
18
|
+
* basePath: "/path/to/config/dir"
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function loadProvider<T extends AFSModule = AFSModule>(packageName: string, options?: AFSModuleLoadParams): Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the configuration schema for an AFS Provider without creating an instance.
|
|
25
|
+
*
|
|
26
|
+
* Useful for:
|
|
27
|
+
* - Configuration validation
|
|
28
|
+
* - Documentation generation
|
|
29
|
+
* - IDE integration
|
|
30
|
+
*
|
|
31
|
+
* @param packageName - Package name or subpath
|
|
32
|
+
* @returns Zod schema for the provider's configuration
|
|
33
|
+
*
|
|
34
|
+
* @throws Error if package doesn't export schema() method
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
39
|
+
* const result = schema.safeParse(config);
|
|
40
|
+
* if (!result.success) {
|
|
41
|
+
* console.error(result.error);
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function getProviderSchema(packageName: string): Promise<ZodType<unknown>>;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { type AFSModuleLoadParams, getProviderSchema, loadProvider };
|
|
48
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/loader/index.ts"],"mappings":";;;;;;AA6HA;;;;;;;;;;;;;;;iBArDsB,YAAA,WAAuB,SAAA,GAAY,SAAA,CAAA,CACvD,WAAA,UACA,OAAA,GAAU,mBAAA,GACT,OAAA,CAAQ,CAAA;;;;;;;;;;;;;;;;;;;;;;;iBAkDW,iBAAA,CAAkB,WAAA,WAAsB,OAAA,CAAQ,OAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
//#region src/loader/index.ts
|
|
5
|
+
/**
|
|
6
|
+
* AFS Provider Dynamic Loader
|
|
7
|
+
*
|
|
8
|
+
* Provides utilities for dynamically loading AFS providers at runtime.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { loadProvider, getProviderSchema } from "@aigne/afs/loader";
|
|
13
|
+
*
|
|
14
|
+
* // Load a provider with configuration
|
|
15
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
16
|
+
* config: { localPath: "./data" },
|
|
17
|
+
* basePath: "/path/to/config/dir"
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Get provider schema for validation
|
|
21
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a package specifier to an importable path.
|
|
26
|
+
* If the specifier is a directory path (e.g. from npm install),
|
|
27
|
+
* read its package.json to find the ESM entry point.
|
|
28
|
+
* We must use the ESM (.mjs) entry, not CJS (.cjs), because
|
|
29
|
+
* importing CJS from ESM wraps module.exports in an extra default layer
|
|
30
|
+
* which breaks the expected export shape.
|
|
31
|
+
*/
|
|
32
|
+
function resolveImportPath(specifier) {
|
|
33
|
+
if (!specifier.startsWith("/")) return specifier;
|
|
34
|
+
const pkgJsonPath = join(specifier, "package.json");
|
|
35
|
+
if (!existsSync(pkgJsonPath)) return specifier;
|
|
36
|
+
try {
|
|
37
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
38
|
+
const esmEntry = typeof pkg.exports === "object" && pkg.exports["."]?.import || pkg.module;
|
|
39
|
+
if (esmEntry) return join(specifier, esmEntry);
|
|
40
|
+
if (pkg.main) return join(specifier, pkg.main);
|
|
41
|
+
} catch {}
|
|
42
|
+
return specifier;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Dynamically load an AFS Provider from a package.
|
|
46
|
+
*
|
|
47
|
+
* @param packageName - Package name or subpath (e.g., "@aigne/afs-fs" or "@aigne/afs-cloud/s3")
|
|
48
|
+
* @param options - Load options (optional)
|
|
49
|
+
* @returns Provider instance
|
|
50
|
+
*
|
|
51
|
+
* @throws Error if package doesn't exist or doesn't export a valid AFS Provider
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const fs = await loadProvider("@aigne/afs-fs", {
|
|
56
|
+
* config: { localPath: "./data" },
|
|
57
|
+
* basePath: "/path/to/config/dir"
|
|
58
|
+
* });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
async function loadProvider(packageName, options) {
|
|
62
|
+
const importPath = resolveImportPath(packageName);
|
|
63
|
+
let module;
|
|
64
|
+
try {
|
|
65
|
+
module = await import(importPath);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`Failed to import package "${packageName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
const ProviderClass = module.default;
|
|
70
|
+
if (!ProviderClass || typeof ProviderClass.load !== "function") throw new Error(`Package "${packageName}" does not export a valid AFS Provider. Expected default export with static load() method.`);
|
|
71
|
+
return ProviderClass.load(options ?? {});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the configuration schema for an AFS Provider without creating an instance.
|
|
75
|
+
*
|
|
76
|
+
* Useful for:
|
|
77
|
+
* - Configuration validation
|
|
78
|
+
* - Documentation generation
|
|
79
|
+
* - IDE integration
|
|
80
|
+
*
|
|
81
|
+
* @param packageName - Package name or subpath
|
|
82
|
+
* @returns Zod schema for the provider's configuration
|
|
83
|
+
*
|
|
84
|
+
* @throws Error if package doesn't export schema() method
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const schema = await getProviderSchema("@aigne/afs-fs");
|
|
89
|
+
* const result = schema.safeParse(config);
|
|
90
|
+
* if (!result.success) {
|
|
91
|
+
* console.error(result.error);
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async function getProviderSchema(packageName) {
|
|
96
|
+
const importPath = resolveImportPath(packageName);
|
|
97
|
+
let module;
|
|
98
|
+
try {
|
|
99
|
+
module = await import(importPath);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new Error(`Failed to import package "${packageName}": ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
}
|
|
103
|
+
const ProviderClass = module.default;
|
|
104
|
+
if (!ProviderClass || typeof ProviderClass.schema !== "function") throw new Error(`Package "${packageName}" does not export schema() method.`);
|
|
105
|
+
return ProviderClass.schema();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
export { getProviderSchema, loadProvider };
|
|
110
|
+
//# sourceMappingURL=index.mjs.map
|