@jfdevelops/react-layout 0.17.5 → 0.18.1

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 (153) hide show
  1. package/dist/create-config/component-keys.cjs +44 -0
  2. package/dist/create-config/component-keys.cjs.map +1 -0
  3. package/dist/create-config/component-keys.mjs +39 -0
  4. package/dist/create-config/component-keys.mjs.map +1 -0
  5. package/dist/create-config/define-layout.cjs +16 -1
  6. package/dist/create-config/define-layout.cjs.map +1 -1
  7. package/dist/create-config/define-layout.d.cts +5 -3
  8. package/dist/create-config/define-layout.d.cts.map +1 -1
  9. package/dist/create-config/define-layout.d.mts +5 -3
  10. package/dist/create-config/define-layout.d.mts.map +1 -1
  11. package/dist/create-config/define-layout.mjs +16 -1
  12. package/dist/create-config/define-layout.mjs.map +1 -1
  13. package/dist/create-config/for-paths/builder.cjs +192 -0
  14. package/dist/create-config/for-paths/builder.cjs.map +1 -0
  15. package/dist/create-config/for-paths/builder.d.cts +77 -0
  16. package/dist/create-config/for-paths/builder.d.cts.map +1 -0
  17. package/dist/create-config/for-paths/builder.d.mts +77 -0
  18. package/dist/create-config/for-paths/builder.d.mts.map +1 -0
  19. package/dist/create-config/for-paths/builder.mjs +192 -0
  20. package/dist/create-config/for-paths/builder.mjs.map +1 -0
  21. package/dist/create-config/for-paths/get-component-for-path.cjs +55 -0
  22. package/dist/create-config/for-paths/get-component-for-path.cjs.map +1 -0
  23. package/dist/create-config/for-paths/get-component-for-path.d.cts +55 -0
  24. package/dist/create-config/for-paths/get-component-for-path.d.cts.map +1 -0
  25. package/dist/create-config/for-paths/get-component-for-path.d.mts +55 -0
  26. package/dist/create-config/for-paths/get-component-for-path.d.mts.map +1 -0
  27. package/dist/create-config/for-paths/get-component-for-path.mjs +55 -0
  28. package/dist/create-config/for-paths/get-component-for-path.mjs.map +1 -0
  29. package/dist/create-config/for-paths/index.d.cts +2 -0
  30. package/dist/create-config/for-paths/index.d.mts +2 -0
  31. package/dist/create-config/get-component.cjs +60 -11
  32. package/dist/create-config/get-component.cjs.map +1 -1
  33. package/dist/create-config/get-component.d.cts +75 -6
  34. package/dist/create-config/get-component.d.cts.map +1 -1
  35. package/dist/create-config/get-component.d.mts +75 -6
  36. package/dist/create-config/get-component.d.mts.map +1 -1
  37. package/dist/create-config/get-component.mjs +61 -11
  38. package/dist/create-config/get-component.mjs.map +1 -1
  39. package/dist/create-config/index.d.cts +6 -1
  40. package/dist/create-config/index.d.mts +6 -1
  41. package/dist/create-config/is-sub-resource-key.cjs +15 -0
  42. package/dist/create-config/is-sub-resource-key.cjs.map +1 -0
  43. package/dist/create-config/is-sub-resource-key.d.cts +30 -0
  44. package/dist/create-config/is-sub-resource-key.d.cts.map +1 -0
  45. package/dist/create-config/is-sub-resource-key.d.mts +30 -0
  46. package/dist/create-config/is-sub-resource-key.d.mts.map +1 -0
  47. package/dist/create-config/is-sub-resource-key.mjs +15 -0
  48. package/dist/create-config/is-sub-resource-key.mjs.map +1 -0
  49. package/dist/create-config/paths/generate.cjs +77 -0
  50. package/dist/create-config/paths/generate.cjs.map +1 -0
  51. package/dist/create-config/paths/generate.mjs +77 -0
  52. package/dist/create-config/paths/generate.mjs.map +1 -0
  53. package/dist/create-config/paths/index.d.cts +2 -0
  54. package/dist/create-config/paths/index.d.mts +2 -0
  55. package/dist/create-config/paths/introspect.cjs +123 -0
  56. package/dist/create-config/paths/introspect.cjs.map +1 -0
  57. package/dist/create-config/paths/introspect.mjs +118 -0
  58. package/dist/create-config/paths/introspect.mjs.map +1 -0
  59. package/dist/create-config/paths/resolve.cjs +130 -0
  60. package/dist/create-config/paths/resolve.cjs.map +1 -0
  61. package/dist/create-config/paths/resolve.mjs +129 -0
  62. package/dist/create-config/paths/resolve.mjs.map +1 -0
  63. package/dist/create-config/paths/types.d.cts +104 -0
  64. package/dist/create-config/paths/types.d.cts.map +1 -0
  65. package/dist/create-config/paths/types.d.mts +104 -0
  66. package/dist/create-config/paths/types.d.mts.map +1 -0
  67. package/dist/create-config/paths/variables.cjs +32 -0
  68. package/dist/create-config/paths/variables.cjs.map +1 -0
  69. package/dist/create-config/paths/variables.d.cts +32 -0
  70. package/dist/create-config/paths/variables.d.cts.map +1 -0
  71. package/dist/create-config/paths/variables.d.mts +32 -0
  72. package/dist/create-config/paths/variables.d.mts.map +1 -0
  73. package/dist/create-config/paths/variables.mjs +29 -0
  74. package/dist/create-config/paths/variables.mjs.map +1 -0
  75. package/dist/create-config/types.d.cts +28 -8
  76. package/dist/create-config/types.d.cts.map +1 -1
  77. package/dist/create-config/types.d.mts +28 -8
  78. package/dist/create-config/types.d.mts.map +1 -1
  79. package/dist/errors/invalid-component.cjs +21 -0
  80. package/dist/errors/invalid-component.cjs.map +1 -0
  81. package/dist/errors/invalid-component.d.cts +18 -0
  82. package/dist/errors/invalid-component.d.cts.map +1 -0
  83. package/dist/errors/invalid-component.d.mts +18 -0
  84. package/dist/errors/invalid-component.d.mts.map +1 -0
  85. package/dist/errors/invalid-component.mjs +21 -0
  86. package/dist/errors/invalid-component.mjs.map +1 -0
  87. package/dist/errors/invalid-config.cjs +13 -0
  88. package/dist/errors/invalid-config.cjs.map +1 -0
  89. package/dist/errors/invalid-config.d.cts +15 -0
  90. package/dist/errors/invalid-config.d.cts.map +1 -0
  91. package/dist/errors/invalid-config.d.mts +15 -0
  92. package/dist/errors/invalid-config.d.mts.map +1 -0
  93. package/dist/errors/invalid-config.mjs +13 -0
  94. package/dist/errors/invalid-config.mjs.map +1 -0
  95. package/dist/errors/invalid-path.cjs +18 -0
  96. package/dist/errors/invalid-path.cjs.map +1 -0
  97. package/dist/errors/invalid-path.d.cts +16 -0
  98. package/dist/errors/invalid-path.d.cts.map +1 -0
  99. package/dist/errors/invalid-path.d.mts +16 -0
  100. package/dist/errors/invalid-path.d.mts.map +1 -0
  101. package/dist/errors/invalid-path.mjs +18 -0
  102. package/dist/errors/invalid-path.mjs.map +1 -0
  103. package/dist/errors/invalid-resource.cjs +18 -0
  104. package/dist/errors/invalid-resource.cjs.map +1 -0
  105. package/dist/errors/invalid-resource.d.cts +16 -0
  106. package/dist/errors/invalid-resource.d.cts.map +1 -0
  107. package/dist/errors/invalid-resource.d.mts +16 -0
  108. package/dist/errors/invalid-resource.d.mts.map +1 -0
  109. package/dist/errors/invalid-resource.mjs +18 -0
  110. package/dist/errors/invalid-resource.mjs.map +1 -0
  111. package/dist/errors/invalid-sub-resource.cjs +18 -0
  112. package/dist/errors/invalid-sub-resource.cjs.map +1 -0
  113. package/dist/errors/invalid-sub-resource.d.cts +17 -0
  114. package/dist/errors/invalid-sub-resource.d.cts.map +1 -0
  115. package/dist/errors/invalid-sub-resource.d.mts +17 -0
  116. package/dist/errors/invalid-sub-resource.d.mts.map +1 -0
  117. package/dist/errors/invalid-sub-resource.mjs +18 -0
  118. package/dist/errors/invalid-sub-resource.mjs.map +1 -0
  119. package/dist/errors/missing-path-variable.cjs +18 -0
  120. package/dist/errors/missing-path-variable.cjs.map +1 -0
  121. package/dist/errors/missing-path-variable.d.cts +16 -0
  122. package/dist/errors/missing-path-variable.d.cts.map +1 -0
  123. package/dist/errors/missing-path-variable.d.mts +16 -0
  124. package/dist/errors/missing-path-variable.d.mts.map +1 -0
  125. package/dist/errors/missing-path-variable.mjs +18 -0
  126. package/dist/errors/missing-path-variable.mjs.map +1 -0
  127. package/dist/errors/react-layout-error.cjs +56 -0
  128. package/dist/errors/react-layout-error.cjs.map +1 -0
  129. package/dist/errors/react-layout-error.d.cts +46 -0
  130. package/dist/errors/react-layout-error.d.cts.map +1 -0
  131. package/dist/errors/react-layout-error.d.mts +46 -0
  132. package/dist/errors/react-layout-error.d.mts.map +1 -0
  133. package/dist/errors/react-layout-error.mjs +54 -0
  134. package/dist/errors/react-layout-error.mjs.map +1 -0
  135. package/dist/index.cjs +15 -0
  136. package/dist/index.d.cts +13 -1
  137. package/dist/index.d.mts +13 -1
  138. package/dist/index.mjs +8 -1
  139. package/dist/props.d.cts +1 -1
  140. package/dist/props.d.cts.map +1 -1
  141. package/dist/props.d.mts +1 -1
  142. package/dist/props.d.mts.map +1 -1
  143. package/dist/resource.cjs.map +1 -1
  144. package/dist/resource.d.cts +2 -2
  145. package/dist/resource.d.cts.map +1 -1
  146. package/dist/resource.d.mts +2 -2
  147. package/dist/resource.d.mts.map +1 -1
  148. package/dist/resource.mjs.map +1 -1
  149. package/dist/utils.d.cts +2 -1
  150. package/dist/utils.d.cts.map +1 -1
  151. package/dist/utils.d.mts +2 -1
  152. package/dist/utils.d.mts.map +1 -1
  153. package/package.json +1 -1
