@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.
Files changed (164) hide show
  1. package/LICENSE.md +17 -84
  2. package/README.md +4 -13
  3. package/dist/_virtual/rolldown_runtime.mjs +7 -0
  4. package/dist/afs.cjs +1330 -0
  5. package/dist/afs.d.cts +275 -0
  6. package/dist/afs.d.cts.map +1 -0
  7. package/dist/afs.d.mts +275 -0
  8. package/dist/afs.d.mts.map +1 -0
  9. package/dist/afs.mjs +1331 -0
  10. package/dist/afs.mjs.map +1 -0
  11. package/dist/capabilities/index.d.mts +2 -0
  12. package/dist/capabilities/types.d.cts +100 -0
  13. package/dist/capabilities/types.d.cts.map +1 -0
  14. package/dist/capabilities/types.d.mts +100 -0
  15. package/dist/capabilities/types.d.mts.map +1 -0
  16. package/dist/capabilities/world-mapping.cjs +20 -0
  17. package/dist/capabilities/world-mapping.d.cts +139 -0
  18. package/dist/capabilities/world-mapping.d.cts.map +1 -0
  19. package/dist/capabilities/world-mapping.d.mts +139 -0
  20. package/dist/capabilities/world-mapping.d.mts.map +1 -0
  21. package/dist/capabilities/world-mapping.mjs +20 -0
  22. package/dist/capabilities/world-mapping.mjs.map +1 -0
  23. package/dist/error.cjs +63 -0
  24. package/dist/error.d.cts +39 -0
  25. package/dist/error.d.cts.map +1 -0
  26. package/dist/error.d.mts +39 -0
  27. package/dist/error.d.mts.map +1 -0
  28. package/dist/error.mjs +59 -0
  29. package/dist/error.mjs.map +1 -0
  30. package/dist/index.cjs +72 -345
  31. package/dist/index.d.cts +18 -300
  32. package/dist/index.d.mts +20 -300
  33. package/dist/index.mjs +16 -342
  34. package/dist/loader/index.cjs +110 -0
  35. package/dist/loader/index.d.cts +48 -0
  36. package/dist/loader/index.d.cts.map +1 -0
  37. package/dist/loader/index.d.mts +48 -0
  38. package/dist/loader/index.d.mts.map +1 -0
  39. package/dist/loader/index.mjs +110 -0
  40. package/dist/loader/index.mjs.map +1 -0
  41. package/dist/meta/index.cjs +4 -0
  42. package/dist/meta/index.mjs +6 -0
  43. package/dist/meta/kind.cjs +161 -0
  44. package/dist/meta/kind.d.cts +134 -0
  45. package/dist/meta/kind.d.cts.map +1 -0
  46. package/dist/meta/kind.d.mts +134 -0
  47. package/dist/meta/kind.d.mts.map +1 -0
  48. package/dist/meta/kind.mjs +157 -0
  49. package/dist/meta/kind.mjs.map +1 -0
  50. package/dist/meta/path.cjs +116 -0
  51. package/dist/meta/path.d.cts +43 -0
  52. package/dist/meta/path.d.cts.map +1 -0
  53. package/dist/meta/path.d.mts +43 -0
  54. package/dist/meta/path.d.mts.map +1 -0
  55. package/dist/meta/path.mjs +112 -0
  56. package/dist/meta/path.mjs.map +1 -0
  57. package/dist/meta/type.d.cts +96 -0
  58. package/dist/meta/type.d.cts.map +1 -0
  59. package/dist/meta/type.d.mts +96 -0
  60. package/dist/meta/type.d.mts.map +1 -0
  61. package/dist/meta/validation.cjs +77 -0
  62. package/dist/meta/validation.d.cts +19 -0
  63. package/dist/meta/validation.d.cts.map +1 -0
  64. package/dist/meta/validation.d.mts +19 -0
  65. package/dist/meta/validation.d.mts.map +1 -0
  66. package/dist/meta/validation.mjs +77 -0
  67. package/dist/meta/validation.mjs.map +1 -0
  68. package/dist/meta/well-known-kinds.cjs +228 -0
  69. package/dist/meta/well-known-kinds.d.cts +52 -0
  70. package/dist/meta/well-known-kinds.d.cts.map +1 -0
  71. package/dist/meta/well-known-kinds.d.mts +52 -0
  72. package/dist/meta/well-known-kinds.d.mts.map +1 -0
  73. package/dist/meta/well-known-kinds.mjs +219 -0
  74. package/dist/meta/well-known-kinds.mjs.map +1 -0
  75. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.cts +141 -0
  76. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.cts.map +1 -0
  77. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.mts +141 -0
  78. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.mts.map +1 -0
  79. package/dist/path.cjs +255 -0
  80. package/dist/path.d.cts +93 -0
  81. package/dist/path.d.cts.map +1 -0
  82. package/dist/path.d.mts +93 -0
  83. package/dist/path.d.mts.map +1 -0
  84. package/dist/path.mjs +249 -0
  85. package/dist/path.mjs.map +1 -0
  86. package/dist/provider/base.cjs +425 -0
  87. package/dist/provider/base.d.cts +175 -0
  88. package/dist/provider/base.d.cts.map +1 -0
  89. package/dist/provider/base.d.mts +175 -0
  90. package/dist/provider/base.d.mts.map +1 -0
  91. package/dist/provider/base.mjs +426 -0
  92. package/dist/provider/base.mjs.map +1 -0
  93. package/dist/provider/decorators.cjs +268 -0
  94. package/dist/provider/decorators.d.cts +244 -0
  95. package/dist/provider/decorators.d.cts.map +1 -0
  96. package/dist/provider/decorators.d.mts +244 -0
  97. package/dist/provider/decorators.d.mts.map +1 -0
  98. package/dist/provider/decorators.mjs +256 -0
  99. package/dist/provider/decorators.mjs.map +1 -0
  100. package/dist/provider/index.cjs +19 -0
  101. package/dist/provider/index.d.cts +5 -0
  102. package/dist/provider/index.d.mts +5 -0
  103. package/dist/provider/index.mjs +5 -0
  104. package/dist/provider/router.cjs +185 -0
  105. package/dist/provider/router.d.cts +50 -0
  106. package/dist/provider/router.d.cts.map +1 -0
  107. package/dist/provider/router.d.mts +50 -0
  108. package/dist/provider/router.d.mts.map +1 -0
  109. package/dist/provider/router.mjs +185 -0
  110. package/dist/provider/router.mjs.map +1 -0
  111. package/dist/provider/types.d.cts +113 -0
  112. package/dist/provider/types.d.cts.map +1 -0
  113. package/dist/provider/types.d.mts +113 -0
  114. package/dist/provider/types.d.mts.map +1 -0
  115. package/dist/registry.cjs +358 -0
  116. package/dist/registry.d.cts +96 -0
  117. package/dist/registry.d.cts.map +1 -0
  118. package/dist/registry.d.mts +96 -0
  119. package/dist/registry.d.mts.map +1 -0
  120. package/dist/registry.mjs +360 -0
  121. package/dist/registry.mjs.map +1 -0
  122. package/dist/type.cjs +34 -0
  123. package/dist/type.d.cts +420 -0
  124. package/dist/type.d.cts.map +1 -0
  125. package/dist/type.d.mts +420 -0
  126. package/dist/type.d.mts.map +1 -0
  127. package/dist/type.mjs +33 -0
  128. package/dist/type.mjs.map +1 -0
  129. package/dist/utils/camelize.d.cts.map +1 -1
  130. package/dist/utils/camelize.d.mts.map +1 -1
  131. package/dist/utils/schema.cjs +129 -0
  132. package/dist/utils/schema.d.cts +65 -0
  133. package/dist/utils/schema.d.cts.map +1 -0
  134. package/dist/utils/schema.d.mts +65 -0
  135. package/dist/utils/schema.d.mts.map +1 -0
  136. package/dist/utils/schema.mjs +124 -0
  137. package/dist/utils/schema.mjs.map +1 -0
  138. package/dist/utils/type-utils.d.cts.map +1 -1
  139. package/dist/utils/type-utils.d.mts.map +1 -1
  140. package/dist/utils/uri-template.cjs +123 -0
  141. package/dist/utils/uri-template.d.cts +48 -0
  142. package/dist/utils/uri-template.d.cts.map +1 -0
  143. package/dist/utils/uri-template.d.mts +48 -0
  144. package/dist/utils/uri-template.d.mts.map +1 -0
  145. package/dist/utils/uri-template.mjs +120 -0
  146. package/dist/utils/uri-template.mjs.map +1 -0
  147. package/dist/utils/uri.cjs +49 -0
  148. package/dist/utils/uri.d.cts +34 -0
  149. package/dist/utils/uri.d.cts.map +1 -0
  150. package/dist/utils/uri.d.mts +34 -0
  151. package/dist/utils/uri.d.mts.map +1 -0
  152. package/dist/utils/uri.mjs +49 -0
  153. package/dist/utils/uri.mjs.map +1 -0
  154. package/dist/utils/zod.cjs +6 -8
  155. package/dist/utils/zod.d.cts +2 -2
  156. package/dist/utils/zod.d.cts.map +1 -1
  157. package/dist/utils/zod.d.mts +2 -2
  158. package/dist/utils/zod.d.mts.map +1 -1
  159. package/dist/utils/zod.mjs +6 -8
  160. package/dist/utils/zod.mjs.map +1 -1
  161. package/package.json +27 -4
  162. package/dist/index.d.cts.map +0 -1
  163. package/dist/index.d.mts.map +0 -1
  164. 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,CAAA,KAAA,YAAA,KAAA;AAAA,iBAIA,QAAA,GAAA,CAAA,KAAA,YAAA,KAAA,IAAsC,MAAA,SAAe,CAAA;AAAA,iBAIrD,OAAA,CAAA,GAAA;AAAA,iBAOA,aAAA,GAAA,CAAA,KAAA,EAAwB,CAAA,GAAA,KAAA,IAAa,WAAA,CAAY,CAAA;AAAA,iBAIjD,GAAA,CAAA,GAAA,OAAA,IAAA"}
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,CAAA,KAAA,YAAA,KAAA;AAAA,iBAIA,QAAA,GAAA,CAAA,KAAA,YAAA,KAAA,IAAsC,MAAA,SAAe,CAAA;AAAA,iBAIrD,OAAA,CAAA,GAAA;AAAA,iBAOA,aAAA,GAAA,CAAA,KAAA,EAAwB,CAAA,GAAA,KAAA,IAAa,WAAA,CAAY,CAAA;AAAA,iBAIjD,GAAA,CAAA,GAAA,OAAA,IAAA"}
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"}