@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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { JSONSchema7 } from "../node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/schema.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Extract the list of top-level property names marked as sensitive.
|
|
6
|
+
*
|
|
7
|
+
* Works with both flat schemas and nested schemas (e.g. credentials.accessKeyId).
|
|
8
|
+
* For nested objects, returns dot-notation paths (e.g. "credentials.accessKeyId").
|
|
9
|
+
*
|
|
10
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
11
|
+
* @returns array of sensitive field paths
|
|
12
|
+
*/
|
|
13
|
+
declare function getSensitiveFields(schema: JSONSchema7): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Extract environment variable mappings from a JSON Schema.
|
|
16
|
+
*
|
|
17
|
+
* Returns a map from field path to array of env variable names.
|
|
18
|
+
* Only includes fields that have `env` metadata set.
|
|
19
|
+
*
|
|
20
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
21
|
+
* @returns map of field path → env variable names
|
|
22
|
+
*/
|
|
23
|
+
declare function getEnvMappings(schema: JSONSchema7): Record<string, string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve environment variables for schema fields that declare `env` metadata.
|
|
26
|
+
*
|
|
27
|
+
* For each field with env mapping, checks process.env for the first matching variable.
|
|
28
|
+
* Only returns fields where an env variable was found.
|
|
29
|
+
*
|
|
30
|
+
* @param schema - JSON Schema with env metadata
|
|
31
|
+
* @param env - Environment variables (defaults to process.env)
|
|
32
|
+
* @returns resolved field values from environment
|
|
33
|
+
*/
|
|
34
|
+
declare function resolveEnvFromSchema(schema: JSONSchema7, env?: Record<string, string | undefined>): Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Reserved key for passing sensitiveArgs annotations through mount.options.
|
|
37
|
+
* Used by CLI --sensitive-args and exec mount actions to annotate which
|
|
38
|
+
* user-provided options are sensitive (for ad-hoc schema construction).
|
|
39
|
+
*/
|
|
40
|
+
declare const SENSITIVE_ARGS_KEY = "_sensitiveArgs";
|
|
41
|
+
/**
|
|
42
|
+
* Build an ad-hoc JSON Schema from user-provided key-value pairs and sensitiveArgs.
|
|
43
|
+
*
|
|
44
|
+
* Used when a provider has no native schema() and no registry manifest schema,
|
|
45
|
+
* e.g., generic MCP servers mounted via direct URI with extra options.
|
|
46
|
+
*
|
|
47
|
+
* @param values - Key-value pairs provided by the user
|
|
48
|
+
* @param sensitiveArgs - Field names that should be marked as sensitive
|
|
49
|
+
* @returns JSON Schema with properties derived from values
|
|
50
|
+
*/
|
|
51
|
+
declare function buildAdHocSchema(values: Record<string, unknown>, sensitiveArgs?: string[]): JSONSchema7;
|
|
52
|
+
/**
|
|
53
|
+
* Separate values into sensitive and non-sensitive groups based on schema metadata.
|
|
54
|
+
*
|
|
55
|
+
* @param schema - JSON Schema with sensitive metadata
|
|
56
|
+
* @param values - Values to separate
|
|
57
|
+
* @returns object with `sensitive` and `nonSensitive` value groups
|
|
58
|
+
*/
|
|
59
|
+
declare function separateSensitiveValues(schema: JSONSchema7, values: Record<string, unknown>): {
|
|
60
|
+
sensitive: Record<string, string>;
|
|
61
|
+
nonSensitive: Record<string, unknown>;
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { SENSITIVE_ARGS_KEY, buildAdHocSchema, getEnvMappings, getSensitiveFields, resolveEnvFromSchema, separateSensitiveValues };
|
|
65
|
+
//# sourceMappingURL=schema.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.cts","names":[],"sources":["../../src/utils/schema.ts"],"mappings":";;;AAiEA;;;;;;;;;AAAA,iBApCgB,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;;;;;;;;iBAoC3B,cAAA,CAAe,MAAA,EAAQ,WAAA,GAAc,MAAA;;;;;AAkErD;;;;;AAYA;iBArCgB,oBAAA,CACd,MAAA,EAAQ,WAAA,EACR,GAAA,GAAK,MAAA,+BACJ,MAAA;;;;;;cAsBU,kBAAA;;;AA2Cb;;;;;;;;iBA/BgB,gBAAA,CACd,MAAA,EAAQ,MAAA,mBACR,aAAA,cACC,WAAA;;;;;;;;iBA4Ba,uBAAA,CACd,MAAA,EAAQ,WAAA,EACR,MAAA,EAAQ,MAAA;EACL,SAAA,EAAW,MAAA;EAAwB,YAAA,EAAc,MAAA;AAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { JSONSchema7 } from "../node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/schema.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Extract the list of top-level property names marked as sensitive.
|
|
6
|
+
*
|
|
7
|
+
* Works with both flat schemas and nested schemas (e.g. credentials.accessKeyId).
|
|
8
|
+
* For nested objects, returns dot-notation paths (e.g. "credentials.accessKeyId").
|
|
9
|
+
*
|
|
10
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
11
|
+
* @returns array of sensitive field paths
|
|
12
|
+
*/
|
|
13
|
+
declare function getSensitiveFields(schema: JSONSchema7): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Extract environment variable mappings from a JSON Schema.
|
|
16
|
+
*
|
|
17
|
+
* Returns a map from field path to array of env variable names.
|
|
18
|
+
* Only includes fields that have `env` metadata set.
|
|
19
|
+
*
|
|
20
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
21
|
+
* @returns map of field path → env variable names
|
|
22
|
+
*/
|
|
23
|
+
declare function getEnvMappings(schema: JSONSchema7): Record<string, string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve environment variables for schema fields that declare `env` metadata.
|
|
26
|
+
*
|
|
27
|
+
* For each field with env mapping, checks process.env for the first matching variable.
|
|
28
|
+
* Only returns fields where an env variable was found.
|
|
29
|
+
*
|
|
30
|
+
* @param schema - JSON Schema with env metadata
|
|
31
|
+
* @param env - Environment variables (defaults to process.env)
|
|
32
|
+
* @returns resolved field values from environment
|
|
33
|
+
*/
|
|
34
|
+
declare function resolveEnvFromSchema(schema: JSONSchema7, env?: Record<string, string | undefined>): Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* Reserved key for passing sensitiveArgs annotations through mount.options.
|
|
37
|
+
* Used by CLI --sensitive-args and exec mount actions to annotate which
|
|
38
|
+
* user-provided options are sensitive (for ad-hoc schema construction).
|
|
39
|
+
*/
|
|
40
|
+
declare const SENSITIVE_ARGS_KEY = "_sensitiveArgs";
|
|
41
|
+
/**
|
|
42
|
+
* Build an ad-hoc JSON Schema from user-provided key-value pairs and sensitiveArgs.
|
|
43
|
+
*
|
|
44
|
+
* Used when a provider has no native schema() and no registry manifest schema,
|
|
45
|
+
* e.g., generic MCP servers mounted via direct URI with extra options.
|
|
46
|
+
*
|
|
47
|
+
* @param values - Key-value pairs provided by the user
|
|
48
|
+
* @param sensitiveArgs - Field names that should be marked as sensitive
|
|
49
|
+
* @returns JSON Schema with properties derived from values
|
|
50
|
+
*/
|
|
51
|
+
declare function buildAdHocSchema(values: Record<string, unknown>, sensitiveArgs?: string[]): JSONSchema7;
|
|
52
|
+
/**
|
|
53
|
+
* Separate values into sensitive and non-sensitive groups based on schema metadata.
|
|
54
|
+
*
|
|
55
|
+
* @param schema - JSON Schema with sensitive metadata
|
|
56
|
+
* @param values - Values to separate
|
|
57
|
+
* @returns object with `sensitive` and `nonSensitive` value groups
|
|
58
|
+
*/
|
|
59
|
+
declare function separateSensitiveValues(schema: JSONSchema7, values: Record<string, unknown>): {
|
|
60
|
+
sensitive: Record<string, string>;
|
|
61
|
+
nonSensitive: Record<string, unknown>;
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { SENSITIVE_ARGS_KEY, buildAdHocSchema, getEnvMappings, getSensitiveFields, resolveEnvFromSchema, separateSensitiveValues };
|
|
65
|
+
//# sourceMappingURL=schema.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.mts","names":[],"sources":["../../src/utils/schema.ts"],"mappings":";;;AAiEA;;;;;;;;;AAAA,iBApCgB,kBAAA,CAAmB,MAAA,EAAQ,WAAA;;;;;;;;;;iBAoC3B,cAAA,CAAe,MAAA,EAAQ,WAAA,GAAc,MAAA;;;;;AAkErD;;;;;AAYA;iBArCgB,oBAAA,CACd,MAAA,EAAQ,WAAA,EACR,GAAA,GAAK,MAAA,+BACJ,MAAA;;;;;;cAsBU,kBAAA;;;AA2Cb;;;;;;;;iBA/BgB,gBAAA,CACd,MAAA,EAAQ,MAAA,mBACR,aAAA,cACC,WAAA;;;;;;;;iBA4Ba,uBAAA,CACd,MAAA,EAAQ,WAAA,EACR,MAAA,EAAQ,MAAA;EACL,SAAA,EAAW,MAAA;EAAwB,YAAA,EAAc,MAAA;AAAA"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//#region src/utils/schema.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract the list of top-level property names marked as sensitive.
|
|
4
|
+
*
|
|
5
|
+
* Works with both flat schemas and nested schemas (e.g. credentials.accessKeyId).
|
|
6
|
+
* For nested objects, returns dot-notation paths (e.g. "credentials.accessKeyId").
|
|
7
|
+
*
|
|
8
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
9
|
+
* @returns array of sensitive field paths
|
|
10
|
+
*/
|
|
11
|
+
function getSensitiveFields(schema) {
|
|
12
|
+
const result = [];
|
|
13
|
+
collectSensitiveFields(schema, "", result);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
function collectSensitiveFields(schema, prefix, result) {
|
|
17
|
+
if (typeof schema !== "object" || schema === null) return;
|
|
18
|
+
const properties = schema.properties;
|
|
19
|
+
if (!properties || typeof properties !== "object") return;
|
|
20
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
21
|
+
const prop = propSchema;
|
|
22
|
+
const fieldPath = prefix ? `${prefix}.${key}` : key;
|
|
23
|
+
if (prop.sensitive === true) result.push(fieldPath);
|
|
24
|
+
if (prop.type === "object" && prop.properties) collectSensitiveFields(prop, fieldPath, result);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract environment variable mappings from a JSON Schema.
|
|
29
|
+
*
|
|
30
|
+
* Returns a map from field path to array of env variable names.
|
|
31
|
+
* Only includes fields that have `env` metadata set.
|
|
32
|
+
*
|
|
33
|
+
* @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)
|
|
34
|
+
* @returns map of field path → env variable names
|
|
35
|
+
*/
|
|
36
|
+
function getEnvMappings(schema) {
|
|
37
|
+
const result = {};
|
|
38
|
+
collectEnvMappings(schema, "", result);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
function collectEnvMappings(schema, prefix, result) {
|
|
42
|
+
if (typeof schema !== "object" || schema === null) return;
|
|
43
|
+
const properties = schema.properties;
|
|
44
|
+
if (!properties || typeof properties !== "object") return;
|
|
45
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
46
|
+
const prop = propSchema;
|
|
47
|
+
const fieldPath = prefix ? `${prefix}.${key}` : key;
|
|
48
|
+
if (Array.isArray(prop.env) && prop.env.length > 0) result[fieldPath] = prop.env;
|
|
49
|
+
if (prop.type === "object" && prop.properties) collectEnvMappings(prop, fieldPath, result);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve environment variables for schema fields that declare `env` metadata.
|
|
54
|
+
*
|
|
55
|
+
* For each field with env mapping, checks process.env for the first matching variable.
|
|
56
|
+
* Only returns fields where an env variable was found.
|
|
57
|
+
*
|
|
58
|
+
* @param schema - JSON Schema with env metadata
|
|
59
|
+
* @param env - Environment variables (defaults to process.env)
|
|
60
|
+
* @returns resolved field values from environment
|
|
61
|
+
*/
|
|
62
|
+
function resolveEnvFromSchema(schema, env = process.env) {
|
|
63
|
+
const mappings = getEnvMappings(schema);
|
|
64
|
+
const resolved = {};
|
|
65
|
+
for (const [field, envVars] of Object.entries(mappings)) for (const envVar of envVars) {
|
|
66
|
+
const value = env[envVar];
|
|
67
|
+
if (value !== void 0 && value !== "") {
|
|
68
|
+
resolved[field] = value;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return resolved;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Reserved key for passing sensitiveArgs annotations through mount.options.
|
|
76
|
+
* Used by CLI --sensitive-args and exec mount actions to annotate which
|
|
77
|
+
* user-provided options are sensitive (for ad-hoc schema construction).
|
|
78
|
+
*/
|
|
79
|
+
const SENSITIVE_ARGS_KEY = "_sensitiveArgs";
|
|
80
|
+
/**
|
|
81
|
+
* Build an ad-hoc JSON Schema from user-provided key-value pairs and sensitiveArgs.
|
|
82
|
+
*
|
|
83
|
+
* Used when a provider has no native schema() and no registry manifest schema,
|
|
84
|
+
* e.g., generic MCP servers mounted via direct URI with extra options.
|
|
85
|
+
*
|
|
86
|
+
* @param values - Key-value pairs provided by the user
|
|
87
|
+
* @param sensitiveArgs - Field names that should be marked as sensitive
|
|
88
|
+
* @returns JSON Schema with properties derived from values
|
|
89
|
+
*/
|
|
90
|
+
function buildAdHocSchema(values, sensitiveArgs = []) {
|
|
91
|
+
const sensitiveSet = new Set(sensitiveArgs);
|
|
92
|
+
const properties = {};
|
|
93
|
+
for (const [key, value] of Object.entries(values)) {
|
|
94
|
+
const prop = { type: typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string" };
|
|
95
|
+
if (sensitiveSet.has(key)) prop.sensitive = true;
|
|
96
|
+
properties[key] = prop;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
type: "object",
|
|
100
|
+
properties
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Separate values into sensitive and non-sensitive groups based on schema metadata.
|
|
105
|
+
*
|
|
106
|
+
* @param schema - JSON Schema with sensitive metadata
|
|
107
|
+
* @param values - Values to separate
|
|
108
|
+
* @returns object with `sensitive` and `nonSensitive` value groups
|
|
109
|
+
*/
|
|
110
|
+
function separateSensitiveValues(schema, values) {
|
|
111
|
+
const sensitiveFields = new Set(getSensitiveFields(schema));
|
|
112
|
+
const sensitive = {};
|
|
113
|
+
const nonSensitive = {};
|
|
114
|
+
for (const [key, value] of Object.entries(values)) if (sensitiveFields.has(key)) sensitive[key] = String(value);
|
|
115
|
+
else nonSensitive[key] = value;
|
|
116
|
+
return {
|
|
117
|
+
sensitive,
|
|
118
|
+
nonSensitive
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
export { SENSITIVE_ARGS_KEY, buildAdHocSchema, getEnvMappings, getSensitiveFields, resolveEnvFromSchema, separateSensitiveValues };
|
|
124
|
+
//# sourceMappingURL=schema.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":[],"sources":["../../src/utils/schema.ts"],"sourcesContent":["/**\n * Schema utilities for extracting sensitive field metadata and env mappings\n * from JSON Schema output (produced by z.toJSONSchema()).\n *\n * Zod 4's .meta() transparently passes custom fields through to JSON Schema output.\n * These utilities read those fields to identify sensitive fields and environment variable bindings.\n */\n\nimport type { JSONSchema7 } from \"../meta/type.js\";\n\n/**\n * Extended JSON Schema property with AFS credential metadata.\n * Fields are passed through from Zod 4's .meta({ sensitive, env }).\n */\ninterface SchemaPropertyWithMeta {\n sensitive?: boolean;\n env?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Extract the list of top-level property names marked as sensitive.\n *\n * Works with both flat schemas and nested schemas (e.g. credentials.accessKeyId).\n * For nested objects, returns dot-notation paths (e.g. \"credentials.accessKeyId\").\n *\n * @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)\n * @returns array of sensitive field paths\n */\nexport function getSensitiveFields(schema: JSONSchema7): string[] {\n const result: string[] = [];\n collectSensitiveFields(schema, \"\", result);\n return result;\n}\n\nfunction collectSensitiveFields(schema: JSONSchema7, prefix: string, result: string[]): void {\n if (typeof schema !== \"object\" || schema === null) return;\n\n const properties = (schema as Record<string, any>).properties;\n if (!properties || typeof properties !== \"object\") return;\n\n for (const [key, propSchema] of Object.entries(properties)) {\n const prop = propSchema as SchemaPropertyWithMeta;\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n\n if (prop.sensitive === true) {\n result.push(fieldPath);\n }\n\n // Recurse into nested objects\n if (prop.type === \"object\" && prop.properties) {\n collectSensitiveFields(prop as JSONSchema7, fieldPath, result);\n }\n }\n}\n\n/**\n * Extract environment variable mappings from a JSON Schema.\n *\n * Returns a map from field path to array of env variable names.\n * Only includes fields that have `env` metadata set.\n *\n * @param schema - JSON Schema (from z.toJSONSchema() or manifest schema)\n * @returns map of field path → env variable names\n */\nexport function getEnvMappings(schema: JSONSchema7): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n collectEnvMappings(schema, \"\", result);\n return result;\n}\n\nfunction collectEnvMappings(\n schema: JSONSchema7,\n prefix: string,\n result: Record<string, string[]>,\n): void {\n if (typeof schema !== \"object\" || schema === null) return;\n\n const properties = (schema as Record<string, any>).properties;\n if (!properties || typeof properties !== \"object\") return;\n\n for (const [key, propSchema] of Object.entries(properties)) {\n const prop = propSchema as SchemaPropertyWithMeta;\n const fieldPath = prefix ? `${prefix}.${key}` : key;\n\n if (Array.isArray(prop.env) && prop.env.length > 0) {\n result[fieldPath] = prop.env;\n }\n\n // Recurse into nested objects\n if (prop.type === \"object\" && prop.properties) {\n collectEnvMappings(prop as JSONSchema7, fieldPath, result);\n }\n }\n}\n\n/**\n * Resolve environment variables for schema fields that declare `env` metadata.\n *\n * For each field with env mapping, checks process.env for the first matching variable.\n * Only returns fields where an env variable was found.\n *\n * @param schema - JSON Schema with env metadata\n * @param env - Environment variables (defaults to process.env)\n * @returns resolved field values from environment\n */\nexport function resolveEnvFromSchema(\n schema: JSONSchema7,\n env: Record<string, string | undefined> = process.env,\n): Record<string, string> {\n const mappings = getEnvMappings(schema);\n const resolved: Record<string, string> = {};\n\n for (const [field, envVars] of Object.entries(mappings)) {\n for (const envVar of envVars) {\n const value = env[envVar];\n if (value !== undefined && value !== \"\") {\n resolved[field] = value;\n break;\n }\n }\n }\n\n return resolved;\n}\n\n/**\n * Reserved key for passing sensitiveArgs annotations through mount.options.\n * Used by CLI --sensitive-args and exec mount actions to annotate which\n * user-provided options are sensitive (for ad-hoc schema construction).\n */\nexport const SENSITIVE_ARGS_KEY = \"_sensitiveArgs\";\n\n/**\n * Build an ad-hoc JSON Schema from user-provided key-value pairs and sensitiveArgs.\n *\n * Used when a provider has no native schema() and no registry manifest schema,\n * e.g., generic MCP servers mounted via direct URI with extra options.\n *\n * @param values - Key-value pairs provided by the user\n * @param sensitiveArgs - Field names that should be marked as sensitive\n * @returns JSON Schema with properties derived from values\n */\nexport function buildAdHocSchema(\n values: Record<string, unknown>,\n sensitiveArgs: string[] = [],\n): JSONSchema7 {\n const sensitiveSet = new Set(sensitiveArgs);\n const properties: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(values)) {\n const prop: Record<string, unknown> = {\n type:\n typeof value === \"number\" ? \"number\" : typeof value === \"boolean\" ? \"boolean\" : \"string\",\n };\n if (sensitiveSet.has(key)) {\n prop.sensitive = true;\n }\n properties[key] = prop;\n }\n\n return {\n type: \"object\",\n properties,\n } as JSONSchema7;\n}\n\n/**\n * Separate values into sensitive and non-sensitive groups based on schema metadata.\n *\n * @param schema - JSON Schema with sensitive metadata\n * @param values - Values to separate\n * @returns object with `sensitive` and `nonSensitive` value groups\n */\nexport function separateSensitiveValues(\n schema: JSONSchema7,\n values: Record<string, unknown>,\n): { sensitive: Record<string, string>; nonSensitive: Record<string, unknown> } {\n const sensitiveFields = new Set(getSensitiveFields(schema));\n const sensitive: Record<string, string> = {};\n const nonSensitive: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(values)) {\n if (sensitiveFields.has(key)) {\n sensitive[key] = String(value);\n } else {\n nonSensitive[key] = value;\n }\n }\n\n return { sensitive, nonSensitive };\n}\n"],"mappings":";;;;;;;;;;AA6BA,SAAgB,mBAAmB,QAA+B;CAChE,MAAM,SAAmB,EAAE;AAC3B,wBAAuB,QAAQ,IAAI,OAAO;AAC1C,QAAO;;AAGT,SAAS,uBAAuB,QAAqB,QAAgB,QAAwB;AAC3F,KAAI,OAAO,WAAW,YAAY,WAAW,KAAM;CAEnD,MAAM,aAAc,OAA+B;AACnD,KAAI,CAAC,cAAc,OAAO,eAAe,SAAU;AAEnD,MAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,WAAW,EAAE;EAC1D,MAAM,OAAO;EACb,MAAM,YAAY,SAAS,GAAG,OAAO,GAAG,QAAQ;AAEhD,MAAI,KAAK,cAAc,KACrB,QAAO,KAAK,UAAU;AAIxB,MAAI,KAAK,SAAS,YAAY,KAAK,WACjC,wBAAuB,MAAqB,WAAW,OAAO;;;;;;;;;;;;AAcpE,SAAgB,eAAe,QAA+C;CAC5E,MAAM,SAAmC,EAAE;AAC3C,oBAAmB,QAAQ,IAAI,OAAO;AACtC,QAAO;;AAGT,SAAS,mBACP,QACA,QACA,QACM;AACN,KAAI,OAAO,WAAW,YAAY,WAAW,KAAM;CAEnD,MAAM,aAAc,OAA+B;AACnD,KAAI,CAAC,cAAc,OAAO,eAAe,SAAU;AAEnD,MAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,WAAW,EAAE;EAC1D,MAAM,OAAO;EACb,MAAM,YAAY,SAAS,GAAG,OAAO,GAAG,QAAQ;AAEhD,MAAI,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,IAAI,SAAS,EAC/C,QAAO,aAAa,KAAK;AAI3B,MAAI,KAAK,SAAS,YAAY,KAAK,WACjC,oBAAmB,MAAqB,WAAW,OAAO;;;;;;;;;;;;;AAehE,SAAgB,qBACd,QACA,MAA0C,QAAQ,KAC1B;CACxB,MAAM,WAAW,eAAe,OAAO;CACvC,MAAM,WAAmC,EAAE;AAE3C,MAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,SAAS,CACrD,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,QAAQ,IAAI;AAClB,MAAI,UAAU,UAAa,UAAU,IAAI;AACvC,YAAS,SAAS;AAClB;;;AAKN,QAAO;;;;;;;AAQT,MAAa,qBAAqB;;;;;;;;;;;AAYlC,SAAgB,iBACd,QACA,gBAA0B,EAAE,EACf;CACb,MAAM,eAAe,IAAI,IAAI,cAAc;CAC3C,MAAM,aAAsC,EAAE;AAE9C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;EACjD,MAAM,OAAgC,EACpC,MACE,OAAO,UAAU,WAAW,WAAW,OAAO,UAAU,YAAY,YAAY,UACnF;AACD,MAAI,aAAa,IAAI,IAAI,CACvB,MAAK,YAAY;AAEnB,aAAW,OAAO;;AAGpB,QAAO;EACL,MAAM;EACN;EACD;;;;;;;;;AAUH,SAAgB,wBACd,QACA,QAC8E;CAC9E,MAAM,kBAAkB,IAAI,IAAI,mBAAmB,OAAO,CAAC;CAC3D,MAAM,YAAoC,EAAE;CAC5C,MAAM,eAAwC,EAAE;AAEhD,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC/C,KAAI,gBAAgB,IAAI,IAAI,CAC1B,WAAU,OAAO,OAAO,MAAM;KAE9B,cAAa,OAAO;AAIxB,QAAO;EAAE;EAAW;EAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-utils.d.cts","names":[],"sources":["../../src/utils/type-utils.ts"],"mappings":";KAAY,cAAA,MAAoB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,KAEhC,OAAA,MAAa,CAAA;AAAA,iBAET,KAAA,
|
|
1
|
+
{"version":3,"file":"type-utils.d.cts","names":[],"sources":["../../src/utils/type-utils.ts"],"mappings":";KAAY,cAAA,MAAoB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,KAEhC,OAAA,MAAa,CAAA;AAAA,iBAET,KAAA,CAAM,KAAA,YAAiB,KAAA;AAAA,iBAIvB,QAAA,GAAA,CAAY,KAAA,YAAiB,KAAA,IAAS,MAAA,SAAe,CAAA;AAAA,iBAIrD,OAAA,CAAQ,GAAA;AAAA,iBAOR,aAAA,GAAA,CAAiB,KAAA,EAAO,CAAA,GAAI,KAAA,IAAS,WAAA,CAAY,CAAA;AAAA,iBAIjD,GAAA,CAAI,GAAA,OAAU,IAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-utils.d.mts","names":[],"sources":["../../src/utils/type-utils.ts"],"mappings":";KAAY,cAAA,MAAoB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,KAEhC,OAAA,MAAa,CAAA;AAAA,iBAET,KAAA,
|
|
1
|
+
{"version":3,"file":"type-utils.d.mts","names":[],"sources":["../../src/utils/type-utils.ts"],"mappings":";KAAY,cAAA,MAAoB,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,KAEhC,OAAA,MAAa,CAAA;AAAA,iBAET,KAAA,CAAM,KAAA,YAAiB,KAAA;AAAA,iBAIvB,QAAA,GAAA,CAAY,KAAA,YAAiB,KAAA,IAAS,MAAA,SAAe,CAAA;AAAA,iBAIrD,OAAA,CAAQ,GAAA;AAAA,iBAOR,aAAA,GAAA,CAAiB,KAAA,EAAO,CAAA,GAAI,KAAA,IAAS,WAAA,CAAY,CAAA;AAAA,iBAIjD,GAAA,CAAI,GAAA,OAAU,IAAA"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/utils/uri-template.ts
|
|
3
|
+
/**
|
|
4
|
+
* Extract scheme from a URI template string.
|
|
5
|
+
* e.g. "s3://{bucket}/{prefix+?}" → "s3"
|
|
6
|
+
*/
|
|
7
|
+
function extractSchemeFromTemplate(template) {
|
|
8
|
+
const match = template.match(/^([a-z0-9][a-z0-9+.-]*):\/\//i);
|
|
9
|
+
if (!match?.[1]) throw new Error(`Invalid URI template: cannot extract scheme from "${template}"`);
|
|
10
|
+
return match[1].toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parse the variable definitions from a URI template's body part.
|
|
14
|
+
*/
|
|
15
|
+
function parseTemplateVariables(templateBody) {
|
|
16
|
+
const vars = [];
|
|
17
|
+
for (const match of templateBody.matchAll(/\{([^}]+)\}/g)) {
|
|
18
|
+
let name = match[1];
|
|
19
|
+
let greedy = false;
|
|
20
|
+
let optional = false;
|
|
21
|
+
if (name.endsWith("+?")) {
|
|
22
|
+
name = name.slice(0, -2);
|
|
23
|
+
greedy = true;
|
|
24
|
+
optional = true;
|
|
25
|
+
} else if (name.endsWith("+")) {
|
|
26
|
+
name = name.slice(0, -1);
|
|
27
|
+
greedy = true;
|
|
28
|
+
} else if (name.endsWith("?")) {
|
|
29
|
+
name = name.slice(0, -1);
|
|
30
|
+
optional = true;
|
|
31
|
+
}
|
|
32
|
+
vars.push({
|
|
33
|
+
name,
|
|
34
|
+
greedy,
|
|
35
|
+
optional
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return vars;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract the body pattern from a URI template (everything after scheme://).
|
|
42
|
+
*/
|
|
43
|
+
function getTemplateBody(template) {
|
|
44
|
+
const idx = template.indexOf("://");
|
|
45
|
+
if (idx < 0) throw new Error(`Invalid URI template: missing "://" in "${template}"`);
|
|
46
|
+
return template.slice(idx + 3);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse a URI body against a URI template, extracting named variables.
|
|
50
|
+
*
|
|
51
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
52
|
+
* @param body - URI body string, e.g. "my-bucket/a/b/c"
|
|
53
|
+
* @returns Record of variable name → value. Optional vars may be undefined.
|
|
54
|
+
* @throws if required variables cannot be extracted from body
|
|
55
|
+
*/
|
|
56
|
+
function parseTemplate(template, body) {
|
|
57
|
+
const vars = parseTemplateVariables(getTemplateBody(template));
|
|
58
|
+
if (vars.length === 0) return {};
|
|
59
|
+
const result = {};
|
|
60
|
+
const segments = body.split("/").filter((s) => s !== "");
|
|
61
|
+
if (vars.length === 1) {
|
|
62
|
+
const v = vars[0];
|
|
63
|
+
if (body === "" || segments.length === 0) if (v.optional) result[v.name] = void 0;
|
|
64
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but URI body is empty`);
|
|
65
|
+
else result[v.name] = body;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
let segIdx = 0;
|
|
69
|
+
for (let i = 0; i < vars.length; i++) {
|
|
70
|
+
const v = vars[i];
|
|
71
|
+
if (v.greedy) {
|
|
72
|
+
const remaining = segments.slice(segIdx);
|
|
73
|
+
if (remaining.length === 0) if (v.optional) result[v.name] = void 0;
|
|
74
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but no segments remain`);
|
|
75
|
+
else {
|
|
76
|
+
result[v.name] = remaining.join("/");
|
|
77
|
+
segIdx = segments.length;
|
|
78
|
+
}
|
|
79
|
+
} else if (segIdx < segments.length) {
|
|
80
|
+
result[v.name] = segments[segIdx];
|
|
81
|
+
segIdx++;
|
|
82
|
+
} else if (v.optional) result[v.name] = void 0;
|
|
83
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but no segments remain`);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build a URI from a template and variable values.
|
|
89
|
+
*
|
|
90
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
91
|
+
* @param vars - Record of variable name → value
|
|
92
|
+
* @returns Constructed URI string
|
|
93
|
+
* @throws if required variables are missing
|
|
94
|
+
*/
|
|
95
|
+
function buildURI(template, vars) {
|
|
96
|
+
const templateVars = parseTemplateVariables(getTemplateBody(template));
|
|
97
|
+
if (templateVars.length === 0) return template;
|
|
98
|
+
const scheme = extractSchemeFromTemplate(template);
|
|
99
|
+
const parts = [];
|
|
100
|
+
for (const v of templateVars) {
|
|
101
|
+
const value = vars[v.name];
|
|
102
|
+
if (value === void 0 || value === "") {
|
|
103
|
+
if (!v.optional) throw new Error(`buildURI: required variable "${v.name}" is missing for template "${template}"`);
|
|
104
|
+
} else parts.push(value);
|
|
105
|
+
}
|
|
106
|
+
return `${scheme}://${parts.join("/")}`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Extract variable names that appear in a URI template.
|
|
110
|
+
* Useful for determining which schema fields are "path variables".
|
|
111
|
+
*
|
|
112
|
+
* @param template - URI template string
|
|
113
|
+
* @returns Array of variable names (without +, ?, +? modifiers)
|
|
114
|
+
*/
|
|
115
|
+
function getTemplateVariableNames(template) {
|
|
116
|
+
return parseTemplateVariables(getTemplateBody(template)).map((v) => v.name);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//#endregion
|
|
120
|
+
exports.buildURI = buildURI;
|
|
121
|
+
exports.extractSchemeFromTemplate = extractSchemeFromTemplate;
|
|
122
|
+
exports.getTemplateVariableNames = getTemplateVariableNames;
|
|
123
|
+
exports.parseTemplate = parseTemplate;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region src/utils/uri-template.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* URI Template parser and builder.
|
|
4
|
+
*
|
|
5
|
+
* Supports AFS URI template variable syntax:
|
|
6
|
+
* - {param} — single segment (no /)
|
|
7
|
+
* - {param+} — multi-segment (greedy, may contain /)
|
|
8
|
+
* - {param?} — optional single segment
|
|
9
|
+
* - {param+?} — optional multi-segment (greedy)
|
|
10
|
+
*
|
|
11
|
+
* Disambiguation: non-greedy {param} consumes up to the next /;
|
|
12
|
+
* greedy {param+} consumes all remaining segments.
|
|
13
|
+
* In {a}/{b+?}, a takes the first segment, b takes the rest (if any).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Extract scheme from a URI template string.
|
|
17
|
+
* e.g. "s3://{bucket}/{prefix+?}" → "s3"
|
|
18
|
+
*/
|
|
19
|
+
declare function extractSchemeFromTemplate(template: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Parse a URI body against a URI template, extracting named variables.
|
|
22
|
+
*
|
|
23
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
24
|
+
* @param body - URI body string, e.g. "my-bucket/a/b/c"
|
|
25
|
+
* @returns Record of variable name → value. Optional vars may be undefined.
|
|
26
|
+
* @throws if required variables cannot be extracted from body
|
|
27
|
+
*/
|
|
28
|
+
declare function parseTemplate(template: string, body: string): Record<string, string | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* Build a URI from a template and variable values.
|
|
31
|
+
*
|
|
32
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
33
|
+
* @param vars - Record of variable name → value
|
|
34
|
+
* @returns Constructed URI string
|
|
35
|
+
* @throws if required variables are missing
|
|
36
|
+
*/
|
|
37
|
+
declare function buildURI(template: string, vars: Record<string, string | undefined>): string;
|
|
38
|
+
/**
|
|
39
|
+
* Extract variable names that appear in a URI template.
|
|
40
|
+
* Useful for determining which schema fields are "path variables".
|
|
41
|
+
*
|
|
42
|
+
* @param template - URI template string
|
|
43
|
+
* @returns Array of variable names (without +, ?, +? modifiers)
|
|
44
|
+
*/
|
|
45
|
+
declare function getTemplateVariableNames(template: string): string[];
|
|
46
|
+
//#endregion
|
|
47
|
+
export { buildURI, extractSchemeFromTemplate, getTemplateVariableNames, parseTemplate };
|
|
48
|
+
//# sourceMappingURL=uri-template.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uri-template.d.cts","names":[],"sources":["../../src/utils/uri-template.ts"],"mappings":";;AAwBA;;;;;AA0DA;;;;;;;;;AA0EA;;iBApIgB,yBAAA,CAA0B,QAAA;;;;;;;AAyK1C;;iBA/GgB,aAAA,CAAc,QAAA,UAAkB,IAAA,WAAe,MAAA;;;;;;;;;iBA0E/C,QAAA,CAAS,QAAA,UAAkB,IAAA,EAAM,MAAA;;;;;;;;iBAqCjC,wBAAA,CAAyB,QAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region src/utils/uri-template.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* URI Template parser and builder.
|
|
4
|
+
*
|
|
5
|
+
* Supports AFS URI template variable syntax:
|
|
6
|
+
* - {param} — single segment (no /)
|
|
7
|
+
* - {param+} — multi-segment (greedy, may contain /)
|
|
8
|
+
* - {param?} — optional single segment
|
|
9
|
+
* - {param+?} — optional multi-segment (greedy)
|
|
10
|
+
*
|
|
11
|
+
* Disambiguation: non-greedy {param} consumes up to the next /;
|
|
12
|
+
* greedy {param+} consumes all remaining segments.
|
|
13
|
+
* In {a}/{b+?}, a takes the first segment, b takes the rest (if any).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Extract scheme from a URI template string.
|
|
17
|
+
* e.g. "s3://{bucket}/{prefix+?}" → "s3"
|
|
18
|
+
*/
|
|
19
|
+
declare function extractSchemeFromTemplate(template: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Parse a URI body against a URI template, extracting named variables.
|
|
22
|
+
*
|
|
23
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
24
|
+
* @param body - URI body string, e.g. "my-bucket/a/b/c"
|
|
25
|
+
* @returns Record of variable name → value. Optional vars may be undefined.
|
|
26
|
+
* @throws if required variables cannot be extracted from body
|
|
27
|
+
*/
|
|
28
|
+
declare function parseTemplate(template: string, body: string): Record<string, string | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* Build a URI from a template and variable values.
|
|
31
|
+
*
|
|
32
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
33
|
+
* @param vars - Record of variable name → value
|
|
34
|
+
* @returns Constructed URI string
|
|
35
|
+
* @throws if required variables are missing
|
|
36
|
+
*/
|
|
37
|
+
declare function buildURI(template: string, vars: Record<string, string | undefined>): string;
|
|
38
|
+
/**
|
|
39
|
+
* Extract variable names that appear in a URI template.
|
|
40
|
+
* Useful for determining which schema fields are "path variables".
|
|
41
|
+
*
|
|
42
|
+
* @param template - URI template string
|
|
43
|
+
* @returns Array of variable names (without +, ?, +? modifiers)
|
|
44
|
+
*/
|
|
45
|
+
declare function getTemplateVariableNames(template: string): string[];
|
|
46
|
+
//#endregion
|
|
47
|
+
export { buildURI, extractSchemeFromTemplate, getTemplateVariableNames, parseTemplate };
|
|
48
|
+
//# sourceMappingURL=uri-template.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uri-template.d.mts","names":[],"sources":["../../src/utils/uri-template.ts"],"mappings":";;AAwBA;;;;;AA0DA;;;;;;;;;AA0EA;;iBApIgB,yBAAA,CAA0B,QAAA;;;;;;;AAyK1C;;iBA/GgB,aAAA,CAAc,QAAA,UAAkB,IAAA,WAAe,MAAA;;;;;;;;;iBA0E/C,QAAA,CAAS,QAAA,UAAkB,IAAA,EAAM,MAAA;;;;;;;;iBAqCjC,wBAAA,CAAyB,QAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
//#region src/utils/uri-template.ts
|
|
2
|
+
/**
|
|
3
|
+
* Extract scheme from a URI template string.
|
|
4
|
+
* e.g. "s3://{bucket}/{prefix+?}" → "s3"
|
|
5
|
+
*/
|
|
6
|
+
function extractSchemeFromTemplate(template) {
|
|
7
|
+
const match = template.match(/^([a-z0-9][a-z0-9+.-]*):\/\//i);
|
|
8
|
+
if (!match?.[1]) throw new Error(`Invalid URI template: cannot extract scheme from "${template}"`);
|
|
9
|
+
return match[1].toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse the variable definitions from a URI template's body part.
|
|
13
|
+
*/
|
|
14
|
+
function parseTemplateVariables(templateBody) {
|
|
15
|
+
const vars = [];
|
|
16
|
+
for (const match of templateBody.matchAll(/\{([^}]+)\}/g)) {
|
|
17
|
+
let name = match[1];
|
|
18
|
+
let greedy = false;
|
|
19
|
+
let optional = false;
|
|
20
|
+
if (name.endsWith("+?")) {
|
|
21
|
+
name = name.slice(0, -2);
|
|
22
|
+
greedy = true;
|
|
23
|
+
optional = true;
|
|
24
|
+
} else if (name.endsWith("+")) {
|
|
25
|
+
name = name.slice(0, -1);
|
|
26
|
+
greedy = true;
|
|
27
|
+
} else if (name.endsWith("?")) {
|
|
28
|
+
name = name.slice(0, -1);
|
|
29
|
+
optional = true;
|
|
30
|
+
}
|
|
31
|
+
vars.push({
|
|
32
|
+
name,
|
|
33
|
+
greedy,
|
|
34
|
+
optional
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return vars;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extract the body pattern from a URI template (everything after scheme://).
|
|
41
|
+
*/
|
|
42
|
+
function getTemplateBody(template) {
|
|
43
|
+
const idx = template.indexOf("://");
|
|
44
|
+
if (idx < 0) throw new Error(`Invalid URI template: missing "://" in "${template}"`);
|
|
45
|
+
return template.slice(idx + 3);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse a URI body against a URI template, extracting named variables.
|
|
49
|
+
*
|
|
50
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
51
|
+
* @param body - URI body string, e.g. "my-bucket/a/b/c"
|
|
52
|
+
* @returns Record of variable name → value. Optional vars may be undefined.
|
|
53
|
+
* @throws if required variables cannot be extracted from body
|
|
54
|
+
*/
|
|
55
|
+
function parseTemplate(template, body) {
|
|
56
|
+
const vars = parseTemplateVariables(getTemplateBody(template));
|
|
57
|
+
if (vars.length === 0) return {};
|
|
58
|
+
const result = {};
|
|
59
|
+
const segments = body.split("/").filter((s) => s !== "");
|
|
60
|
+
if (vars.length === 1) {
|
|
61
|
+
const v = vars[0];
|
|
62
|
+
if (body === "" || segments.length === 0) if (v.optional) result[v.name] = void 0;
|
|
63
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but URI body is empty`);
|
|
64
|
+
else result[v.name] = body;
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
let segIdx = 0;
|
|
68
|
+
for (let i = 0; i < vars.length; i++) {
|
|
69
|
+
const v = vars[i];
|
|
70
|
+
if (v.greedy) {
|
|
71
|
+
const remaining = segments.slice(segIdx);
|
|
72
|
+
if (remaining.length === 0) if (v.optional) result[v.name] = void 0;
|
|
73
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but no segments remain`);
|
|
74
|
+
else {
|
|
75
|
+
result[v.name] = remaining.join("/");
|
|
76
|
+
segIdx = segments.length;
|
|
77
|
+
}
|
|
78
|
+
} else if (segIdx < segments.length) {
|
|
79
|
+
result[v.name] = segments[segIdx];
|
|
80
|
+
segIdx++;
|
|
81
|
+
} else if (v.optional) result[v.name] = void 0;
|
|
82
|
+
else throw new Error(`URI template "${template}" requires "${v.name}" but no segments remain`);
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build a URI from a template and variable values.
|
|
88
|
+
*
|
|
89
|
+
* @param template - URI template string, e.g. "s3://{bucket}/{prefix+?}"
|
|
90
|
+
* @param vars - Record of variable name → value
|
|
91
|
+
* @returns Constructed URI string
|
|
92
|
+
* @throws if required variables are missing
|
|
93
|
+
*/
|
|
94
|
+
function buildURI(template, vars) {
|
|
95
|
+
const templateVars = parseTemplateVariables(getTemplateBody(template));
|
|
96
|
+
if (templateVars.length === 0) return template;
|
|
97
|
+
const scheme = extractSchemeFromTemplate(template);
|
|
98
|
+
const parts = [];
|
|
99
|
+
for (const v of templateVars) {
|
|
100
|
+
const value = vars[v.name];
|
|
101
|
+
if (value === void 0 || value === "") {
|
|
102
|
+
if (!v.optional) throw new Error(`buildURI: required variable "${v.name}" is missing for template "${template}"`);
|
|
103
|
+
} else parts.push(value);
|
|
104
|
+
}
|
|
105
|
+
return `${scheme}://${parts.join("/")}`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Extract variable names that appear in a URI template.
|
|
109
|
+
* Useful for determining which schema fields are "path variables".
|
|
110
|
+
*
|
|
111
|
+
* @param template - URI template string
|
|
112
|
+
* @returns Array of variable names (without +, ?, +? modifiers)
|
|
113
|
+
*/
|
|
114
|
+
function getTemplateVariableNames(template) {
|
|
115
|
+
return parseTemplateVariables(getTemplateBody(template)).map((v) => v.name);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
//#endregion
|
|
119
|
+
export { buildURI, extractSchemeFromTemplate, getTemplateVariableNames, parseTemplate };
|
|
120
|
+
//# sourceMappingURL=uri-template.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uri-template.mjs","names":[],"sources":["../../src/utils/uri-template.ts"],"sourcesContent":["/**\n * URI Template parser and builder.\n *\n * Supports AFS URI template variable syntax:\n * - {param} — single segment (no /)\n * - {param+} — multi-segment (greedy, may contain /)\n * - {param?} — optional single segment\n * - {param+?} — optional multi-segment (greedy)\n *\n * Disambiguation: non-greedy {param} consumes up to the next /;\n * greedy {param+} consumes all remaining segments.\n * In {a}/{b+?}, a takes the first segment, b takes the rest (if any).\n */\n\ninterface TemplateVariable {\n name: string;\n greedy: boolean;\n optional: boolean;\n}\n\n/**\n * Extract scheme from a URI template string.\n * e.g. \"s3://{bucket}/{prefix+?}\" → \"s3\"\n */\nexport function extractSchemeFromTemplate(template: string): string {\n const match = template.match(/^([a-z0-9][a-z0-9+.-]*):\\/\\//i);\n if (!match?.[1]) {\n throw new Error(`Invalid URI template: cannot extract scheme from \"${template}\"`);\n }\n return match[1].toLowerCase();\n}\n\n/**\n * Parse the variable definitions from a URI template's body part.\n */\nfunction parseTemplateVariables(templateBody: string): TemplateVariable[] {\n const vars: TemplateVariable[] = [];\n const regex = /\\{([^}]+)\\}/g;\n for (const match of templateBody.matchAll(regex)) {\n const raw = match[1]!;\n let name = raw;\n let greedy = false;\n let optional = false;\n\n // Check for +? (greedy + optional)\n if (name.endsWith(\"+?\")) {\n name = name.slice(0, -2);\n greedy = true;\n optional = true;\n } else if (name.endsWith(\"+\")) {\n name = name.slice(0, -1);\n greedy = true;\n } else if (name.endsWith(\"?\")) {\n name = name.slice(0, -1);\n optional = true;\n }\n\n vars.push({ name, greedy, optional });\n }\n\n return vars;\n}\n\n/**\n * Extract the body pattern from a URI template (everything after scheme://).\n */\nfunction getTemplateBody(template: string): string {\n const idx = template.indexOf(\"://\");\n if (idx < 0) {\n throw new Error(`Invalid URI template: missing \"://\" in \"${template}\"`);\n }\n return template.slice(idx + 3);\n}\n\n/**\n * Parse a URI body against a URI template, extracting named variables.\n *\n * @param template - URI template string, e.g. \"s3://{bucket}/{prefix+?}\"\n * @param body - URI body string, e.g. \"my-bucket/a/b/c\"\n * @returns Record of variable name → value. Optional vars may be undefined.\n * @throws if required variables cannot be extracted from body\n */\nexport function parseTemplate(template: string, body: string): Record<string, string | undefined> {\n const templateBody = getTemplateBody(template);\n const vars = parseTemplateVariables(templateBody);\n\n // If no variables, return empty\n if (vars.length === 0) {\n return {};\n }\n\n const result: Record<string, string | undefined> = {};\n\n const segments = body.split(\"/\").filter((s) => s !== \"\");\n\n if (vars.length === 1) {\n // Single variable case — simplest\n const v = vars[0]!;\n if (body === \"\" || segments.length === 0) {\n if (v.optional) {\n result[v.name] = undefined;\n } else {\n throw new Error(`URI template \"${template}\" requires \"${v.name}\" but URI body is empty`);\n }\n } else {\n // For greedy or single, take the entire body\n result[v.name] = body;\n }\n return result;\n }\n\n // Multi-variable case\n // Strategy: non-greedy vars consume one segment each (up to next /).\n // Greedy var consumes all remaining segments.\n let segIdx = 0;\n\n for (let i = 0; i < vars.length; i++) {\n const v = vars[i]!;\n\n if (v.greedy) {\n // Greedy: consume all remaining segments\n const remaining = segments.slice(segIdx);\n if (remaining.length === 0) {\n if (v.optional) {\n result[v.name] = undefined;\n } else {\n throw new Error(`URI template \"${template}\" requires \"${v.name}\" but no segments remain`);\n }\n } else {\n result[v.name] = remaining.join(\"/\");\n segIdx = segments.length;\n }\n } else {\n // Non-greedy: consume one segment\n if (segIdx < segments.length) {\n result[v.name] = segments[segIdx]!;\n segIdx++;\n } else if (v.optional) {\n result[v.name] = undefined;\n } else {\n throw new Error(`URI template \"${template}\" requires \"${v.name}\" but no segments remain`);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Build a URI from a template and variable values.\n *\n * @param template - URI template string, e.g. \"s3://{bucket}/{prefix+?}\"\n * @param vars - Record of variable name → value\n * @returns Constructed URI string\n * @throws if required variables are missing\n */\nexport function buildURI(template: string, vars: Record<string, string | undefined>): string {\n const templateBody = getTemplateBody(template);\n const templateVars = parseTemplateVariables(templateBody);\n\n // No template variables — the template IS the final URI (fixed URI)\n if (templateVars.length === 0) {\n return template;\n }\n\n const scheme = extractSchemeFromTemplate(template);\n\n const parts: string[] = [];\n\n for (const v of templateVars) {\n const value = vars[v.name];\n if (value === undefined || value === \"\") {\n if (!v.optional) {\n throw new Error(\n `buildURI: required variable \"${v.name}\" is missing for template \"${template}\"`,\n );\n }\n // Skip optional vars with no value\n } else {\n parts.push(value);\n }\n }\n\n return `${scheme}://${parts.join(\"/\")}`;\n}\n\n/**\n * Extract variable names that appear in a URI template.\n * Useful for determining which schema fields are \"path variables\".\n *\n * @param template - URI template string\n * @returns Array of variable names (without +, ?, +? modifiers)\n */\nexport function getTemplateVariableNames(template: string): string[] {\n const templateBody = getTemplateBody(template);\n return parseTemplateVariables(templateBody).map((v) => v.name);\n}\n"],"mappings":";;;;;AAwBA,SAAgB,0BAA0B,UAA0B;CAClE,MAAM,QAAQ,SAAS,MAAM,gCAAgC;AAC7D,KAAI,CAAC,QAAQ,GACX,OAAM,IAAI,MAAM,qDAAqD,SAAS,GAAG;AAEnF,QAAO,MAAM,GAAG,aAAa;;;;;AAM/B,SAAS,uBAAuB,cAA0C;CACxE,MAAM,OAA2B,EAAE;AAEnC,MAAK,MAAM,SAAS,aAAa,SADnB,eACkC,EAAE;EAEhD,IAAI,OADQ,MAAM;EAElB,IAAI,SAAS;EACb,IAAI,WAAW;AAGf,MAAI,KAAK,SAAS,KAAK,EAAE;AACvB,UAAO,KAAK,MAAM,GAAG,GAAG;AACxB,YAAS;AACT,cAAW;aACF,KAAK,SAAS,IAAI,EAAE;AAC7B,UAAO,KAAK,MAAM,GAAG,GAAG;AACxB,YAAS;aACA,KAAK,SAAS,IAAI,EAAE;AAC7B,UAAO,KAAK,MAAM,GAAG,GAAG;AACxB,cAAW;;AAGb,OAAK,KAAK;GAAE;GAAM;GAAQ;GAAU,CAAC;;AAGvC,QAAO;;;;;AAMT,SAAS,gBAAgB,UAA0B;CACjD,MAAM,MAAM,SAAS,QAAQ,MAAM;AACnC,KAAI,MAAM,EACR,OAAM,IAAI,MAAM,2CAA2C,SAAS,GAAG;AAEzE,QAAO,SAAS,MAAM,MAAM,EAAE;;;;;;;;;;AAWhC,SAAgB,cAAc,UAAkB,MAAkD;CAEhG,MAAM,OAAO,uBADQ,gBAAgB,SAAS,CACG;AAGjD,KAAI,KAAK,WAAW,EAClB,QAAO,EAAE;CAGX,MAAM,SAA6C,EAAE;CAErD,MAAM,WAAW,KAAK,MAAM,IAAI,CAAC,QAAQ,MAAM,MAAM,GAAG;AAExD,KAAI,KAAK,WAAW,GAAG;EAErB,MAAM,IAAI,KAAK;AACf,MAAI,SAAS,MAAM,SAAS,WAAW,EACrC,KAAI,EAAE,SACJ,QAAO,EAAE,QAAQ;MAEjB,OAAM,IAAI,MAAM,iBAAiB,SAAS,cAAc,EAAE,KAAK,yBAAyB;MAI1F,QAAO,EAAE,QAAQ;AAEnB,SAAO;;CAMT,IAAI,SAAS;AAEb,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,IAAI,KAAK;AAEf,MAAI,EAAE,QAAQ;GAEZ,MAAM,YAAY,SAAS,MAAM,OAAO;AACxC,OAAI,UAAU,WAAW,EACvB,KAAI,EAAE,SACJ,QAAO,EAAE,QAAQ;OAEjB,OAAM,IAAI,MAAM,iBAAiB,SAAS,cAAc,EAAE,KAAK,0BAA0B;QAEtF;AACL,WAAO,EAAE,QAAQ,UAAU,KAAK,IAAI;AACpC,aAAS,SAAS;;aAIhB,SAAS,SAAS,QAAQ;AAC5B,UAAO,EAAE,QAAQ,SAAS;AAC1B;aACS,EAAE,SACX,QAAO,EAAE,QAAQ;MAEjB,OAAM,IAAI,MAAM,iBAAiB,SAAS,cAAc,EAAE,KAAK,0BAA0B;;AAK/F,QAAO;;;;;;;;;;AAWT,SAAgB,SAAS,UAAkB,MAAkD;CAE3F,MAAM,eAAe,uBADA,gBAAgB,SAAS,CACW;AAGzD,KAAI,aAAa,WAAW,EAC1B,QAAO;CAGT,MAAM,SAAS,0BAA0B,SAAS;CAElD,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,KAAK,cAAc;EAC5B,MAAM,QAAQ,KAAK,EAAE;AACrB,MAAI,UAAU,UAAa,UAAU,IACnC;OAAI,CAAC,EAAE,SACL,OAAM,IAAI,MACR,gCAAgC,EAAE,KAAK,6BAA6B,SAAS,GAC9E;QAIH,OAAM,KAAK,MAAM;;AAIrB,QAAO,GAAG,OAAO,KAAK,MAAM,KAAK,IAAI;;;;;;;;;AAUvC,SAAgB,yBAAyB,UAA4B;AAEnE,QAAO,uBADc,gBAAgB,SAAS,CACH,CAAC,KAAK,MAAM,EAAE,KAAK"}
|