@@ -1,4 +1,9 @@
1
1
  import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.mjs";
2
- import { CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.mjs";
2
+ import { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathVariable, ResourcePathVariable, SubResourcePathVariable } from "./paths/variables.mjs";
3
+ import { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveParameterizedPathValue, ResourceSubResourceKeys } from "./paths/types.mjs";
4
+ import { CreateGetComponentForPath, GetComponentForPath, GetComponentForPathApi, PathValueComponentGetter, PathVariableGuards, ResolvedPathValue } from "./for-paths/get-component-for-path.mjs";
5
+ import { ForPaths, ForPathsRenderContext, RenderedPathComponent, RenderedPathComponentHOF, TargetPathBuilder } from "./for-paths/builder.mjs";
6
+ import { IsSubResourceKey, IsSubResourceKeyOptions, IsSubResourceKeyResult } from "./is-sub-resource-key.mjs";
7
+ import { ComponentTypes, CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceConfigPath, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.mjs";
3
8
  import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref } from "./create-resource-links.mjs";
4
9
  import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, defineResourceLayout } from "./define-layout.mjs";
@@ -0,0 +1,15 @@
1
+ const require_introspect = require('./paths/introspect.cjs');
2
+
3
+ //#region src/create-config/is-sub-resource-key.ts
4
+ function createIsSubResourceKey(config) {
5
+ return (key, options) => {
6
+ if (typeof key !== "string") return false;
7
+ if (options.path !== void 0) return require_introspect.collectPathSubResourceKeys(config, options.path).includes(key);
8
+ if (options.resource !== void 0) return require_introspect.collectResourceSubResourceKeys(config, options.resource).includes(key);
9
+ return false;
10
+ };
11
+ }
12
+
13
+ //#endregion
14
+ exports.createIsSubResourceKey = createIsSubResourceKey;
15
+ //# sourceMappingURL=is-sub-resource-key.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-sub-resource-key.cjs","names":["collectPathSubResourceKeys","collectResourceSubResourceKeys"],"sources":["../../src/create-config/is-sub-resource-key.ts"],"sourcesContent":["import type { ResourceDefinition } from '../resource';\nimport {\n collectPathSubResourceKeys,\n collectResourceSubResourceKeys,\n} from './paths';\nimport type {\n ConfigResourceKeys,\n PathSubResourceKeys,\n ResourceSubResourceKeys,\n} from './paths';\n\n/** Either a path whose `$subResource` segment supplies the valid keys, or one resource. */\nexport type IsSubResourceKeyOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n AllowedPath extends string,\n> =\n | { path: AllowedPath; resource?: never }\n | { resource: ConfigResourceKeys<Resources, Config>; path?: never };\n\nexport type IsSubResourceKeyResult<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n Options,\n> = Options extends { path: infer Path extends string }\n ? PathSubResourceKeys<Resources, Config, Path>\n : Options extends { resource: infer Resource }\n ? ResourceSubResourceKeys<Config, Resource>\n : never;\n\n/**\n * Narrows an unknown value to a configured sub-resource key.\n *\n * @example\n * ```ts\n * if (isSubResourceKey(slug, { resource: 'templates' })) {\n * // slug is 'deleted' | 'expired'\n * }\n * ```\n */\nexport type IsSubResourceKey<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n AllowedPath extends string,\n> = <\n const Options extends IsSubResourceKeyOptions<Resources, Config, AllowedPath>,\n>(\n key: unknown,\n options: Options,\n) => key is IsSubResourceKeyResult<Resources, Config, Options>;\n\nexport function createIsSubResourceKey(config: Record<string, unknown>) {\n return (\n key: unknown,\n options: { path?: string; resource?: string },\n ): boolean => {\n if (typeof key !== 'string') {\n return false;\n }\n\n if (options.path !== undefined) {\n return collectPathSubResourceKeys(config, options.path).includes(key);\n }\n\n if (options.resource !== undefined) {\n return collectResourceSubResourceKeys(config, options.resource).includes(\n key,\n );\n }\n\n return false;\n };\n}\n"],"mappings":";;;AAmDA,SAAgB,uBAAuB,QAAiC;CACtE,QACE,KACA,YACY;EACZ,IAAI,OAAO,QAAQ,UACjB,OAAO;EAGT,IAAI,QAAQ,SAAS,QACnB,OAAOA,8CAA2B,QAAQ,QAAQ,IAAI,EAAE,SAAS,GAAG;EAGtE,IAAI,QAAQ,aAAa,QACvB,OAAOC,kDAA+B,QAAQ,QAAQ,QAAQ,EAAE,SAC9D,GACF;EAGF,OAAO;CACT;AACF"}
@@ -0,0 +1,30 @@
1
+ import { ResourceDefinition } from "../resource.cjs";
2
+ import { ConfigResourceKeys, PathSubResourceKeys, ResourceSubResourceKeys } from "./paths/types.cjs";
3
+ //#region src/create-config/is-sub-resource-key.d.ts
4
+ /** Either a path whose `$subResource` segment supplies the valid keys, or one resource. */
5
+ type IsSubResourceKeyOptions<Resources extends ReadonlyArray<ResourceDefinition>, Config, AllowedPath extends string> = {
6
+ path: AllowedPath;
7
+ resource?: never;
8
+ } | {
9
+ resource: ConfigResourceKeys<Resources, Config>;
10
+ path?: never;
11
+ };
12
+ type IsSubResourceKeyResult<Resources extends ReadonlyArray<ResourceDefinition>, Config, Options> = Options extends {
13
+ path: infer Path extends string;
14
+ } ? PathSubResourceKeys<Resources, Config, Path> : Options extends {
15
+ resource: infer Resource;
16
+ } ? ResourceSubResourceKeys<Config, Resource> : never;
17
+ /**
18
+ * Narrows an unknown value to a configured sub-resource key.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * if (isSubResourceKey(slug, { resource: 'templates' })) {
23
+ * // slug is 'deleted' | 'expired'
24
+ * }
25
+ * ```
26
+ */
27
+ type IsSubResourceKey<Resources extends ReadonlyArray<ResourceDefinition>, Config, AllowedPath extends string> = <const Options extends IsSubResourceKeyOptions<Resources, Config, AllowedPath>>(key: unknown, options: Options) => key is IsSubResourceKeyResult<Resources, Config, Options>;
28
+ //#endregion
29
+ export { IsSubResourceKey, IsSubResourceKeyOptions, IsSubResourceKeyResult };
30
+ //# sourceMappingURL=is-sub-resource-key.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-sub-resource-key.d.cts","names":[],"sources":["../../src/create-config/is-sub-resource-key.ts"],"mappings":";;;;KAYY,uBAAA,mBACQ,aAAA,CAAc,kBAAA;EAI5B,IAAA,EAAM,WAAA;EAAa,QAAA;AAAA;EACnB,QAAA,EAAU,kBAAA,CAAmB,SAAA,EAAW,MAAA;EAAS,IAAA;AAAA;AAAA,KAE3C,sBAAA,mBACQ,aAAA,CAAc,kBAAA,sBAG9B,OAAA;EAAkB,IAAA;AAAA,IAClB,mBAAA,CAAoB,SAAA,EAAW,MAAA,EAAQ,IAAA,IACvC,OAAA;EAAkB,QAAA;AAAA,IAChB,uBAAA,CAAwB,MAAA,EAAQ,QAAA;;;;;;;;;;;KAa1B,gBAAA,mBACQ,aAAA,CAAc,kBAAA,gEAIV,uBAAA,CAAwB,SAAA,EAAW,MAAA,EAAQ,WAAA,GAEjE,GAAA,WACA,OAAA,EAAS,OAAA,KACN,GAAA,IAAO,sBAAA,CAAuB,SAAA,EAAW,MAAA,EAAQ,OAAA"}
@@ -0,0 +1,30 @@
1
+ import { ResourceDefinition } from "../resource.mjs";
2
+ import { ConfigResourceKeys, PathSubResourceKeys, ResourceSubResourceKeys } from "./paths/types.mjs";
3
+ //#region src/create-config/is-sub-resource-key.d.ts
4
+ /** Either a path whose `$subResource` segment supplies the valid keys, or one resource. */
5
+ type IsSubResourceKeyOptions<Resources extends ReadonlyArray<ResourceDefinition>, Config, AllowedPath extends string> = {
6
+ path: AllowedPath;
7
+ resource?: never;
8
+ } | {
9
+ resource: ConfigResourceKeys<Resources, Config>;
10
+ path?: never;
11
+ };
12
+ type IsSubResourceKeyResult<Resources extends ReadonlyArray<ResourceDefinition>, Config, Options> = Options extends {
13
+ path: infer Path extends string;
14
+ } ? PathSubResourceKeys<Resources, Config, Path> : Options extends {
15
+ resource: infer Resource;
16
+ } ? ResourceSubResourceKeys<Config, Resource> : never;
17
+ /**
18
+ * Narrows an unknown value to a configured sub-resource key.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * if (isSubResourceKey(slug, { resource: 'templates' })) {
23
+ * // slug is 'deleted' | 'expired'
24
+ * }
25
+ * ```
26
+ */
27
+ type IsSubResourceKey<Resources extends ReadonlyArray<ResourceDefinition>, Config, AllowedPath extends string> = <const Options extends IsSubResourceKeyOptions<Resources, Config, AllowedPath>>(key: unknown, options: Options) => key is IsSubResourceKeyResult<Resources, Config, Options>;
28
+ //#endregion
29
+ export { IsSubResourceKey, IsSubResourceKeyOptions, IsSubResourceKeyResult };
30
+ //# sourceMappingURL=is-sub-resource-key.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-sub-resource-key.d.mts","names":[],"sources":["../../src/create-config/is-sub-resource-key.ts"],"mappings":";;;;KAYY,uBAAA,mBACQ,aAAA,CAAc,kBAAA;EAI5B,IAAA,EAAM,WAAA;EAAa,QAAA;AAAA;EACnB,QAAA,EAAU,kBAAA,CAAmB,SAAA,EAAW,MAAA;EAAS,IAAA;AAAA;AAAA,KAE3C,sBAAA,mBACQ,aAAA,CAAc,kBAAA,sBAG9B,OAAA;EAAkB,IAAA;AAAA,IAClB,mBAAA,CAAoB,SAAA,EAAW,MAAA,EAAQ,IAAA,IACvC,OAAA;EAAkB,QAAA;AAAA,IAChB,uBAAA,CAAwB,MAAA,EAAQ,QAAA;;;;;;;;;;;KAa1B,gBAAA,mBACQ,aAAA,CAAc,kBAAA,gEAIV,uBAAA,CAAwB,SAAA,EAAW,MAAA,EAAQ,WAAA,GAEjE,GAAA,WACA,OAAA,EAAS,OAAA,KACN,GAAA,IAAO,sBAAA,CAAuB,SAAA,EAAW,MAAA,EAAQ,OAAA"}
@@ -0,0 +1,15 @@
1
+ import { collectPathSubResourceKeys, collectResourceSubResourceKeys } from "./paths/introspect.mjs";
2
+
3
+ //#region src/create-config/is-sub-resource-key.ts
4
+ function createIsSubResourceKey(config) {
5
+ return (key, options) => {
6
+ if (typeof key !== "string") return false;
7
+ if (options.path !== void 0) return collectPathSubResourceKeys(config, options.path).includes(key);
8
+ if (options.resource !== void 0) return collectResourceSubResourceKeys(config, options.resource).includes(key);
9
+ return false;
10
+ };
11
+ }
12
+
13
+ //#endregion
14
+ export { createIsSubResourceKey };
15
+ //# sourceMappingURL=is-sub-resource-key.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-sub-resource-key.mjs","names":[],"sources":["../../src/create-config/is-sub-resource-key.ts"],"sourcesContent":["import type { ResourceDefinition } from '../resource';\nimport {\n collectPathSubResourceKeys,\n collectResourceSubResourceKeys,\n} from './paths';\nimport type {\n ConfigResourceKeys,\n PathSubResourceKeys,\n ResourceSubResourceKeys,\n} from './paths';\n\n/** Either a path whose `$subResource` segment supplies the valid keys, or one resource. */\nexport type IsSubResourceKeyOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n AllowedPath extends string,\n> =\n | { path: AllowedPath; resource?: never }\n | { resource: ConfigResourceKeys<Resources, Config>; path?: never };\n\nexport type IsSubResourceKeyResult<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n Options,\n> = Options extends { path: infer Path extends string }\n ? PathSubResourceKeys<Resources, Config, Path>\n : Options extends { resource: infer Resource }\n ? ResourceSubResourceKeys<Config, Resource>\n : never;\n\n/**\n * Narrows an unknown value to a configured sub-resource key.\n *\n * @example\n * ```ts\n * if (isSubResourceKey(slug, { resource: 'templates' })) {\n * // slug is 'deleted' | 'expired'\n * }\n * ```\n */\nexport type IsSubResourceKey<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config,\n AllowedPath extends string,\n> = <\n const Options extends IsSubResourceKeyOptions<Resources, Config, AllowedPath>,\n>(\n key: unknown,\n options: Options,\n) => key is IsSubResourceKeyResult<Resources, Config, Options>;\n\nexport function createIsSubResourceKey(config: Record<string, unknown>) {\n return (\n key: unknown,\n options: { path?: string; resource?: string },\n ): boolean => {\n if (typeof key !== 'string') {\n return false;\n }\n\n if (options.path !== undefined) {\n return collectPathSubResourceKeys(config, options.path).includes(key);\n }\n\n if (options.resource !== undefined) {\n return collectResourceSubResourceKeys(config, options.resource).includes(\n key,\n );\n }\n\n return false;\n };\n}\n"],"mappings":";;;AAmDA,SAAgB,uBAAuB,QAAiC;CACtE,QACE,KACA,YACY;EACZ,IAAI,OAAO,QAAQ,UACjB,OAAO;EAGT,IAAI,QAAQ,SAAS,QACnB,OAAO,2BAA2B,QAAQ,QAAQ,IAAI,EAAE,SAAS,GAAG;EAGtE,IAAI,QAAQ,aAAa,QACvB,OAAO,+BAA+B,QAAQ,QAAQ,QAAQ,EAAE,SAC9D,GACF;EAGF,OAAO;CACT;AACF"}
@@ -0,0 +1,77 @@
1
+ const require_component_keys = require('../component-keys.cjs');
2
+ const require_variables = require('./variables.cjs');
3
+
4
+ //#region src/create-config/paths/generate.ts
5
+ /** Recursion cap for generated paths. Must stay aligned with `MaxPathDepth` in `./types`. */
6
+ const MAX_PATH_DEPTH = 6;
7
+ const RESOURCE_VARIABLE = require_variables.createPathVariable("resource");
8
+ const SUB_RESOURCE_VARIABLE = require_variables.createPathVariable("subResource");
9
+ const COMPONENT_VARIABLE = require_variables.createPathVariable("component");
10
+ /** Component tails on one node: its slots, its shared branches, and `$component`. */
11
+ function collectComponentTails(node) {
12
+ const tails = [];
13
+ for (const key of require_component_keys.COMPONENT_SLOT_KEYS) if (node[key] !== void 0) tails.push(key);
14
+ if (require_component_keys.readComponentKeys(node).length > 0) tails.push(COMPONENT_VARIABLE);
15
+ for (const branch of require_component_keys.SHARED_BRANCH_KEYS) {
16
+ const branchNode = node[branch];
17
+ if (!require_component_keys.isConfigNode(branchNode)) continue;
18
+ tails.push(branch);
19
+ for (const key of require_component_keys.COMPONENT_SLOT_KEYS) if (branchNode[key] !== void 0) tails.push(`${branch}.${key}`);
20
+ if (require_component_keys.readComponentKeys(branchNode).length > 0) tails.push(`${branch}.${COMPONENT_VARIABLE}`);
21
+ }
22
+ return tails;
23
+ }
24
+ /**
25
+ * Component tails valid after a `$subResource` segment: one variable stands for the whole
26
+ * sub-resource chain, so every descendant's tails are reachable.
27
+ */
28
+ function collectDescendantComponentTails(node, depth) {
29
+ if (depth === 0) return [];
30
+ const tails = /* @__PURE__ */ new Set();
31
+ for (const key of require_component_keys.readSubResourceKeys(node)) {
32
+ const subNode = node[key];
33
+ if (!require_component_keys.isConfigNode(subNode)) continue;
34
+ for (const tail of collectComponentTails(subNode)) tails.add(tail);
35
+ for (const tail of collectDescendantComponentTails(subNode, depth - 1)) tails.add(tail);
36
+ }
37
+ return [...tails];
38
+ }
39
+ /** Every path tail valid below one config node. */
40
+ function collectEntryPaths(node, depth) {
41
+ if (depth === 0) return [];
42
+ const paths = new Set(collectComponentTails(node));
43
+ const subResourceKeys = require_component_keys.readSubResourceKeys(node);
44
+ if (subResourceKeys.length > 0) {
45
+ paths.add(SUB_RESOURCE_VARIABLE);
46
+ for (const tail of collectDescendantComponentTails(node, depth)) paths.add(`${SUB_RESOURCE_VARIABLE}.${tail}`);
47
+ }
48
+ for (const key of subResourceKeys) {
49
+ const subNode = node[key];
50
+ paths.add(key);
51
+ if (!require_component_keys.isConfigNode(subNode)) continue;
52
+ for (const nested of collectEntryPaths(subNode, depth - 1)) paths.add(`${key}.${nested}`);
53
+ }
54
+ return [...paths];
55
+ }
56
+ /**
57
+ * Paths a config accepts, with resource and sub-resource segments available both as
58
+ * literals and as variables. Runtime twin of `ParameterizedResourcePath`.
59
+ */
60
+ function generateResourceConfigPaths(config) {
61
+ const paths = /* @__PURE__ */ new Set();
62
+ for (const resource of Object.keys(config)) {
63
+ const resourceNode = config[resource];
64
+ if (!require_component_keys.isConfigNode(resourceNode)) continue;
65
+ paths.add(resource);
66
+ paths.add(RESOURCE_VARIABLE);
67
+ for (const tail of collectEntryPaths(resourceNode, 6)) {
68
+ paths.add(`${resource}.${tail}`);
69
+ paths.add(`${RESOURCE_VARIABLE}.${tail}`);
70
+ }
71
+ }
72
+ return [...paths];
73
+ }
74
+
75
+ //#endregion
76
+ exports.generateResourceConfigPaths = generateResourceConfigPaths;
77
+ //# sourceMappingURL=generate.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.cjs","names":["createPathVariable","COMPONENT_SLOT_KEYS","readComponentKeys","SHARED_BRANCH_KEYS","isConfigNode","readSubResourceKeys"],"sources":["../../../src/create-config/paths/generate.ts"],"sourcesContent":["import {\n COMPONENT_SLOT_KEYS,\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n SHARED_BRANCH_KEYS,\n} from '../component-keys';\nimport {\n createPathVariable,\n type ComponentPathVariable,\n type ResourcePathVariable,\n type SubResourcePathVariable,\n} from './variables';\n\n/** Recursion cap for generated paths. Must stay aligned with `MaxPathDepth` in `./types`. */\nexport const MAX_PATH_DEPTH = 6;\n\nconst RESOURCE_VARIABLE: ResourcePathVariable = createPathVariable('resource');\nconst SUB_RESOURCE_VARIABLE: SubResourcePathVariable =\n createPathVariable('subResource');\nconst COMPONENT_VARIABLE: ComponentPathVariable =\n createPathVariable('component');\n\n/** Component tails on one node: its slots, its shared branches, and `$component`. */\nfunction collectComponentTails(node: Record<string, unknown>): string[] {\n const tails: string[] = [];\n\n for (const key of COMPONENT_SLOT_KEYS) {\n if (node[key] !== undefined) {\n tails.push(key);\n }\n }\n\n if (readComponentKeys(node).length > 0) {\n tails.push(COMPONENT_VARIABLE);\n }\n\n for (const branch of SHARED_BRANCH_KEYS) {\n const branchNode = node[branch];\n\n if (!isConfigNode(branchNode)) {\n continue;\n }\n\n tails.push(branch);\n\n for (const key of COMPONENT_SLOT_KEYS) {\n if (branchNode[key] !== undefined) {\n tails.push(`${branch}.${key}`);\n }\n }\n\n if (readComponentKeys(branchNode).length > 0) {\n tails.push(`${branch}.${COMPONENT_VARIABLE}`);\n }\n }\n\n return tails;\n}\n\n/**\n * Component tails valid after a `$subResource` segment: one variable stands for the whole\n * sub-resource chain, so every descendant's tails are reachable.\n */\nfunction collectDescendantComponentTails(\n node: Record<string, unknown>,\n depth: number,\n): string[] {\n if (depth === 0) {\n return [];\n }\n\n const tails = new Set<string>();\n\n for (const key of readSubResourceKeys(node)) {\n const subNode = node[key];\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n for (const tail of collectComponentTails(subNode)) {\n tails.add(tail);\n }\n\n for (const tail of collectDescendantComponentTails(subNode, depth - 1)) {\n tails.add(tail);\n }\n }\n\n return [...tails];\n}\n\n/** Every path tail valid below one config node. */\nfunction collectEntryPaths(\n node: Record<string, unknown>,\n depth: number,\n): string[] {\n if (depth === 0) {\n return [];\n }\n\n const paths = new Set<string>(collectComponentTails(node));\n const subResourceKeys = readSubResourceKeys(node);\n\n if (subResourceKeys.length > 0) {\n paths.add(SUB_RESOURCE_VARIABLE);\n\n for (const tail of collectDescendantComponentTails(node, depth)) {\n paths.add(`${SUB_RESOURCE_VARIABLE}.${tail}`);\n }\n }\n\n for (const key of subResourceKeys) {\n const subNode = node[key];\n\n paths.add(key);\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n for (const nested of collectEntryPaths(subNode, depth - 1)) {\n paths.add(`${key}.${nested}`);\n }\n }\n\n return [...paths];\n}\n\n/**\n * Paths a config accepts, with resource and sub-resource segments available both as\n * literals and as variables. Runtime twin of `ParameterizedResourcePath`.\n */\nexport function generateResourceConfigPaths(\n config: Record<string, unknown>,\n): string[] {\n const paths = new Set<string>();\n\n for (const resource of Object.keys(config)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n paths.add(resource);\n paths.add(RESOURCE_VARIABLE);\n\n for (const tail of collectEntryPaths(resourceNode, MAX_PATH_DEPTH)) {\n paths.add(`${resource}.${tail}`);\n paths.add(`${RESOURCE_VARIABLE}.${tail}`);\n }\n }\n\n return [...paths];\n}\n"],"mappings":";;;;;AAeA,MAAa,iBAAiB;AAE9B,MAAM,oBAA0CA,qCAAmB,UAAU;AAC7E,MAAM,wBACJA,qCAAmB,aAAa;AAClC,MAAM,qBACJA,qCAAmB,WAAW;;AAGhC,SAAS,sBAAsB,MAAyC;CACtE,MAAM,QAAkB,CAAC;CAEzB,KAAK,MAAM,OAAOC,4CAChB,IAAI,KAAK,SAAS,QAChB,MAAM,KAAK,GAAG;CAIlB,IAAIC,yCAAkB,IAAI,EAAE,SAAS,GACnC,MAAM,KAAK,kBAAkB;CAG/B,KAAK,MAAM,UAAUC,2CAAoB;EACvC,MAAM,aAAa,KAAK;EAExB,IAAI,CAACC,oCAAa,UAAU,GAC1B;EAGF,MAAM,KAAK,MAAM;EAEjB,KAAK,MAAM,OAAOH,4CAChB,IAAI,WAAW,SAAS,QACtB,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK;EAIjC,IAAIC,yCAAkB,UAAU,EAAE,SAAS,GACzC,MAAM,KAAK,GAAG,OAAO,GAAG,oBAAoB;CAEhD;CAEA,OAAO;AACT;;;;;AAMA,SAAS,gCACP,MACA,OACU;CACV,IAAI,UAAU,GACZ,OAAO,CAAC;CAGV,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,OAAOG,2CAAoB,IAAI,GAAG;EAC3C,MAAM,UAAU,KAAK;EAErB,IAAI,CAACD,oCAAa,OAAO,GACvB;EAGF,KAAK,MAAM,QAAQ,sBAAsB,OAAO,GAC9C,MAAM,IAAI,IAAI;EAGhB,KAAK,MAAM,QAAQ,gCAAgC,SAAS,QAAQ,CAAC,GACnE,MAAM,IAAI,IAAI;CAElB;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;AAGA,SAAS,kBACP,MACA,OACU;CACV,IAAI,UAAU,GACZ,OAAO,CAAC;CAGV,MAAM,QAAQ,IAAI,IAAY,sBAAsB,IAAI,CAAC;CACzD,MAAM,kBAAkBC,2CAAoB,IAAI;CAEhD,IAAI,gBAAgB,SAAS,GAAG;EAC9B,MAAM,IAAI,qBAAqB;EAE/B,KAAK,MAAM,QAAQ,gCAAgC,MAAM,KAAK,GAC5D,MAAM,IAAI,GAAG,sBAAsB,GAAG,MAAM;CAEhD;CAEA,KAAK,MAAM,OAAO,iBAAiB;EACjC,MAAM,UAAU,KAAK;EAErB,MAAM,IAAI,GAAG;EAEb,IAAI,CAACD,oCAAa,OAAO,GACvB;EAGF,KAAK,MAAM,UAAU,kBAAkB,SAAS,QAAQ,CAAC,GACvD,MAAM,IAAI,GAAG,IAAI,GAAG,QAAQ;CAEhC;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;;;;AAMA,SAAgB,4BACd,QACU;CACV,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,GAAG;EAC1C,MAAM,eAAe,OAAO;EAE5B,IAAI,CAACA,oCAAa,YAAY,GAC5B;EAGF,MAAM,IAAI,QAAQ;EAClB,MAAM,IAAI,iBAAiB;EAE3B,KAAK,MAAM,QAAQ,kBAAkB,eAA4B,GAAG;GAClE,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM;GAC/B,MAAM,IAAI,GAAG,kBAAkB,GAAG,MAAM;EAC1C;CACF;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB"}
@@ -0,0 +1,77 @@
1
+ import { COMPONENT_SLOT_KEYS, SHARED_BRANCH_KEYS, isConfigNode, readComponentKeys, readSubResourceKeys } from "../component-keys.mjs";
2
+ import { createPathVariable } from "./variables.mjs";
3
+
4
+ //#region src/create-config/paths/generate.ts
5
+ /** Recursion cap for generated paths. Must stay aligned with `MaxPathDepth` in `./types`. */
6
+ const MAX_PATH_DEPTH = 6;
7
+ const RESOURCE_VARIABLE = createPathVariable("resource");
8
+ const SUB_RESOURCE_VARIABLE = createPathVariable("subResource");
9
+ const COMPONENT_VARIABLE = createPathVariable("component");
10
+ /** Component tails on one node: its slots, its shared branches, and `$component`. */
11
+ function collectComponentTails(node) {
12
+ const tails = [];
13
+ for (const key of COMPONENT_SLOT_KEYS) if (node[key] !== void 0) tails.push(key);
14
+ if (readComponentKeys(node).length > 0) tails.push(COMPONENT_VARIABLE);
15
+ for (const branch of SHARED_BRANCH_KEYS) {
16
+ const branchNode = node[branch];
17
+ if (!isConfigNode(branchNode)) continue;
18
+ tails.push(branch);
19
+ for (const key of COMPONENT_SLOT_KEYS) if (branchNode[key] !== void 0) tails.push(`${branch}.${key}`);
20
+ if (readComponentKeys(branchNode).length > 0) tails.push(`${branch}.${COMPONENT_VARIABLE}`);
21
+ }
22
+ return tails;
23
+ }
24
+ /**
25
+ * Component tails valid after a `$subResource` segment: one variable stands for the whole
26
+ * sub-resource chain, so every descendant's tails are reachable.
27
+ */
28
+ function collectDescendantComponentTails(node, depth) {
29
+ if (depth === 0) return [];
30
+ const tails = /* @__PURE__ */ new Set();
31
+ for (const key of readSubResourceKeys(node)) {
32
+ const subNode = node[key];
33
+ if (!isConfigNode(subNode)) continue;
34
+ for (const tail of collectComponentTails(subNode)) tails.add(tail);
35
+ for (const tail of collectDescendantComponentTails(subNode, depth - 1)) tails.add(tail);
36
+ }
37
+ return [...tails];
38
+ }
39
+ /** Every path tail valid below one config node. */
40
+ function collectEntryPaths(node, depth) {
41
+ if (depth === 0) return [];
42
+ const paths = new Set(collectComponentTails(node));
43
+ const subResourceKeys = readSubResourceKeys(node);
44
+ if (subResourceKeys.length > 0) {
45
+ paths.add(SUB_RESOURCE_VARIABLE);
46
+ for (const tail of collectDescendantComponentTails(node, depth)) paths.add(`${SUB_RESOURCE_VARIABLE}.${tail}`);
47
+ }
48
+ for (const key of subResourceKeys) {
49
+ const subNode = node[key];
50
+ paths.add(key);
51
+ if (!isConfigNode(subNode)) continue;
52
+ for (const nested of collectEntryPaths(subNode, depth - 1)) paths.add(`${key}.${nested}`);
53
+ }
54
+ return [...paths];
55
+ }
56
+ /**
57
+ * Paths a config accepts, with resource and sub-resource segments available both as
58
+ * literals and as variables. Runtime twin of `ParameterizedResourcePath`.
59
+ */
60
+ function generateResourceConfigPaths(config) {
61
+ const paths = /* @__PURE__ */ new Set();
62
+ for (const resource of Object.keys(config)) {
63
+ const resourceNode = config[resource];
64
+ if (!isConfigNode(resourceNode)) continue;
65
+ paths.add(resource);
66
+ paths.add(RESOURCE_VARIABLE);
67
+ for (const tail of collectEntryPaths(resourceNode, 6)) {
68
+ paths.add(`${resource}.${tail}`);
69
+ paths.add(`${RESOURCE_VARIABLE}.${tail}`);
70
+ }
71
+ }
72
+ return [...paths];
73
+ }
74
+
75
+ //#endregion
76
+ export { generateResourceConfigPaths };
77
+ //# sourceMappingURL=generate.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.mjs","names":[],"sources":["../../../src/create-config/paths/generate.ts"],"sourcesContent":["import {\n COMPONENT_SLOT_KEYS,\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n SHARED_BRANCH_KEYS,\n} from '../component-keys';\nimport {\n createPathVariable,\n type ComponentPathVariable,\n type ResourcePathVariable,\n type SubResourcePathVariable,\n} from './variables';\n\n/** Recursion cap for generated paths. Must stay aligned with `MaxPathDepth` in `./types`. */\nexport const MAX_PATH_DEPTH = 6;\n\nconst RESOURCE_VARIABLE: ResourcePathVariable = createPathVariable('resource');\nconst SUB_RESOURCE_VARIABLE: SubResourcePathVariable =\n createPathVariable('subResource');\nconst COMPONENT_VARIABLE: ComponentPathVariable =\n createPathVariable('component');\n\n/** Component tails on one node: its slots, its shared branches, and `$component`. */\nfunction collectComponentTails(node: Record<string, unknown>): string[] {\n const tails: string[] = [];\n\n for (const key of COMPONENT_SLOT_KEYS) {\n if (node[key] !== undefined) {\n tails.push(key);\n }\n }\n\n if (readComponentKeys(node).length > 0) {\n tails.push(COMPONENT_VARIABLE);\n }\n\n for (const branch of SHARED_BRANCH_KEYS) {\n const branchNode = node[branch];\n\n if (!isConfigNode(branchNode)) {\n continue;\n }\n\n tails.push(branch);\n\n for (const key of COMPONENT_SLOT_KEYS) {\n if (branchNode[key] !== undefined) {\n tails.push(`${branch}.${key}`);\n }\n }\n\n if (readComponentKeys(branchNode).length > 0) {\n tails.push(`${branch}.${COMPONENT_VARIABLE}`);\n }\n }\n\n return tails;\n}\n\n/**\n * Component tails valid after a `$subResource` segment: one variable stands for the whole\n * sub-resource chain, so every descendant's tails are reachable.\n */\nfunction collectDescendantComponentTails(\n node: Record<string, unknown>,\n depth: number,\n): string[] {\n if (depth === 0) {\n return [];\n }\n\n const tails = new Set<string>();\n\n for (const key of readSubResourceKeys(node)) {\n const subNode = node[key];\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n for (const tail of collectComponentTails(subNode)) {\n tails.add(tail);\n }\n\n for (const tail of collectDescendantComponentTails(subNode, depth - 1)) {\n tails.add(tail);\n }\n }\n\n return [...tails];\n}\n\n/** Every path tail valid below one config node. */\nfunction collectEntryPaths(\n node: Record<string, unknown>,\n depth: number,\n): string[] {\n if (depth === 0) {\n return [];\n }\n\n const paths = new Set<string>(collectComponentTails(node));\n const subResourceKeys = readSubResourceKeys(node);\n\n if (subResourceKeys.length > 0) {\n paths.add(SUB_RESOURCE_VARIABLE);\n\n for (const tail of collectDescendantComponentTails(node, depth)) {\n paths.add(`${SUB_RESOURCE_VARIABLE}.${tail}`);\n }\n }\n\n for (const key of subResourceKeys) {\n const subNode = node[key];\n\n paths.add(key);\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n for (const nested of collectEntryPaths(subNode, depth - 1)) {\n paths.add(`${key}.${nested}`);\n }\n }\n\n return [...paths];\n}\n\n/**\n * Paths a config accepts, with resource and sub-resource segments available both as\n * literals and as variables. Runtime twin of `ParameterizedResourcePath`.\n */\nexport function generateResourceConfigPaths(\n config: Record<string, unknown>,\n): string[] {\n const paths = new Set<string>();\n\n for (const resource of Object.keys(config)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n paths.add(resource);\n paths.add(RESOURCE_VARIABLE);\n\n for (const tail of collectEntryPaths(resourceNode, MAX_PATH_DEPTH)) {\n paths.add(`${resource}.${tail}`);\n paths.add(`${RESOURCE_VARIABLE}.${tail}`);\n }\n }\n\n return [...paths];\n}\n"],"mappings":";;;;;AAeA,MAAa,iBAAiB;AAE9B,MAAM,oBAA0C,mBAAmB,UAAU;AAC7E,MAAM,wBACJ,mBAAmB,aAAa;AAClC,MAAM,qBACJ,mBAAmB,WAAW;;AAGhC,SAAS,sBAAsB,MAAyC;CACtE,MAAM,QAAkB,CAAC;CAEzB,KAAK,MAAM,OAAO,qBAChB,IAAI,KAAK,SAAS,QAChB,MAAM,KAAK,GAAG;CAIlB,IAAI,kBAAkB,IAAI,EAAE,SAAS,GACnC,MAAM,KAAK,kBAAkB;CAG/B,KAAK,MAAM,UAAU,oBAAoB;EACvC,MAAM,aAAa,KAAK;EAExB,IAAI,CAAC,aAAa,UAAU,GAC1B;EAGF,MAAM,KAAK,MAAM;EAEjB,KAAK,MAAM,OAAO,qBAChB,IAAI,WAAW,SAAS,QACtB,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK;EAIjC,IAAI,kBAAkB,UAAU,EAAE,SAAS,GACzC,MAAM,KAAK,GAAG,OAAO,GAAG,oBAAoB;CAEhD;CAEA,OAAO;AACT;;;;;AAMA,SAAS,gCACP,MACA,OACU;CACV,IAAI,UAAU,GACZ,OAAO,CAAC;CAGV,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,OAAO,oBAAoB,IAAI,GAAG;EAC3C,MAAM,UAAU,KAAK;EAErB,IAAI,CAAC,aAAa,OAAO,GACvB;EAGF,KAAK,MAAM,QAAQ,sBAAsB,OAAO,GAC9C,MAAM,IAAI,IAAI;EAGhB,KAAK,MAAM,QAAQ,gCAAgC,SAAS,QAAQ,CAAC,GACnE,MAAM,IAAI,IAAI;CAElB;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;AAGA,SAAS,kBACP,MACA,OACU;CACV,IAAI,UAAU,GACZ,OAAO,CAAC;CAGV,MAAM,QAAQ,IAAI,IAAY,sBAAsB,IAAI,CAAC;CACzD,MAAM,kBAAkB,oBAAoB,IAAI;CAEhD,IAAI,gBAAgB,SAAS,GAAG;EAC9B,MAAM,IAAI,qBAAqB;EAE/B,KAAK,MAAM,QAAQ,gCAAgC,MAAM,KAAK,GAC5D,MAAM,IAAI,GAAG,sBAAsB,GAAG,MAAM;CAEhD;CAEA,KAAK,MAAM,OAAO,iBAAiB;EACjC,MAAM,UAAU,KAAK;EAErB,MAAM,IAAI,GAAG;EAEb,IAAI,CAAC,aAAa,OAAO,GACvB;EAGF,KAAK,MAAM,UAAU,kBAAkB,SAAS,QAAQ,CAAC,GACvD,MAAM,IAAI,GAAG,IAAI,GAAG,QAAQ;CAEhC;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;;;;AAMA,SAAgB,4BACd,QACU;CACV,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,GAAG;EAC1C,MAAM,eAAe,OAAO;EAE5B,IAAI,CAAC,aAAa,YAAY,GAC5B;EAGF,MAAM,IAAI,QAAQ;EAClB,MAAM,IAAI,iBAAiB;EAE3B,KAAK,MAAM,QAAQ,kBAAkB,eAA4B,GAAG;GAClE,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM;GAC/B,MAAM,IAAI,GAAG,kBAAkB,GAAG,MAAM;EAC1C;CACF;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB"}
@@ -0,0 +1,2 @@
1
+ import { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathHead, PathTail, PathVariable, PathVariableIdentifier, ResourcePathVariable, SubResourcePathVariable } from "./variables.cjs";
2
+ import { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveConfigNode, ResolveParameterizedPathValue, ResourceSubResourceKeys } from "./types.cjs";
@@ -0,0 +1,2 @@
1
+ import { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathHead, PathTail, PathVariable, PathVariableIdentifier, ResourcePathVariable, SubResourcePathVariable } from "./variables.mjs";
2
+ import { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveConfigNode, ResolveParameterizedPathValue, ResourceSubResourceKeys } from "./types.mjs";
@@ -0,0 +1,123 @@
1
+ const require_component_keys = require('../component-keys.cjs');
2
+ const require_variables = require('./variables.cjs');
3
+
4
+ //#region src/create-config/paths/introspect.ts
5
+ /** Every branch below `node`, at any depth within the path depth cap. */
6
+ function collectDescendantNodes(node, depth = 6) {
7
+ if (depth === 0) return [];
8
+ const nodes = [];
9
+ for (const key of require_component_keys.readSubResourceKeys(node)) {
10
+ const subNode = node[key];
11
+ if (!require_component_keys.isConfigNode(subNode)) continue;
12
+ nodes.push(subNode, ...collectDescendantNodes(subNode, depth - 1));
13
+ }
14
+ return nodes;
15
+ }
16
+ /** Sub-resource keys on `node` and below it, matching the values a nested param accepts. */
17
+ function collectSubResourceKeysBelow(node, depth = 6) {
18
+ const keys = new Set(require_component_keys.readSubResourceKeys(node));
19
+ for (const descendant of collectDescendantNodes(node, depth)) for (const key of require_component_keys.readSubResourceKeys(descendant)) keys.add(key);
20
+ return [...keys];
21
+ }
22
+ /**
23
+ * Whether the segments can be walked from `node`, treating variables as wildcards.
24
+ * Used to narrow which resources a `$resource` path can target.
25
+ */
26
+ function pathExistsOnNode(node, segments) {
27
+ if (segments.length === 0) return true;
28
+ if (!require_component_keys.isConfigNode(node)) return false;
29
+ const [segment, ...rest] = segments;
30
+ if (segment === void 0) return true;
31
+ const variableName = require_variables.readPathVariableName(segment);
32
+ if (variableName === "subResource") return collectDescendantNodes(node).some((descendant) => pathExistsOnNode(descendant, rest));
33
+ if (variableName === "component") return require_component_keys.readComponentKeys(node).some((key) => pathExistsOnNode(node[key], rest));
34
+ if (variableName !== void 0) return false;
35
+ const next = node[segment];
36
+ return next !== void 0 && pathExistsOnNode(next, rest);
37
+ }
38
+ /** Resource keys configured in a config map. */
39
+ function collectConfigResources(config) {
40
+ return Object.keys(config).filter((key) => require_component_keys.isConfigNode(config[key]));
41
+ }
42
+ /**
43
+ * Resources a path can target. A `$resource` path keeps only the resources whose config
44
+ * satisfies the path's fixed segments; a literal path keeps just that resource.
45
+ */
46
+ function collectPathResources(config, path) {
47
+ const [head, ...rest] = path.split(".");
48
+ const resources = collectConfigResources(config);
49
+ if (head === void 0) return [];
50
+ if (require_variables.readPathVariableName(head) === "resource") return resources.filter((resource) => pathExistsOnNode(config[resource], rest));
51
+ return resources.filter((resource) => resource === head && pathExistsOnNode(config[resource], rest));
52
+ }
53
+ /** Nodes a path's fixed prefix resolves to, stopping before `segments` runs out. */
54
+ function collectNodesForSegments(node, segments) {
55
+ let frontier = [node];
56
+ for (const segment of segments) {
57
+ const next = [];
58
+ const variableName = require_variables.readPathVariableName(segment);
59
+ for (const current of frontier) {
60
+ if (variableName === "subResource") {
61
+ next.push(...collectDescendantNodes(current));
62
+ continue;
63
+ }
64
+ if (variableName === "component") {
65
+ for (const key of require_component_keys.readComponentKeys(current)) {
66
+ const value = current[key];
67
+ if (require_component_keys.isConfigNode(value)) next.push(value);
68
+ }
69
+ continue;
70
+ }
71
+ if (variableName !== void 0) continue;
72
+ const value = current[segment];
73
+ if (require_component_keys.isConfigNode(value)) next.push(value);
74
+ }
75
+ frontier = next;
76
+ }
77
+ return frontier;
78
+ }
79
+ /** Sub-resource keys valid for the `$subResource` segment of a path. */
80
+ function collectPathSubResourceKeys(config, path) {
81
+ const segments = path.split(".");
82
+ const subResourceIndex = segments.findIndex((segment) => require_variables.readPathVariableName(segment) === "subResource");
83
+ const keys = /* @__PURE__ */ new Set();
84
+ for (const resource of collectPathResources(config, path)) {
85
+ const resourceNode = config[resource];
86
+ if (!require_component_keys.isConfigNode(resourceNode)) continue;
87
+ const prefix = subResourceIndex === -1 ? [] : segments.slice(1, subResourceIndex);
88
+ for (const node of collectNodesForSegments(resourceNode, prefix)) for (const key of collectSubResourceKeysBelow(node)) keys.add(key);
89
+ }
90
+ return [...keys];
91
+ }
92
+ /** Component slot keys configured on the node a path resolves to. */
93
+ function collectPathComponentKeys(config, path) {
94
+ const tail = path.split(".").slice(1);
95
+ const withoutTrailingComponent = require_variables.readPathVariableName(tail.at(-1) ?? "") === "component" ? tail.slice(0, -1) : tail;
96
+ const keys = /* @__PURE__ */ new Set();
97
+ for (const resource of collectPathResources(config, path)) {
98
+ const resourceNode = config[resource];
99
+ if (!require_component_keys.isConfigNode(resourceNode)) continue;
100
+ for (const node of collectNodesForSegments(resourceNode, withoutTrailingComponent)) for (const key of require_component_keys.readComponentKeys(node)) keys.add(key);
101
+ }
102
+ return [...keys];
103
+ }
104
+ /** Sub-resource keys configured for one resource, at any depth. */
105
+ function collectResourceSubResourceKeys(config, resource) {
106
+ const resourceNode = config[resource];
107
+ return require_component_keys.isConfigNode(resourceNode) ? collectSubResourceKeysBelow(resourceNode) : [];
108
+ }
109
+ /** All sub-resource keys configured anywhere in a config map. */
110
+ function collectAllSubResourceKeys(config) {
111
+ const keys = /* @__PURE__ */ new Set();
112
+ for (const resource of collectConfigResources(config)) for (const key of collectResourceSubResourceKeys(config, resource)) keys.add(key);
113
+ return [...keys];
114
+ }
115
+
116
+ //#endregion
117
+ exports.collectAllSubResourceKeys = collectAllSubResourceKeys;
118
+ exports.collectConfigResources = collectConfigResources;
119
+ exports.collectPathComponentKeys = collectPathComponentKeys;
120
+ exports.collectPathResources = collectPathResources;
121
+ exports.collectPathSubResourceKeys = collectPathSubResourceKeys;
122
+ exports.collectResourceSubResourceKeys = collectResourceSubResourceKeys;
123
+ //# sourceMappingURL=introspect.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.cjs","names":["readSubResourceKeys","isConfigNode","readPathVariableName","readComponentKeys"],"sources":["../../../src/create-config/paths/introspect.ts"],"sourcesContent":["import {\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n} from '../component-keys';\nimport { MAX_PATH_DEPTH } from './generate';\nimport { readPathVariableName } from './variables';\n\n/** Every branch below `node`, at any depth within the path depth cap. */\nexport function collectDescendantNodes(\n node: Record<string, unknown>,\n depth = MAX_PATH_DEPTH,\n): Record<string, unknown>[] {\n if (depth === 0) {\n return [];\n }\n\n const nodes: Record<string, unknown>[] = [];\n\n for (const key of readSubResourceKeys(node)) {\n const subNode = node[key];\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n nodes.push(subNode, ...collectDescendantNodes(subNode, depth - 1));\n }\n\n return nodes;\n}\n\n/** Sub-resource keys on `node` and below it, matching the values a nested param accepts. */\nexport function collectSubResourceKeysBelow(\n node: Record<string, unknown>,\n depth = MAX_PATH_DEPTH,\n): string[] {\n const keys = new Set<string>(readSubResourceKeys(node));\n\n for (const descendant of collectDescendantNodes(node, depth)) {\n for (const key of readSubResourceKeys(descendant)) {\n keys.add(key);\n }\n }\n\n return [...keys];\n}\n\n/**\n * Whether the segments can be walked from `node`, treating variables as wildcards.\n * Used to narrow which resources a `$resource` path can target.\n */\nexport function pathExistsOnNode(\n node: unknown,\n segments: readonly string[],\n): boolean {\n if (segments.length === 0) {\n return true;\n }\n\n if (!isConfigNode(node)) {\n return false;\n }\n\n const [segment, ...rest] = segments;\n\n if (segment === undefined) {\n return true;\n }\n\n const variableName = readPathVariableName(segment);\n\n if (variableName === 'subResource') {\n return collectDescendantNodes(node).some((descendant) =>\n pathExistsOnNode(descendant, rest),\n );\n }\n\n if (variableName === 'component') {\n return readComponentKeys(node).some((key) =>\n pathExistsOnNode(node[key], rest),\n );\n }\n\n if (variableName !== undefined) {\n return false;\n }\n\n const next = node[segment];\n\n return next !== undefined && pathExistsOnNode(next, rest);\n}\n\n/** Resource keys configured in a config map. */\nexport function collectConfigResources(\n config: Record<string, unknown>,\n): string[] {\n return Object.keys(config).filter((key) => isConfigNode(config[key]));\n}\n\n/**\n * Resources a path can target. A `$resource` path keeps only the resources whose config\n * satisfies the path's fixed segments; a literal path keeps just that resource.\n */\nexport function collectPathResources(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const [head, ...rest] = path.split('.');\n const resources = collectConfigResources(config);\n\n if (head === undefined) {\n return [];\n }\n\n if (readPathVariableName(head) === 'resource') {\n return resources.filter((resource) =>\n pathExistsOnNode(config[resource], rest),\n );\n }\n\n return resources.filter(\n (resource) => resource === head && pathExistsOnNode(config[resource], rest),\n );\n}\n\n/** Nodes a path's fixed prefix resolves to, stopping before `segments` runs out. */\nfunction collectNodesForSegments(\n node: Record<string, unknown>,\n segments: readonly string[],\n): Record<string, unknown>[] {\n let frontier: Record<string, unknown>[] = [node];\n\n for (const segment of segments) {\n const next: Record<string, unknown>[] = [];\n const variableName = readPathVariableName(segment);\n\n for (const current of frontier) {\n if (variableName === 'subResource') {\n next.push(...collectDescendantNodes(current));\n continue;\n }\n\n if (variableName === 'component') {\n for (const key of readComponentKeys(current)) {\n const value = current[key];\n\n if (isConfigNode(value)) {\n next.push(value);\n }\n }\n continue;\n }\n\n if (variableName !== undefined) {\n continue;\n }\n\n const value = current[segment];\n\n if (isConfigNode(value)) {\n next.push(value);\n }\n }\n\n frontier = next;\n }\n\n return frontier;\n}\n\n/** Sub-resource keys valid for the `$subResource` segment of a path. */\nexport function collectPathSubResourceKeys(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const segments = path.split('.');\n const subResourceIndex = segments.findIndex(\n (segment) => readPathVariableName(segment) === 'subResource',\n );\n const keys = new Set<string>();\n\n for (const resource of collectPathResources(config, path)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n const prefix =\n subResourceIndex === -1 ? [] : segments.slice(1, subResourceIndex);\n\n for (const node of collectNodesForSegments(resourceNode, prefix)) {\n for (const key of collectSubResourceKeysBelow(node)) {\n keys.add(key);\n }\n }\n }\n\n return [...keys];\n}\n\n/** Component slot keys configured on the node a path resolves to. */\nexport function collectPathComponentKeys(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const segments = path.split('.');\n const tail = segments.slice(1);\n const withoutTrailingComponent =\n readPathVariableName(tail.at(-1) ?? '') === 'component'\n ? tail.slice(0, -1)\n : tail;\n const keys = new Set<string>();\n\n for (const resource of collectPathResources(config, path)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n for (const node of collectNodesForSegments(\n resourceNode,\n withoutTrailingComponent,\n )) {\n for (const key of readComponentKeys(node)) {\n keys.add(key);\n }\n }\n }\n\n return [...keys];\n}\n\n/** Sub-resource keys configured for one resource, at any depth. */\nexport function collectResourceSubResourceKeys(\n config: Record<string, unknown>,\n resource: string,\n): string[] {\n const resourceNode = config[resource];\n\n return isConfigNode(resourceNode)\n ? collectSubResourceKeysBelow(resourceNode)\n : [];\n}\n\n/** All sub-resource keys configured anywhere in a config map. */\nexport function collectAllSubResourceKeys(\n config: Record<string, unknown>,\n): string[] {\n const keys = new Set<string>();\n\n for (const resource of collectConfigResources(config)) {\n for (const key of collectResourceSubResourceKeys(config, resource)) {\n keys.add(key);\n }\n }\n\n return [...keys];\n}\n"],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import { isConfigNode, readComponentKeys, readSubResourceKeys } from "../component-keys.mjs";
2
+ import { readPathVariableName } from "./variables.mjs";
3
+
4
+ //#region src/create-config/paths/introspect.ts
5
+ /** Every branch below `node`, at any depth within the path depth cap. */
6
+ function collectDescendantNodes(node, depth = 6) {
7
+ if (depth === 0) return [];
8
+ const nodes = [];
9
+ for (const key of readSubResourceKeys(node)) {
10
+ const subNode = node[key];
11
+ if (!isConfigNode(subNode)) continue;
12
+ nodes.push(subNode, ...collectDescendantNodes(subNode, depth - 1));
13
+ }
14
+ return nodes;
15
+ }
16
+ /** Sub-resource keys on `node` and below it, matching the values a nested param accepts. */
17
+ function collectSubResourceKeysBelow(node, depth = 6) {
18
+ const keys = new Set(readSubResourceKeys(node));
19
+ for (const descendant of collectDescendantNodes(node, depth)) for (const key of readSubResourceKeys(descendant)) keys.add(key);
20
+ return [...keys];
21
+ }
22
+ /**
23
+ * Whether the segments can be walked from `node`, treating variables as wildcards.
24
+ * Used to narrow which resources a `$resource` path can target.
25
+ */
26
+ function pathExistsOnNode(node, segments) {
27
+ if (segments.length === 0) return true;
28
+ if (!isConfigNode(node)) return false;
29
+ const [segment, ...rest] = segments;
30
+ if (segment === void 0) return true;
31
+ const variableName = readPathVariableName(segment);
32
+ if (variableName === "subResource") return collectDescendantNodes(node).some((descendant) => pathExistsOnNode(descendant, rest));
33
+ if (variableName === "component") return readComponentKeys(node).some((key) => pathExistsOnNode(node[key], rest));
34
+ if (variableName !== void 0) return false;
35
+ const next = node[segment];
36
+ return next !== void 0 && pathExistsOnNode(next, rest);
37
+ }
38
+ /** Resource keys configured in a config map. */
39
+ function collectConfigResources(config) {
40
+ return Object.keys(config).filter((key) => isConfigNode(config[key]));
41
+ }
42
+ /**
43
+ * Resources a path can target. A `$resource` path keeps only the resources whose config
44
+ * satisfies the path's fixed segments; a literal path keeps just that resource.
45
+ */
46
+ function collectPathResources(config, path) {
47
+ const [head, ...rest] = path.split(".");
48
+ const resources = collectConfigResources(config);
49
+ if (head === void 0) return [];
50
+ if (readPathVariableName(head) === "resource") return resources.filter((resource) => pathExistsOnNode(config[resource], rest));
51
+ return resources.filter((resource) => resource === head && pathExistsOnNode(config[resource], rest));
52
+ }
53
+ /** Nodes a path's fixed prefix resolves to, stopping before `segments` runs out. */
54
+ function collectNodesForSegments(node, segments) {
55
+ let frontier = [node];
56
+ for (const segment of segments) {
57
+ const next = [];
58
+ const variableName = readPathVariableName(segment);
59
+ for (const current of frontier) {
60
+ if (variableName === "subResource") {
61
+ next.push(...collectDescendantNodes(current));
62
+ continue;
63
+ }
64
+ if (variableName === "component") {
65
+ for (const key of readComponentKeys(current)) {
66
+ const value = current[key];
67
+ if (isConfigNode(value)) next.push(value);
68
+ }
69
+ continue;
70
+ }
71
+ if (variableName !== void 0) continue;
72
+ const value = current[segment];
73
+ if (isConfigNode(value)) next.push(value);
74
+ }
75
+ frontier = next;
76
+ }
77
+ return frontier;
78
+ }
79
+ /** Sub-resource keys valid for the `$subResource` segment of a path. */
80
+ function collectPathSubResourceKeys(config, path) {
81
+ const segments = path.split(".");
82
+ const subResourceIndex = segments.findIndex((segment) => readPathVariableName(segment) === "subResource");
83
+ const keys = /* @__PURE__ */ new Set();
84
+ for (const resource of collectPathResources(config, path)) {
85
+ const resourceNode = config[resource];
86
+ if (!isConfigNode(resourceNode)) continue;
87
+ const prefix = subResourceIndex === -1 ? [] : segments.slice(1, subResourceIndex);
88
+ for (const node of collectNodesForSegments(resourceNode, prefix)) for (const key of collectSubResourceKeysBelow(node)) keys.add(key);
89
+ }
90
+ return [...keys];
91
+ }
92
+ /** Component slot keys configured on the node a path resolves to. */
93
+ function collectPathComponentKeys(config, path) {
94
+ const tail = path.split(".").slice(1);
95
+ const withoutTrailingComponent = readPathVariableName(tail.at(-1) ?? "") === "component" ? tail.slice(0, -1) : tail;
96
+ const keys = /* @__PURE__ */ new Set();
97
+ for (const resource of collectPathResources(config, path)) {
98
+ const resourceNode = config[resource];
99
+ if (!isConfigNode(resourceNode)) continue;
100
+ for (const node of collectNodesForSegments(resourceNode, withoutTrailingComponent)) for (const key of readComponentKeys(node)) keys.add(key);
101
+ }
102
+ return [...keys];
103
+ }
104
+ /** Sub-resource keys configured for one resource, at any depth. */
105
+ function collectResourceSubResourceKeys(config, resource) {
106
+ const resourceNode = config[resource];
107
+ return isConfigNode(resourceNode) ? collectSubResourceKeysBelow(resourceNode) : [];
108
+ }
109
+ /** All sub-resource keys configured anywhere in a config map. */
110
+ function collectAllSubResourceKeys(config) {
111
+ const keys = /* @__PURE__ */ new Set();
112
+ for (const resource of collectConfigResources(config)) for (const key of collectResourceSubResourceKeys(config, resource)) keys.add(key);
113
+ return [...keys];
114
+ }
115
+
116
+ //#endregion
117
+ export { collectAllSubResourceKeys, collectConfigResources, collectPathComponentKeys, collectPathResources, collectPathSubResourceKeys, collectResourceSubResourceKeys };
118
+ //# sourceMappingURL=introspect.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspect.mjs","names":[],"sources":["../../../src/create-config/paths/introspect.ts"],"sourcesContent":["import {\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n} from '../component-keys';\nimport { MAX_PATH_DEPTH } from './generate';\nimport { readPathVariableName } from './variables';\n\n/** Every branch below `node`, at any depth within the path depth cap. */\nexport function collectDescendantNodes(\n node: Record<string, unknown>,\n depth = MAX_PATH_DEPTH,\n): Record<string, unknown>[] {\n if (depth === 0) {\n return [];\n }\n\n const nodes: Record<string, unknown>[] = [];\n\n for (const key of readSubResourceKeys(node)) {\n const subNode = node[key];\n\n if (!isConfigNode(subNode)) {\n continue;\n }\n\n nodes.push(subNode, ...collectDescendantNodes(subNode, depth - 1));\n }\n\n return nodes;\n}\n\n/** Sub-resource keys on `node` and below it, matching the values a nested param accepts. */\nexport function collectSubResourceKeysBelow(\n node: Record<string, unknown>,\n depth = MAX_PATH_DEPTH,\n): string[] {\n const keys = new Set<string>(readSubResourceKeys(node));\n\n for (const descendant of collectDescendantNodes(node, depth)) {\n for (const key of readSubResourceKeys(descendant)) {\n keys.add(key);\n }\n }\n\n return [...keys];\n}\n\n/**\n * Whether the segments can be walked from `node`, treating variables as wildcards.\n * Used to narrow which resources a `$resource` path can target.\n */\nexport function pathExistsOnNode(\n node: unknown,\n segments: readonly string[],\n): boolean {\n if (segments.length === 0) {\n return true;\n }\n\n if (!isConfigNode(node)) {\n return false;\n }\n\n const [segment, ...rest] = segments;\n\n if (segment === undefined) {\n return true;\n }\n\n const variableName = readPathVariableName(segment);\n\n if (variableName === 'subResource') {\n return collectDescendantNodes(node).some((descendant) =>\n pathExistsOnNode(descendant, rest),\n );\n }\n\n if (variableName === 'component') {\n return readComponentKeys(node).some((key) =>\n pathExistsOnNode(node[key], rest),\n );\n }\n\n if (variableName !== undefined) {\n return false;\n }\n\n const next = node[segment];\n\n return next !== undefined && pathExistsOnNode(next, rest);\n}\n\n/** Resource keys configured in a config map. */\nexport function collectConfigResources(\n config: Record<string, unknown>,\n): string[] {\n return Object.keys(config).filter((key) => isConfigNode(config[key]));\n}\n\n/**\n * Resources a path can target. A `$resource` path keeps only the resources whose config\n * satisfies the path's fixed segments; a literal path keeps just that resource.\n */\nexport function collectPathResources(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const [head, ...rest] = path.split('.');\n const resources = collectConfigResources(config);\n\n if (head === undefined) {\n return [];\n }\n\n if (readPathVariableName(head) === 'resource') {\n return resources.filter((resource) =>\n pathExistsOnNode(config[resource], rest),\n );\n }\n\n return resources.filter(\n (resource) => resource === head && pathExistsOnNode(config[resource], rest),\n );\n}\n\n/** Nodes a path's fixed prefix resolves to, stopping before `segments` runs out. */\nfunction collectNodesForSegments(\n node: Record<string, unknown>,\n segments: readonly string[],\n): Record<string, unknown>[] {\n let frontier: Record<string, unknown>[] = [node];\n\n for (const segment of segments) {\n const next: Record<string, unknown>[] = [];\n const variableName = readPathVariableName(segment);\n\n for (const current of frontier) {\n if (variableName === 'subResource') {\n next.push(...collectDescendantNodes(current));\n continue;\n }\n\n if (variableName === 'component') {\n for (const key of readComponentKeys(current)) {\n const value = current[key];\n\n if (isConfigNode(value)) {\n next.push(value);\n }\n }\n continue;\n }\n\n if (variableName !== undefined) {\n continue;\n }\n\n const value = current[segment];\n\n if (isConfigNode(value)) {\n next.push(value);\n }\n }\n\n frontier = next;\n }\n\n return frontier;\n}\n\n/** Sub-resource keys valid for the `$subResource` segment of a path. */\nexport function collectPathSubResourceKeys(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const segments = path.split('.');\n const subResourceIndex = segments.findIndex(\n (segment) => readPathVariableName(segment) === 'subResource',\n );\n const keys = new Set<string>();\n\n for (const resource of collectPathResources(config, path)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n const prefix =\n subResourceIndex === -1 ? [] : segments.slice(1, subResourceIndex);\n\n for (const node of collectNodesForSegments(resourceNode, prefix)) {\n for (const key of collectSubResourceKeysBelow(node)) {\n keys.add(key);\n }\n }\n }\n\n return [...keys];\n}\n\n/** Component slot keys configured on the node a path resolves to. */\nexport function collectPathComponentKeys(\n config: Record<string, unknown>,\n path: string,\n): string[] {\n const segments = path.split('.');\n const tail = segments.slice(1);\n const withoutTrailingComponent =\n readPathVariableName(tail.at(-1) ?? '') === 'component'\n ? tail.slice(0, -1)\n : tail;\n const keys = new Set<string>();\n\n for (const resource of collectPathResources(config, path)) {\n const resourceNode = config[resource];\n\n if (!isConfigNode(resourceNode)) {\n continue;\n }\n\n for (const node of collectNodesForSegments(\n resourceNode,\n withoutTrailingComponent,\n )) {\n for (const key of readComponentKeys(node)) {\n keys.add(key);\n }\n }\n }\n\n return [...keys];\n}\n\n/** Sub-resource keys configured for one resource, at any depth. */\nexport function collectResourceSubResourceKeys(\n config: Record<string, unknown>,\n resource: string,\n): string[] {\n const resourceNode = config[resource];\n\n return isConfigNode(resourceNode)\n ? collectSubResourceKeysBelow(resourceNode)\n : [];\n}\n\n/** All sub-resource keys configured anywhere in a config map. */\nexport function collectAllSubResourceKeys(\n config: Record<string, unknown>,\n): string[] {\n const keys = new Set<string>();\n\n for (const resource of collectConfigResources(config)) {\n for (const key of collectResourceSubResourceKeys(config, resource)) {\n keys.add(key);\n }\n }\n\n return [...keys];\n}\n"],"mappings":"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"}