@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,185 @@
1
+
2
+ //#region src/provider/router.ts
3
+ /**
4
+ * Calculate specificity score for a pattern.
5
+ * Higher score = higher priority.
6
+ *
7
+ * Scoring rules:
8
+ * - Static segment: +100
9
+ * - Named parameter (single segment): +10
10
+ * - Wildcard ((.*) or (.+) or * or +): +1
11
+ * - Bonus for more segments: +5 per segment
12
+ *
13
+ * Examples:
14
+ * - /:path(.*) = 1 + 5 = 6 (low)
15
+ * - /:path(.*)/.meta = 1 + 100 + 10 = 111 (higher - has static .meta)
16
+ * - /:path(.*)/.meta/.kinds = 1 + 100 + 100 + 15 = 216 (highest)
17
+ */
18
+ function calculateSpecificity(pattern) {
19
+ let score = 0;
20
+ const segments = pattern.split("/").filter(Boolean);
21
+ for (const segment of segments) if (segment.endsWith("*") || segment.endsWith("+") || segment.endsWith("(.*)") || segment.endsWith("(.+)")) score += 1;
22
+ else if (segment.startsWith(":")) score += 10;
23
+ else score += 100;
24
+ score += segments.length * 5;
25
+ return score;
26
+ }
27
+ function convertToURLPattern(pattern) {
28
+ let result = pattern.replace(/\/\*\*$/g, "/:_(.*)");
29
+ result = result.replace(/\/\*\*\//g, "/:_(.*)/");
30
+ if (result.includes("/**")) result = result.replace(/\/\*\*/g, "/:_(.*)");
31
+ result = result.replace(/\/:(\w+)\*(\/.+)/g, "{/:$1(.*)}?$2");
32
+ const segments = result.split("/").filter(Boolean);
33
+ if (segments.length >= 2) {
34
+ const lastSegment = segments[segments.length - 1];
35
+ if (lastSegment && /^:\w+\*$/.test(lastSegment)) {
36
+ const wildcardName = lastSegment.slice(1, -1);
37
+ result = `${`/${segments.slice(0, -1).join("/")}`}{/:${wildcardName}(.*)}?`;
38
+ }
39
+ }
40
+ result = result.replace(/:(\w+)\*/g, ":$1(.*)");
41
+ result = result.replace(/:(\w+)\+/g, ":$1(.+)");
42
+ return result;
43
+ }
44
+ /**
45
+ * Provider router using native URLPattern for type-safe route handling.
46
+ * Supports suffix patterns like /:path*\/.meta for flexible routing.
47
+ */
48
+ var ProviderRouter = class {
49
+ routers = /* @__PURE__ */ new Map();
50
+ allPatterns = /* @__PURE__ */ new Set();
51
+ constructor() {
52
+ for (const op of [
53
+ "list",
54
+ "read",
55
+ "write",
56
+ "delete",
57
+ "exec",
58
+ "search",
59
+ "stat",
60
+ "explain",
61
+ "rename"
62
+ ]) this.routers.set(op, { routes: [] });
63
+ }
64
+ /**
65
+ * Register a route with the router
66
+ */
67
+ registerRoute(pattern, operation, handler, description, listOptions) {
68
+ const storage = this.routers.get(operation);
69
+ if (!storage) throw new Error(`Unknown operation: ${operation}`);
70
+ if (storage.routes.find((r) => r.originalPattern === pattern)) {
71
+ console.warn(`[AFSBaseProvider] Route conflict: ${operation} ${pattern} is being overwritten`);
72
+ storage.routes = storage.routes.filter((r) => r.originalPattern !== pattern);
73
+ }
74
+ const definition = {
75
+ pattern,
76
+ operation,
77
+ handler,
78
+ description,
79
+ listOptions
80
+ };
81
+ const urlPatternPath = convertToURLPattern(pattern);
82
+ const urlPattern = new URLPattern({ pathname: urlPatternPath });
83
+ const specificity = calculateSpecificity(urlPatternPath);
84
+ const compiledRoute = {
85
+ pattern: urlPattern,
86
+ originalPattern: pattern,
87
+ definition,
88
+ specificity
89
+ };
90
+ let inserted = false;
91
+ for (let i = 0; i < storage.routes.length; i++) {
92
+ const existingRoute = storage.routes[i];
93
+ if (existingRoute && specificity > existingRoute.specificity) {
94
+ storage.routes.splice(i, 0, compiledRoute);
95
+ inserted = true;
96
+ break;
97
+ }
98
+ }
99
+ if (!inserted) storage.routes.push(compiledRoute);
100
+ this.allPatterns.add(pattern);
101
+ }
102
+ /**
103
+ * Match a path against registered routes for an operation.
104
+ * Routes are checked in specificity order (most specific first).
105
+ */
106
+ match(path, operation) {
107
+ const storage = this.routers.get(operation);
108
+ if (!storage) return null;
109
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
110
+ for (const route of storage.routes) {
111
+ const result = route.pattern.exec({ pathname: normalizedPath });
112
+ if (result) {
113
+ const params = {};
114
+ const groups = result.pathname.groups;
115
+ for (const [key, value] of Object.entries(groups)) params[key] = value !== void 0 ? decodeURIComponent(value) : value;
116
+ return {
117
+ route: route.definition,
118
+ params
119
+ };
120
+ }
121
+ }
122
+ return null;
123
+ }
124
+ /**
125
+ * Get static children paths for a given path.
126
+ * Used for list auto-expansion.
127
+ *
128
+ * This analyzes all registered patterns to find which ones
129
+ * would be direct children of the given path.
130
+ *
131
+ * Excludes .meta and .actions as they are implicit paths.
132
+ */
133
+ getStaticChildren(basePath) {
134
+ const children = [];
135
+ const normalizedBase = basePath === "/" ? "" : basePath;
136
+ for (const pattern of this.allPatterns) {
137
+ if (pattern.endsWith("/.meta") || pattern.endsWith("/.actions")) continue;
138
+ const childPath = this.findStaticChild(normalizedBase, pattern);
139
+ if (childPath && !children.includes(childPath)) children.push(childPath);
140
+ }
141
+ return children;
142
+ }
143
+ /**
144
+ * Find a static child path from a pattern relative to basePath
145
+ *
146
+ * For patterns like "/:table/new" and basePath "/users",
147
+ * we need to check if the pattern could match and what static
148
+ * segment comes after.
149
+ */
150
+ findStaticChild(basePath, pattern) {
151
+ const baseSegments = basePath ? basePath.split("/").filter(Boolean) : [];
152
+ const patternSegments = pattern.split("/").filter(Boolean);
153
+ if (patternSegments.length <= baseSegments.length) return null;
154
+ for (let i = 0; i < baseSegments.length; i++) {
155
+ const patternSeg = patternSegments[i];
156
+ const baseSeg = baseSegments[i];
157
+ const isParam$1 = patternSeg?.startsWith(":");
158
+ const isWildcard$1 = patternSeg === "**" || patternSeg?.endsWith("*") || patternSeg?.endsWith("+") || patternSeg?.endsWith("(.*)") || patternSeg?.endsWith("(.+)");
159
+ if (patternSeg !== baseSeg && !isParam$1 && !isWildcard$1) return null;
160
+ }
161
+ const nextSegment = patternSegments[baseSegments.length];
162
+ if (!nextSegment) return null;
163
+ const isParam = nextSegment.startsWith(":");
164
+ const isWildcard = nextSegment === "**" || nextSegment.endsWith("*") || nextSegment.endsWith("+") || nextSegment.endsWith("(.*)") || nextSegment.endsWith("(.+)");
165
+ if (isParam || isWildcard) return null;
166
+ return `${basePath}/${nextSegment}`;
167
+ }
168
+ /**
169
+ * Get all registered patterns
170
+ */
171
+ getAllPatterns() {
172
+ return Array.from(this.allPatterns);
173
+ }
174
+ /**
175
+ * Get all routes for an operation
176
+ */
177
+ getRoutesForOperation(operation) {
178
+ const storage = this.routers.get(operation);
179
+ if (!storage) return [];
180
+ return storage.routes.map((r) => r.definition);
181
+ }
182
+ };
183
+
184
+ //#endregion
185
+ exports.ProviderRouter = ProviderRouter;
@@ -0,0 +1,50 @@
1
+ import { ListDecoratorOptions, RouteDefinition, RouteHandler, RouteMatch, RouteOperation } from "./types.cjs";
2
+
3
+ //#region src/provider/router.d.ts
4
+ /**
5
+ * Provider router using native URLPattern for type-safe route handling.
6
+ * Supports suffix patterns like /:path*\/.meta for flexible routing.
7
+ */
8
+ declare class ProviderRouter {
9
+ private routers;
10
+ private allPatterns;
11
+ constructor();
12
+ /**
13
+ * Register a route with the router
14
+ */
15
+ registerRoute(pattern: string, operation: RouteOperation, handler: RouteHandler, description?: string, listOptions?: ListDecoratorOptions): void;
16
+ /**
17
+ * Match a path against registered routes for an operation.
18
+ * Routes are checked in specificity order (most specific first).
19
+ */
20
+ match(path: string, operation: RouteOperation): RouteMatch | null;
21
+ /**
22
+ * Get static children paths for a given path.
23
+ * Used for list auto-expansion.
24
+ *
25
+ * This analyzes all registered patterns to find which ones
26
+ * would be direct children of the given path.
27
+ *
28
+ * Excludes .meta and .actions as they are implicit paths.
29
+ */
30
+ getStaticChildren(basePath: string): string[];
31
+ /**
32
+ * Find a static child path from a pattern relative to basePath
33
+ *
34
+ * For patterns like "/:table/new" and basePath "/users",
35
+ * we need to check if the pattern could match and what static
36
+ * segment comes after.
37
+ */
38
+ private findStaticChild;
39
+ /**
40
+ * Get all registered patterns
41
+ */
42
+ getAllPatterns(): string[];
43
+ /**
44
+ * Get all routes for an operation
45
+ */
46
+ getRoutesForOperation(operation: RouteOperation): RouteDefinition[];
47
+ }
48
+ //#endregion
49
+ export { ProviderRouter };
50
+ //# sourceMappingURL=router.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.cts","names":[],"sources":["../../src/provider/router.ts"],"mappings":";;;;;AA0HA;;cAAa,cAAA;EAAA,QACH,OAAA;EAAA,QACA,WAAA;;EA2FuB;;;EAlE/B,aAAA,CACE,OAAA,UACA,SAAA,EAAW,cAAA,EACX,OAAA,EAAS,YAAA,EACT,WAAA,WACA,WAAA,GAAc,oBAAA;EA8LiD;;;;EAjIjE,KAAA,CAAM,IAAA,UAAc,SAAA,EAAW,cAAA,GAAiB,UAAA;EAlEhD;;;;;;;;;EA6GA,iBAAA,CAAkB,QAAA;EA3CZ;;;;;;;EAAA,QAsEE,eAAA;EA2DR;;;EAPA,cAAA,CAAA;EAOiE;;;EAAjE,qBAAA,CAAsB,SAAA,EAAW,cAAA,GAAiB,eAAA;AAAA"}
@@ -0,0 +1,50 @@
1
+ import { ListDecoratorOptions, RouteDefinition, RouteHandler, RouteMatch, RouteOperation } from "./types.mjs";
2
+
3
+ //#region src/provider/router.d.ts
4
+ /**
5
+ * Provider router using native URLPattern for type-safe route handling.
6
+ * Supports suffix patterns like /:path*\/.meta for flexible routing.
7
+ */
8
+ declare class ProviderRouter {
9
+ private routers;
10
+ private allPatterns;
11
+ constructor();
12
+ /**
13
+ * Register a route with the router
14
+ */
15
+ registerRoute(pattern: string, operation: RouteOperation, handler: RouteHandler, description?: string, listOptions?: ListDecoratorOptions): void;
16
+ /**
17
+ * Match a path against registered routes for an operation.
18
+ * Routes are checked in specificity order (most specific first).
19
+ */
20
+ match(path: string, operation: RouteOperation): RouteMatch | null;
21
+ /**
22
+ * Get static children paths for a given path.
23
+ * Used for list auto-expansion.
24
+ *
25
+ * This analyzes all registered patterns to find which ones
26
+ * would be direct children of the given path.
27
+ *
28
+ * Excludes .meta and .actions as they are implicit paths.
29
+ */
30
+ getStaticChildren(basePath: string): string[];
31
+ /**
32
+ * Find a static child path from a pattern relative to basePath
33
+ *
34
+ * For patterns like "/:table/new" and basePath "/users",
35
+ * we need to check if the pattern could match and what static
36
+ * segment comes after.
37
+ */
38
+ private findStaticChild;
39
+ /**
40
+ * Get all registered patterns
41
+ */
42
+ getAllPatterns(): string[];
43
+ /**
44
+ * Get all routes for an operation
45
+ */
46
+ getRoutesForOperation(operation: RouteOperation): RouteDefinition[];
47
+ }
48
+ //#endregion
49
+ export { ProviderRouter };
50
+ //# sourceMappingURL=router.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.mts","names":[],"sources":["../../src/provider/router.ts"],"mappings":";;;;;AA0HA;;cAAa,cAAA;EAAA,QACH,OAAA;EAAA,QACA,WAAA;;EA2FuB;;;EAlE/B,aAAA,CACE,OAAA,UACA,SAAA,EAAW,cAAA,EACX,OAAA,EAAS,YAAA,EACT,WAAA,WACA,WAAA,GAAc,oBAAA;EA8LiD;;;;EAjIjE,KAAA,CAAM,IAAA,UAAc,SAAA,EAAW,cAAA,GAAiB,UAAA;EAlEhD;;;;;;;;;EA6GA,iBAAA,CAAkB,QAAA;EA3CZ;;;;;;;EAAA,QAsEE,eAAA;EA2DR;;;EAPA,cAAA,CAAA;EAOiE;;;EAAjE,qBAAA,CAAsB,SAAA,EAAW,cAAA,GAAiB,eAAA;AAAA"}
@@ -0,0 +1,185 @@
1
+ //#region src/provider/router.ts
2
+ /**
3
+ * Calculate specificity score for a pattern.
4
+ * Higher score = higher priority.
5
+ *
6
+ * Scoring rules:
7
+ * - Static segment: +100
8
+ * - Named parameter (single segment): +10
9
+ * - Wildcard ((.*) or (.+) or * or +): +1
10
+ * - Bonus for more segments: +5 per segment
11
+ *
12
+ * Examples:
13
+ * - /:path(.*) = 1 + 5 = 6 (low)
14
+ * - /:path(.*)/.meta = 1 + 100 + 10 = 111 (higher - has static .meta)
15
+ * - /:path(.*)/.meta/.kinds = 1 + 100 + 100 + 15 = 216 (highest)
16
+ */
17
+ function calculateSpecificity(pattern) {
18
+ let score = 0;
19
+ const segments = pattern.split("/").filter(Boolean);
20
+ for (const segment of segments) if (segment.endsWith("*") || segment.endsWith("+") || segment.endsWith("(.*)") || segment.endsWith("(.+)")) score += 1;
21
+ else if (segment.startsWith(":")) score += 10;
22
+ else score += 100;
23
+ score += segments.length * 5;
24
+ return score;
25
+ }
26
+ function convertToURLPattern(pattern) {
27
+ let result = pattern.replace(/\/\*\*$/g, "/:_(.*)");
28
+ result = result.replace(/\/\*\*\//g, "/:_(.*)/");
29
+ if (result.includes("/**")) result = result.replace(/\/\*\*/g, "/:_(.*)");
30
+ result = result.replace(/\/:(\w+)\*(\/.+)/g, "{/:$1(.*)}?$2");
31
+ const segments = result.split("/").filter(Boolean);
32
+ if (segments.length >= 2) {
33
+ const lastSegment = segments[segments.length - 1];
34
+ if (lastSegment && /^:\w+\*$/.test(lastSegment)) {
35
+ const wildcardName = lastSegment.slice(1, -1);
36
+ result = `${`/${segments.slice(0, -1).join("/")}`}{/:${wildcardName}(.*)}?`;
37
+ }
38
+ }
39
+ result = result.replace(/:(\w+)\*/g, ":$1(.*)");
40
+ result = result.replace(/:(\w+)\+/g, ":$1(.+)");
41
+ return result;
42
+ }
43
+ /**
44
+ * Provider router using native URLPattern for type-safe route handling.
45
+ * Supports suffix patterns like /:path*\/.meta for flexible routing.
46
+ */
47
+ var ProviderRouter = class {
48
+ routers = /* @__PURE__ */ new Map();
49
+ allPatterns = /* @__PURE__ */ new Set();
50
+ constructor() {
51
+ for (const op of [
52
+ "list",
53
+ "read",
54
+ "write",
55
+ "delete",
56
+ "exec",
57
+ "search",
58
+ "stat",
59
+ "explain",
60
+ "rename"
61
+ ]) this.routers.set(op, { routes: [] });
62
+ }
63
+ /**
64
+ * Register a route with the router
65
+ */
66
+ registerRoute(pattern, operation, handler, description, listOptions) {
67
+ const storage = this.routers.get(operation);
68
+ if (!storage) throw new Error(`Unknown operation: ${operation}`);
69
+ if (storage.routes.find((r) => r.originalPattern === pattern)) {
70
+ console.warn(`[AFSBaseProvider] Route conflict: ${operation} ${pattern} is being overwritten`);
71
+ storage.routes = storage.routes.filter((r) => r.originalPattern !== pattern);
72
+ }
73
+ const definition = {
74
+ pattern,
75
+ operation,
76
+ handler,
77
+ description,
78
+ listOptions
79
+ };
80
+ const urlPatternPath = convertToURLPattern(pattern);
81
+ const urlPattern = new URLPattern({ pathname: urlPatternPath });
82
+ const specificity = calculateSpecificity(urlPatternPath);
83
+ const compiledRoute = {
84
+ pattern: urlPattern,
85
+ originalPattern: pattern,
86
+ definition,
87
+ specificity
88
+ };
89
+ let inserted = false;
90
+ for (let i = 0; i < storage.routes.length; i++) {
91
+ const existingRoute = storage.routes[i];
92
+ if (existingRoute && specificity > existingRoute.specificity) {
93
+ storage.routes.splice(i, 0, compiledRoute);
94
+ inserted = true;
95
+ break;
96
+ }
97
+ }
98
+ if (!inserted) storage.routes.push(compiledRoute);
99
+ this.allPatterns.add(pattern);
100
+ }
101
+ /**
102
+ * Match a path against registered routes for an operation.
103
+ * Routes are checked in specificity order (most specific first).
104
+ */
105
+ match(path, operation) {
106
+ const storage = this.routers.get(operation);
107
+ if (!storage) return null;
108
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
109
+ for (const route of storage.routes) {
110
+ const result = route.pattern.exec({ pathname: normalizedPath });
111
+ if (result) {
112
+ const params = {};
113
+ const groups = result.pathname.groups;
114
+ for (const [key, value] of Object.entries(groups)) params[key] = value !== void 0 ? decodeURIComponent(value) : value;
115
+ return {
116
+ route: route.definition,
117
+ params
118
+ };
119
+ }
120
+ }
121
+ return null;
122
+ }
123
+ /**
124
+ * Get static children paths for a given path.
125
+ * Used for list auto-expansion.
126
+ *
127
+ * This analyzes all registered patterns to find which ones
128
+ * would be direct children of the given path.
129
+ *
130
+ * Excludes .meta and .actions as they are implicit paths.
131
+ */
132
+ getStaticChildren(basePath) {
133
+ const children = [];
134
+ const normalizedBase = basePath === "/" ? "" : basePath;
135
+ for (const pattern of this.allPatterns) {
136
+ if (pattern.endsWith("/.meta") || pattern.endsWith("/.actions")) continue;
137
+ const childPath = this.findStaticChild(normalizedBase, pattern);
138
+ if (childPath && !children.includes(childPath)) children.push(childPath);
139
+ }
140
+ return children;
141
+ }
142
+ /**
143
+ * Find a static child path from a pattern relative to basePath
144
+ *
145
+ * For patterns like "/:table/new" and basePath "/users",
146
+ * we need to check if the pattern could match and what static
147
+ * segment comes after.
148
+ */
149
+ findStaticChild(basePath, pattern) {
150
+ const baseSegments = basePath ? basePath.split("/").filter(Boolean) : [];
151
+ const patternSegments = pattern.split("/").filter(Boolean);
152
+ if (patternSegments.length <= baseSegments.length) return null;
153
+ for (let i = 0; i < baseSegments.length; i++) {
154
+ const patternSeg = patternSegments[i];
155
+ const baseSeg = baseSegments[i];
156
+ const isParam$1 = patternSeg?.startsWith(":");
157
+ const isWildcard$1 = patternSeg === "**" || patternSeg?.endsWith("*") || patternSeg?.endsWith("+") || patternSeg?.endsWith("(.*)") || patternSeg?.endsWith("(.+)");
158
+ if (patternSeg !== baseSeg && !isParam$1 && !isWildcard$1) return null;
159
+ }
160
+ const nextSegment = patternSegments[baseSegments.length];
161
+ if (!nextSegment) return null;
162
+ const isParam = nextSegment.startsWith(":");
163
+ const isWildcard = nextSegment === "**" || nextSegment.endsWith("*") || nextSegment.endsWith("+") || nextSegment.endsWith("(.*)") || nextSegment.endsWith("(.+)");
164
+ if (isParam || isWildcard) return null;
165
+ return `${basePath}/${nextSegment}`;
166
+ }
167
+ /**
168
+ * Get all registered patterns
169
+ */
170
+ getAllPatterns() {
171
+ return Array.from(this.allPatterns);
172
+ }
173
+ /**
174
+ * Get all routes for an operation
175
+ */
176
+ getRoutesForOperation(operation) {
177
+ const storage = this.routers.get(operation);
178
+ if (!storage) return [];
179
+ return storage.routes.map((r) => r.definition);
180
+ }
181
+ };
182
+
183
+ //#endregion
184
+ export { ProviderRouter };
185
+ //# sourceMappingURL=router.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.mjs","names":["isParam","isWildcard"],"sources":["../../src/provider/router.ts"],"sourcesContent":["import type {\n ListDecoratorOptions,\n RouteDefinition,\n RouteHandler,\n RouteMatch,\n RouteOperation,\n} from \"./types.js\";\n\n/**\n * Compiled route with URLPattern and metadata\n */\ninterface CompiledRoute {\n /** URLPattern instance for matching */\n pattern: URLPattern;\n /** Original pattern string (e.g., /:path*\\/.meta) */\n originalPattern: string;\n /** Route definition */\n definition: RouteDefinition;\n /** Specificity score for priority sorting */\n specificity: number;\n}\n\n/**\n * Internal storage for routes by operation\n */\ninterface RouterStorage {\n routes: CompiledRoute[];\n}\n\n/**\n * Calculate specificity score for a pattern.\n * Higher score = higher priority.\n *\n * Scoring rules:\n * - Static segment: +100\n * - Named parameter (single segment): +10\n * - Wildcard ((.*) or (.+) or * or +): +1\n * - Bonus for more segments: +5 per segment\n *\n * Examples:\n * - /:path(.*) = 1 + 5 = 6 (low)\n * - /:path(.*)/.meta = 1 + 100 + 10 = 111 (higher - has static .meta)\n * - /:path(.*)/.meta/.kinds = 1 + 100 + 100 + 15 = 216 (highest)\n */\nfunction calculateSpecificity(pattern: string): number {\n let score = 0;\n const segments = pattern.split(\"/\").filter(Boolean);\n\n for (const segment of segments) {\n // Check for wildcard patterns: ends with *, +, (.*), or (.+)\n const isWildcard =\n segment.endsWith(\"*\") ||\n segment.endsWith(\"+\") ||\n segment.endsWith(\"(.*)\") ||\n segment.endsWith(\"(.+)\");\n\n if (isWildcard) {\n // Wildcard: lowest priority\n score += 1;\n } else if (segment.startsWith(\":\")) {\n // Named parameter\n score += 10;\n } else {\n // Static segment: highest priority\n score += 100;\n }\n }\n\n // Bonus for more segments (longer patterns are more specific)\n score += segments.length * 5;\n\n return score;\n}\n\n// Convert AFS route pattern syntax to URLPattern syntax.\n// Conversions:\n// - Standalone wildcard (e.g. at end) → /:_(.*) or /:name(.*)\n// - Suffix patterns (wildcard followed by more path) → optional group {/:name(.*)}?/suffix\n// - Trailing wildcard preceded by segments → optional group {/:name(.*)}?\n// - :name+ → :name(.+) (one or more segments)\nfunction convertToURLPattern(pattern: string): string {\n // Replace standalone /** with /:_(.*)\n let result = pattern.replace(/\\/\\*\\*$/g, \"/:_(.*)\");\n result = result.replace(/\\/\\*\\*\\//g, \"/:_(.*)/\");\n\n // Handle /** at start or middle\n if (result.includes(\"/**\")) {\n result = result.replace(/\\/\\*\\*/g, \"/:_(.*)\");\n }\n\n // Convert :name* followed by more path (suffix pattern) to optional group\n // e.g., /:path*/.meta → {/:path(.*)}?/.meta\n result = result.replace(/\\/:(\\w+)\\*(\\/.+)/g, \"{/:$1(.*)}?$2\");\n\n // Convert trailing :name* (preceded by other segments) to optional group\n // e.g., /:branch/:path* → /:branch{/:path(.*)}?\n // This allows /main to match with path=undefined, and /main/foo to match with path=\"foo\"\n // Only apply when there are at least 2 segments (prefix + wildcard)\n const segments = result.split(\"/\").filter(Boolean);\n if (segments.length >= 2) {\n const lastSegment = segments[segments.length - 1];\n if (lastSegment && /^:\\w+\\*$/.test(lastSegment)) {\n // Last segment is a wildcard like :path*\n const wildcardName = lastSegment.slice(1, -1); // Remove : and *\n const prefix = `/${segments.slice(0, -1).join(\"/\")}`;\n result = `${prefix}{/:${wildcardName}(.*)}?`;\n }\n }\n\n // Convert standalone :name* to :name(.*) for zero-or-more matching (including empty)\n result = result.replace(/:(\\w+)\\*/g, \":$1(.*)\");\n\n // Convert :name+ to :name(.+) for one-or-more matching\n result = result.replace(/:(\\w+)\\+/g, \":$1(.+)\");\n\n return result;\n}\n\n/**\n * Provider router using native URLPattern for type-safe route handling.\n * Supports suffix patterns like /:path*\\/.meta for flexible routing.\n */\nexport class ProviderRouter {\n private routers: Map<RouteOperation, RouterStorage> = new Map();\n private allPatterns: Set<string> = new Set();\n\n constructor() {\n // Initialize routers for each operation type\n const operations: RouteOperation[] = [\n \"list\",\n \"read\",\n \"write\",\n \"delete\",\n \"exec\",\n \"search\",\n \"stat\",\n \"explain\",\n \"rename\",\n ];\n for (const op of operations) {\n this.routers.set(op, {\n routes: [],\n });\n }\n }\n\n /**\n * Register a route with the router\n */\n registerRoute(\n pattern: string,\n operation: RouteOperation,\n handler: RouteHandler,\n description?: string,\n listOptions?: ListDecoratorOptions,\n ): void {\n const storage = this.routers.get(operation);\n if (!storage) {\n throw new Error(`Unknown operation: ${operation}`);\n }\n\n // Check for conflict\n const existing = storage.routes.find((r) => r.originalPattern === pattern);\n if (existing) {\n console.warn(\n `[AFSBaseProvider] Route conflict: ${operation} ${pattern} is being overwritten`,\n );\n // Remove the existing route\n storage.routes = storage.routes.filter((r) => r.originalPattern !== pattern);\n }\n\n const definition: RouteDefinition = {\n pattern,\n operation,\n handler,\n description,\n listOptions,\n };\n\n // Convert pattern to URLPattern syntax\n const urlPatternPath = convertToURLPattern(pattern);\n\n // Create URLPattern (using pathname only)\n const urlPattern = new URLPattern({ pathname: urlPatternPath });\n\n const specificity = calculateSpecificity(urlPatternPath);\n\n const compiledRoute: CompiledRoute = {\n pattern: urlPattern,\n originalPattern: pattern,\n definition,\n specificity,\n };\n\n // Insert in sorted order (highest specificity first)\n let inserted = false;\n for (let i = 0; i < storage.routes.length; i++) {\n const existingRoute = storage.routes[i];\n if (existingRoute && specificity > existingRoute.specificity) {\n storage.routes.splice(i, 0, compiledRoute);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n storage.routes.push(compiledRoute);\n }\n\n this.allPatterns.add(pattern);\n }\n\n /**\n * Match a path against registered routes for an operation.\n * Routes are checked in specificity order (most specific first).\n */\n match(path: string, operation: RouteOperation): RouteMatch | null {\n const storage = this.routers.get(operation);\n if (!storage) {\n return null;\n }\n\n // Ensure path starts with /\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n\n // Try routes in order (already sorted by specificity)\n for (const route of storage.routes) {\n const result = route.pattern.exec({ pathname: normalizedPath });\n if (result) {\n // Extract params from URLPattern groups\n const params: Record<string, string | undefined> = {};\n const groups = result.pathname.groups;\n\n for (const [key, value] of Object.entries(groups)) {\n // URLPattern may return empty string for optional wildcards\n // We preserve the original value (could be undefined or empty string)\n // Decode URL-encoded characters (e.g., %20 for spaces)\n params[key] = value !== undefined ? decodeURIComponent(value) : value;\n }\n\n return {\n route: route.definition,\n params: params as Record<string, string>,\n };\n }\n }\n\n return null;\n }\n\n /**\n * Get static children paths for a given path.\n * Used for list auto-expansion.\n *\n * This analyzes all registered patterns to find which ones\n * would be direct children of the given path.\n *\n * Excludes .meta and .actions as they are implicit paths.\n */\n getStaticChildren(basePath: string): string[] {\n const children: string[] = [];\n const normalizedBase = basePath === \"/\" ? \"\" : basePath;\n\n for (const pattern of this.allPatterns) {\n // Skip .meta and .actions - they are implicit\n if (pattern.endsWith(\"/.meta\") || pattern.endsWith(\"/.actions\")) {\n continue;\n }\n\n // Try to find a static child segment in this pattern\n const childPath = this.findStaticChild(normalizedBase, pattern);\n if (childPath && !children.includes(childPath)) {\n children.push(childPath);\n }\n }\n\n return children;\n }\n\n /**\n * Find a static child path from a pattern relative to basePath\n *\n * For patterns like \"/:table/new\" and basePath \"/users\",\n * we need to check if the pattern could match and what static\n * segment comes after.\n */\n private findStaticChild(basePath: string, pattern: string): string | null {\n const baseSegments = basePath ? basePath.split(\"/\").filter(Boolean) : [];\n const patternSegments = pattern.split(\"/\").filter(Boolean);\n\n // Pattern must be longer than base to have a child\n if (patternSegments.length <= baseSegments.length) {\n return null;\n }\n\n // Check if pattern could match basePath\n for (let i = 0; i < baseSegments.length; i++) {\n const patternSeg = patternSegments[i];\n const baseSeg = baseSegments[i];\n\n // Pattern segment must either match exactly or be a parameter/wildcard\n const isParam = patternSeg?.startsWith(\":\");\n const isWildcard =\n patternSeg === \"**\" ||\n patternSeg?.endsWith(\"*\") ||\n patternSeg?.endsWith(\"+\") ||\n patternSeg?.endsWith(\"(.*)\") ||\n patternSeg?.endsWith(\"(.+)\");\n if (patternSeg !== baseSeg && !isParam && !isWildcard) {\n return null;\n }\n }\n\n // Get the next segment after basePath\n const nextSegment = patternSegments[baseSegments.length];\n\n // Must be a static segment (not a parameter or wildcard)\n if (!nextSegment) {\n return null;\n }\n const isParam = nextSegment.startsWith(\":\");\n const isWildcard =\n nextSegment === \"**\" ||\n nextSegment.endsWith(\"*\") ||\n nextSegment.endsWith(\"+\") ||\n nextSegment.endsWith(\"(.*)\") ||\n nextSegment.endsWith(\"(.+)\");\n if (isParam || isWildcard) {\n return null;\n }\n\n // Build the child path\n return `${basePath}/${nextSegment}`;\n }\n\n /**\n * Get all registered patterns\n */\n getAllPatterns(): string[] {\n return Array.from(this.allPatterns);\n }\n\n /**\n * Get all routes for an operation\n */\n getRoutesForOperation(operation: RouteOperation): RouteDefinition[] {\n const storage = this.routers.get(operation);\n if (!storage) {\n return [];\n }\n return storage.routes.map((r) => r.definition);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ import { AFSExplainResult } from "../meta/type.cjs";
2
+ import { AFSDeleteOptions, AFSDeleteResult, AFSEntry, AFSExecOptions, AFSExecResult, AFSListOptions, AFSReadOptions, AFSRenameResult, AFSSearchOptions, AFSSearchResult, AFSStatResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "../type.cjs";
3
+
4
+ //#region src/provider/types.d.ts
5
+ /**
6
+ * Route operation types matching AFSModule methods
7
+ */
8
+ type RouteOperation = "list" | "read" | "write" | "delete" | "exec" | "search" | "stat" | "explain" | "rename";
9
+ /**
10
+ * Union type for all possible operation options
11
+ */
12
+ type RouteOptions = AFSListOptions | AFSReadOptions | AFSWriteOptions | AFSDeleteOptions | AFSExecOptions | AFSSearchOptions;
13
+ /**
14
+ * Context passed to route handlers
15
+ *
16
+ * Note: Wildcard params (e.g., :path*) may be undefined for paths that
17
+ * don't include that segment (e.g., root paths). Always check for undefined
18
+ * when using optional wildcard params.
19
+ */
20
+ interface RouteContext<TParams = Record<string, string | undefined>> {
21
+ /** The full request path */
22
+ path: string;
23
+ /** Parameters extracted from the route pattern */
24
+ params: TParams;
25
+ /** Operation options (type depends on operation) */
26
+ options?: RouteOptions;
27
+ }
28
+ /**
29
+ * Result type for @List handlers
30
+ * - data: array of entries
31
+ * - total: optional, if present indicates complete dataset size
32
+ * if absent, data.length IS the total (all data returned)
33
+ * - noExpand: optional, paths that should not be expanded during BFS depth traversal
34
+ * (internal use only, not exposed in public API)
35
+ */
36
+ interface ListHandlerResult {
37
+ data: AFSEntry[];
38
+ total?: number;
39
+ /** Paths that should not be expanded during BFS (internal, not exposed in public API) */
40
+ noExpand?: string[];
41
+ }
42
+ /**
43
+ * Handler function types for each operation
44
+ */
45
+ type ListRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>) => Promise<ListHandlerResult>;
46
+ type ReadRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>) => Promise<AFSEntry | undefined>;
47
+ type WriteRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>, content: AFSWriteEntryPayload) => Promise<AFSWriteResult>;
48
+ type DeleteRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>) => Promise<AFSDeleteResult>;
49
+ type ExecRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>, args: Record<string, unknown>) => Promise<AFSExecResult>;
50
+ type SearchRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>, query: string, options?: AFSSearchOptions) => Promise<AFSSearchResult>;
51
+ type StatRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>) => Promise<AFSStatResult>;
52
+ type ExplainRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>) => Promise<AFSExplainResult>;
53
+ type RenameRouteHandler<TParams = Record<string, string | undefined>> = (ctx: RouteContext<TParams>, newPath: string) => Promise<AFSRenameResult>;
54
+ /**
55
+ * Union type for all route handlers
56
+ */
57
+ type RouteHandler = ListRouteHandler | ReadRouteHandler | WriteRouteHandler | DeleteRouteHandler | ExecRouteHandler | SearchRouteHandler | StatRouteHandler | ExplainRouteHandler | RenameRouteHandler;
58
+ /**
59
+ * Route definition stored in the router
60
+ */
61
+ interface RouteDefinition {
62
+ /** Route pattern (e.g., "/:table/:pk") */
63
+ pattern: string;
64
+ /** Operation type */
65
+ operation: RouteOperation;
66
+ /** Handler function */
67
+ handler: RouteHandler;
68
+ /** Optional description for documentation */
69
+ description?: string;
70
+ /** Options specific to list operations */
71
+ listOptions?: ListDecoratorOptions;
72
+ }
73
+ /**
74
+ * Options for @List decorator
75
+ */
76
+ interface ListDecoratorOptions {
77
+ /**
78
+ * Whether the handler handles maxDepth recursion itself.
79
+ * - false (default): Base provider will auto-expand depth via BFS
80
+ * - true: Handler is responsible for depth traversal
81
+ *
82
+ * Most providers can use the default (false) and just return single-level results.
83
+ * Set to true for providers that need custom depth handling (like S3 with delimiter optimization).
84
+ */
85
+ handleDepth?: boolean;
86
+ }
87
+ /**
88
+ * Metadata stored by decorators for later collection
89
+ */
90
+ interface RouteMetadata {
91
+ /** Route pattern */
92
+ pattern: string;
93
+ /** Operation type */
94
+ operation: RouteOperation;
95
+ /** Method name on the class */
96
+ methodName: string;
97
+ /** Optional description */
98
+ description?: string;
99
+ /** Options specific to list operations */
100
+ listOptions?: ListDecoratorOptions;
101
+ }
102
+ /**
103
+ * Match result from router
104
+ */
105
+ interface RouteMatch {
106
+ /** The matched route definition */
107
+ route: RouteDefinition;
108
+ /** Extracted parameters (wildcards may be undefined or empty string) */
109
+ params: Record<string, string | undefined>;
110
+ }
111
+ //#endregion
112
+ export { DeleteRouteHandler, ExecRouteHandler, ExplainRouteHandler, ListDecoratorOptions, ListHandlerResult, ListRouteHandler, ReadRouteHandler, RenameRouteHandler, RouteContext, RouteDefinition, RouteHandler, RouteMatch, RouteMetadata, RouteOperation, SearchRouteHandler, StatRouteHandler, WriteRouteHandler };
113
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","names":[],"sources":["../../src/provider/types.ts"],"mappings":";;;;;;;KAqBY,cAAA;;;;KAcA,YAAA,GACR,cAAA,GACA,cAAA,GACA,eAAA,GACA,gBAAA,GACA,cAAA,GACA,gBAAA;AANJ;;;;;;;AAAA,UAeiB,YAAA,WAAuB,MAAA;EATpC;EAWF,IAAA;EAXkB;EAclB,MAAA,EAAQ,OAAA;EAlBN;EAqBF,OAAA,GAAU,YAAA;AAAA;;;;;AARZ;;;;UAmBiB,iBAAA;EACf,IAAA,EAAM,QAAA;EACN,KAAA;EAbsB;EAetB,QAAA;AAAA;;;;KAMU,gBAAA,WAA2B,MAAA,iCACrC,GAAA,EAAK,YAAA,CAAa,OAAA,MACf,OAAA,CAAQ,iBAAA;AAAA,KAED,gBAAA,WAA2B,MAAA,iCACrC,GAAA,EAAK,YAAA,CAAa,OAAA,MACf,OAAA,CAAQ,QAAA;AAAA,KAED,iBAAA,WAA4B,MAAA,iCACtC,GAAA,EAAK,YAAA,CAAa,OAAA,GAClB,OAAA,EAAS,oBAAA,KACN,OAAA,CAAQ,cAAA;AAAA,KAED,kBAAA,WAA6B,MAAA,iCACvC,GAAA,EAAK,YAAA,CAAa,OAAA,MACf,OAAA,CAAQ,eAAA;AAAA,KAED,gBAAA,WAA2B,MAAA,iCACrC,GAAA,EAAK,YAAA,CAAa,OAAA,GAClB,IAAA,EAAM,MAAA,sBACH,OAAA,CAAQ,aAAA;AAAA,KAED,kBAAA,WAA6B,MAAA,iCACvC,GAAA,EAAK,YAAA,CAAa,OAAA,GAClB,KAAA,UACA,OAAA,GAAU,gBAAA,KACP,OAAA,CAAQ,eAAA;AAAA,KAED,gBAAA,WAA2B,MAAA,iCACrC,GAAA,EAAK,YAAA,CAAa,OAAA,MACf,OAAA,CAAQ,aAAA;AAAA,KAED,mBAAA,WAA8B,MAAA,iCACxC,GAAA,EAAK,YAAA,CAAa,OAAA,MACf,OAAA,CAAQ,gBAAA;AAAA,KAED,kBAAA,WAA6B,MAAA,iCACvC,GAAA,EAAK,YAAA,CAAa,OAAA,GAClB,OAAA,aACG,OAAA,CAAQ,eAAA;;;;KAKD,YAAA,GACR,gBAAA,GACA,gBAAA,GACA,iBAAA,GACA,kBAAA,GACA,gBAAA,GACA,kBAAA,GACA,gBAAA,GACA,mBAAA,GACA,kBAAA;;AArDJ;;UA0DiB,eAAA;EA1DsB;EA4DrC,OAAA;EA3DK;EA8DL,SAAA,EAAW,cAAA;EA7DR;EAgEH,OAAA,EAAS,YAAA;EAhEC;EAmEV,WAAA;EArEqC;EAwErC,WAAA,GAAc,oBAAA;AAAA;;;;UAMC,oBAAA;EA5Ea;AAE9B;;;;;;;EAmFE,WAAA;AAAA;;;;UAMe,aAAA;EAxFG;EA0FlB,OAAA;EAzFG;EA4FH,SAAA,EAAW,cAAA;EA5FQ;EA+FnB,UAAA;EA7FU;EAgGV,WAAA;EAhG2B;EAmG3B,WAAA,GAAc,oBAAA;AAAA;;;;UAMC,UAAA;EAtGL;EAwGV,KAAA,EAAO,eAAA;EA3GqB;EA8G5B,MAAA,EAAQ,MAAA;AAAA"}