@jfdevelops/react-layout 0.17.5 → 0.18.0

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 (149) 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 +13 -0
  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 +13 -0
  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/resource.cjs.map +1 -1
  140. package/dist/resource.d.cts +2 -2
  141. package/dist/resource.d.cts.map +1 -1
  142. package/dist/resource.d.mts +2 -2
  143. package/dist/resource.d.mts.map +1 -1
  144. package/dist/resource.mjs.map +1 -1
  145. package/dist/utils.d.cts +2 -1
  146. package/dist/utils.d.cts.map +1 -1
  147. package/dist/utils.d.mts +2 -1
  148. package/dist/utils.d.mts.map +1 -1
  149. package/package.json +1 -1
@@ -0,0 +1,130 @@
1
+ const require_invalid_path = require('../../errors/invalid-path.cjs');
2
+ const require_invalid_resource = require('../../errors/invalid-resource.cjs');
3
+ const require_invalid_sub_resource = require('../../errors/invalid-sub-resource.cjs');
4
+ const require_invalid_component = require('../../errors/invalid-component.cjs');
5
+ const require_missing_path_variable = require('../../errors/missing-path-variable.cjs');
6
+ const require_component_keys = require('../component-keys.cjs');
7
+ const require_variables = require('./variables.cjs');
8
+
9
+ //#region src/create-config/paths/resolve.ts
10
+ function readSubResourceParamKey(param) {
11
+ return typeof param === "string" ? param : param.value;
12
+ }
13
+ /** Sub-resource slugs a param walks through, outermost first. */
14
+ function flattenSubResourceParam(param) {
15
+ if (typeof param === "string") return [param];
16
+ return [param.value, ...flattenSubResourceParam(param.subResource)];
17
+ }
18
+ function isSubResourceParamValue(value) {
19
+ if (typeof value === "string") return value.length > 0;
20
+ if (typeof value !== "object" || value === null) return false;
21
+ const { value: slug, subResource } = value;
22
+ return typeof slug === "string" && isSubResourceParamValue(subResource);
23
+ }
24
+ function resolveSubResourceParam(node, param, resource) {
25
+ const key = readSubResourceParamKey(param);
26
+ if (!require_component_keys.isConfigNode(node)) throw new require_invalid_sub_resource.InvalidSubResourceError({
27
+ subResource: key,
28
+ resource,
29
+ reason: `"${key}" cannot be read because its parent is not a configured resource`
30
+ });
31
+ const next = node[key];
32
+ if (!require_component_keys.isConfigNode(next)) throw new require_invalid_sub_resource.InvalidSubResourceError({
33
+ subResource: key,
34
+ resource,
35
+ validSubResources: require_component_keys.readSubResourceKeys(node)
36
+ });
37
+ if (typeof param === "string") return next;
38
+ return resolveSubResourceParam(next, param.subResource, resource);
39
+ }
40
+ function readVariable(variables, name, path) {
41
+ const value = variables[name];
42
+ if (value === void 0) throw new require_missing_path_variable.MissingPathVariableError({
43
+ variable: name,
44
+ path,
45
+ providedVariables: Object.keys(variables)
46
+ });
47
+ return value;
48
+ }
49
+ /**
50
+ * Reads the value a path points at, substituting variable segments from `variables`.
51
+ * Throws a typed error naming the segment that could not be resolved.
52
+ */
53
+ function resolveParameterizedPath(config, path, variables = {}) {
54
+ const segments = path.split(".");
55
+ let cursor = config;
56
+ let resource;
57
+ for (const [index, segment] of segments.entries()) {
58
+ const isRoot = index === 0;
59
+ const variableName = require_variables.readPathVariableName(segment);
60
+ if (variableName === void 0) {
61
+ if (!require_component_keys.isConfigNode(cursor)) throw new require_invalid_path.InvalidPathError({
62
+ path,
63
+ reason: `"${segment}" cannot be read because the value before it is not a config branch`
64
+ });
65
+ const next = cursor[segment];
66
+ if (next === void 0) {
67
+ if (isRoot) throw new require_invalid_resource.InvalidResourceError({
68
+ resource: segment,
69
+ validResources: Object.keys(config)
70
+ });
71
+ throw new require_invalid_path.InvalidPathError({
72
+ path,
73
+ reason: `"${segment}" is not configured`
74
+ });
75
+ }
76
+ if (isRoot) resource = segment;
77
+ cursor = next;
78
+ continue;
79
+ }
80
+ switch (variableName) {
81
+ case "resource": {
82
+ const value = readVariable(variables, "resource", path);
83
+ if (typeof value !== "string" || !require_component_keys.isConfigNode(config[value])) throw new require_invalid_resource.InvalidResourceError({
84
+ resource: value,
85
+ validResources: Object.keys(config)
86
+ });
87
+ resource = value;
88
+ cursor = config[value];
89
+ break;
90
+ }
91
+ case "subResource": {
92
+ const value = readVariable(variables, "subResource", path);
93
+ if (!isSubResourceParamValue(value)) throw new require_invalid_sub_resource.InvalidSubResourceError({
94
+ subResource: value,
95
+ resource,
96
+ reason: "A sub-resource must be a slug or an object with `value` and `subResource`"
97
+ });
98
+ cursor = resolveSubResourceParam(cursor, value, resource);
99
+ break;
100
+ }
101
+ case "component": {
102
+ const value = readVariable(variables, "component", path);
103
+ if (!require_component_keys.isConfigNode(cursor)) throw new require_invalid_component.InvalidComponentError({
104
+ component: value,
105
+ path,
106
+ resource,
107
+ reason: `"${String(value)}" cannot be read because the value before it is not a config branch`
108
+ });
109
+ if (typeof value !== "string" || cursor[value] === void 0) throw new require_invalid_component.InvalidComponentError({
110
+ component: value,
111
+ path,
112
+ resource,
113
+ validComponents: require_component_keys.readComponentKeys(cursor)
114
+ });
115
+ cursor = cursor[value];
116
+ break;
117
+ }
118
+ default: throw new require_invalid_path.InvalidPathError({
119
+ path,
120
+ reason: `"${segment}" is not a supported path variable`
121
+ });
122
+ }
123
+ }
124
+ return cursor;
125
+ }
126
+
127
+ //#endregion
128
+ exports.flattenSubResourceParam = flattenSubResourceParam;
129
+ exports.resolveParameterizedPath = resolveParameterizedPath;
130
+ //# sourceMappingURL=resolve.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.cjs","names":["isConfigNode","InvalidSubResourceError","readSubResourceKeys","MissingPathVariableError","readPathVariableName","InvalidPathError","InvalidResourceError","InvalidComponentError","readComponentKeys"],"sources":["../../../src/create-config/paths/resolve.ts"],"sourcesContent":["import {\n InvalidComponentError,\n InvalidPathError,\n InvalidResourceError,\n InvalidSubResourceError,\n MissingPathVariableError,\n} from '../../errors';\nimport {\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n} from '../component-keys';\nimport { readPathVariableName } from './variables';\n\n/** A `$subResource` value: a slug, or a slug plus the next `subResource` below it. */\nexport type SubResourceParamValue =\n | string\n | { value: string; subResource: SubResourceParamValue };\n\n/** Values supplied for the variables a path leaves open. */\nexport type PathVariableValues = {\n resource?: string;\n subResource?: SubResourceParamValue;\n component?: string;\n};\n\nfunction readSubResourceParamKey(param: SubResourceParamValue): string {\n return typeof param === 'string' ? param : param.value;\n}\n\n/** Sub-resource slugs a param walks through, outermost first. */\nexport function flattenSubResourceParam(\n param: SubResourceParamValue,\n): string[] {\n if (typeof param === 'string') {\n return [param];\n }\n\n return [param.value, ...flattenSubResourceParam(param.subResource)];\n}\n\nfunction isSubResourceParamValue(\n value: unknown,\n): value is SubResourceParamValue {\n if (typeof value === 'string') {\n return value.length > 0;\n }\n\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const { value: slug, subResource } = value as {\n value?: unknown;\n subResource?: unknown;\n };\n\n return typeof slug === 'string' && isSubResourceParamValue(subResource);\n}\n\nfunction resolveSubResourceParam(\n node: unknown,\n param: SubResourceParamValue,\n resource: string | undefined,\n): unknown {\n const key = readSubResourceParamKey(param);\n\n if (!isConfigNode(node)) {\n throw new InvalidSubResourceError({\n subResource: key,\n resource,\n reason: `\"${key}\" cannot be read because its parent is not a configured resource`,\n });\n }\n\n const next = node[key];\n\n if (!isConfigNode(next)) {\n throw new InvalidSubResourceError({\n subResource: key,\n resource,\n validSubResources: readSubResourceKeys(node),\n });\n }\n\n if (typeof param === 'string') {\n return next;\n }\n\n return resolveSubResourceParam(next, param.subResource, resource);\n}\n\nfunction readVariable<Name extends keyof PathVariableValues>(\n variables: PathVariableValues,\n name: Name,\n path: string,\n): NonNullable<PathVariableValues[Name]> {\n const value = variables[name];\n\n if (value === undefined) {\n throw new MissingPathVariableError({\n variable: name,\n path,\n providedVariables: Object.keys(variables),\n });\n }\n\n return value as NonNullable<PathVariableValues[Name]>;\n}\n\n/**\n * Reads the value a path points at, substituting variable segments from `variables`.\n * Throws a typed error naming the segment that could not be resolved.\n */\nexport function resolveParameterizedPath(\n config: Record<string, unknown>,\n path: string,\n variables: PathVariableValues = {},\n): unknown {\n const segments = path.split('.');\n let cursor: unknown = config;\n let resource: string | undefined;\n\n for (const [index, segment] of segments.entries()) {\n const isRoot = index === 0;\n const variableName = readPathVariableName(segment);\n\n if (variableName === undefined) {\n if (!isConfigNode(cursor)) {\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" cannot be read because the value before it is not a config branch`,\n });\n }\n\n const next = cursor[segment];\n\n if (next === undefined) {\n if (isRoot) {\n throw new InvalidResourceError({\n resource: segment,\n validResources: Object.keys(config),\n });\n }\n\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" is not configured`,\n });\n }\n\n if (isRoot) {\n resource = segment;\n }\n\n cursor = next;\n continue;\n }\n\n switch (variableName) {\n case 'resource': {\n const value = readVariable(variables, 'resource', path);\n\n if (typeof value !== 'string' || !isConfigNode(config[value])) {\n throw new InvalidResourceError({\n resource: value,\n validResources: Object.keys(config),\n });\n }\n\n resource = value;\n cursor = config[value];\n break;\n }\n case 'subResource': {\n const value = readVariable(variables, 'subResource', path);\n\n if (!isSubResourceParamValue(value)) {\n throw new InvalidSubResourceError({\n subResource: value,\n resource,\n reason:\n 'A sub-resource must be a slug or an object with `value` and `subResource`',\n });\n }\n\n cursor = resolveSubResourceParam(cursor, value, resource);\n break;\n }\n case 'component': {\n const value = readVariable(variables, 'component', path);\n\n if (!isConfigNode(cursor)) {\n throw new InvalidComponentError({\n component: value,\n path,\n resource,\n reason: `\"${String(value)}\" cannot be read because the value before it is not a config branch`,\n });\n }\n\n if (typeof value !== 'string' || cursor[value] === undefined) {\n throw new InvalidComponentError({\n component: value,\n path,\n resource,\n validComponents: readComponentKeys(cursor),\n });\n }\n\n cursor = cursor[value];\n break;\n }\n default: {\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" is not a supported path variable`,\n });\n }\n }\n }\n\n return cursor;\n}\n"],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ import { InvalidPathError } from "../../errors/invalid-path.mjs";
2
+ import { InvalidResourceError } from "../../errors/invalid-resource.mjs";
3
+ import { InvalidSubResourceError } from "../../errors/invalid-sub-resource.mjs";
4
+ import { InvalidComponentError } from "../../errors/invalid-component.mjs";
5
+ import { MissingPathVariableError } from "../../errors/missing-path-variable.mjs";
6
+ import { isConfigNode, readComponentKeys, readSubResourceKeys } from "../component-keys.mjs";
7
+ import { readPathVariableName } from "./variables.mjs";
8
+
9
+ //#region src/create-config/paths/resolve.ts
10
+ function readSubResourceParamKey(param) {
11
+ return typeof param === "string" ? param : param.value;
12
+ }
13
+ /** Sub-resource slugs a param walks through, outermost first. */
14
+ function flattenSubResourceParam(param) {
15
+ if (typeof param === "string") return [param];
16
+ return [param.value, ...flattenSubResourceParam(param.subResource)];
17
+ }
18
+ function isSubResourceParamValue(value) {
19
+ if (typeof value === "string") return value.length > 0;
20
+ if (typeof value !== "object" || value === null) return false;
21
+ const { value: slug, subResource } = value;
22
+ return typeof slug === "string" && isSubResourceParamValue(subResource);
23
+ }
24
+ function resolveSubResourceParam(node, param, resource) {
25
+ const key = readSubResourceParamKey(param);
26
+ if (!isConfigNode(node)) throw new InvalidSubResourceError({
27
+ subResource: key,
28
+ resource,
29
+ reason: `"${key}" cannot be read because its parent is not a configured resource`
30
+ });
31
+ const next = node[key];
32
+ if (!isConfigNode(next)) throw new InvalidSubResourceError({
33
+ subResource: key,
34
+ resource,
35
+ validSubResources: readSubResourceKeys(node)
36
+ });
37
+ if (typeof param === "string") return next;
38
+ return resolveSubResourceParam(next, param.subResource, resource);
39
+ }
40
+ function readVariable(variables, name, path) {
41
+ const value = variables[name];
42
+ if (value === void 0) throw new MissingPathVariableError({
43
+ variable: name,
44
+ path,
45
+ providedVariables: Object.keys(variables)
46
+ });
47
+ return value;
48
+ }
49
+ /**
50
+ * Reads the value a path points at, substituting variable segments from `variables`.
51
+ * Throws a typed error naming the segment that could not be resolved.
52
+ */
53
+ function resolveParameterizedPath(config, path, variables = {}) {
54
+ const segments = path.split(".");
55
+ let cursor = config;
56
+ let resource;
57
+ for (const [index, segment] of segments.entries()) {
58
+ const isRoot = index === 0;
59
+ const variableName = readPathVariableName(segment);
60
+ if (variableName === void 0) {
61
+ if (!isConfigNode(cursor)) throw new InvalidPathError({
62
+ path,
63
+ reason: `"${segment}" cannot be read because the value before it is not a config branch`
64
+ });
65
+ const next = cursor[segment];
66
+ if (next === void 0) {
67
+ if (isRoot) throw new InvalidResourceError({
68
+ resource: segment,
69
+ validResources: Object.keys(config)
70
+ });
71
+ throw new InvalidPathError({
72
+ path,
73
+ reason: `"${segment}" is not configured`
74
+ });
75
+ }
76
+ if (isRoot) resource = segment;
77
+ cursor = next;
78
+ continue;
79
+ }
80
+ switch (variableName) {
81
+ case "resource": {
82
+ const value = readVariable(variables, "resource", path);
83
+ if (typeof value !== "string" || !isConfigNode(config[value])) throw new InvalidResourceError({
84
+ resource: value,
85
+ validResources: Object.keys(config)
86
+ });
87
+ resource = value;
88
+ cursor = config[value];
89
+ break;
90
+ }
91
+ case "subResource": {
92
+ const value = readVariable(variables, "subResource", path);
93
+ if (!isSubResourceParamValue(value)) throw new InvalidSubResourceError({
94
+ subResource: value,
95
+ resource,
96
+ reason: "A sub-resource must be a slug or an object with `value` and `subResource`"
97
+ });
98
+ cursor = resolveSubResourceParam(cursor, value, resource);
99
+ break;
100
+ }
101
+ case "component": {
102
+ const value = readVariable(variables, "component", path);
103
+ if (!isConfigNode(cursor)) throw new InvalidComponentError({
104
+ component: value,
105
+ path,
106
+ resource,
107
+ reason: `"${String(value)}" cannot be read because the value before it is not a config branch`
108
+ });
109
+ if (typeof value !== "string" || cursor[value] === void 0) throw new InvalidComponentError({
110
+ component: value,
111
+ path,
112
+ resource,
113
+ validComponents: readComponentKeys(cursor)
114
+ });
115
+ cursor = cursor[value];
116
+ break;
117
+ }
118
+ default: throw new InvalidPathError({
119
+ path,
120
+ reason: `"${segment}" is not a supported path variable`
121
+ });
122
+ }
123
+ }
124
+ return cursor;
125
+ }
126
+
127
+ //#endregion
128
+ export { flattenSubResourceParam, resolveParameterizedPath };
129
+ //# sourceMappingURL=resolve.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.mjs","names":[],"sources":["../../../src/create-config/paths/resolve.ts"],"sourcesContent":["import {\n InvalidComponentError,\n InvalidPathError,\n InvalidResourceError,\n InvalidSubResourceError,\n MissingPathVariableError,\n} from '../../errors';\nimport {\n isConfigNode,\n readComponentKeys,\n readSubResourceKeys,\n} from '../component-keys';\nimport { readPathVariableName } from './variables';\n\n/** A `$subResource` value: a slug, or a slug plus the next `subResource` below it. */\nexport type SubResourceParamValue =\n | string\n | { value: string; subResource: SubResourceParamValue };\n\n/** Values supplied for the variables a path leaves open. */\nexport type PathVariableValues = {\n resource?: string;\n subResource?: SubResourceParamValue;\n component?: string;\n};\n\nfunction readSubResourceParamKey(param: SubResourceParamValue): string {\n return typeof param === 'string' ? param : param.value;\n}\n\n/** Sub-resource slugs a param walks through, outermost first. */\nexport function flattenSubResourceParam(\n param: SubResourceParamValue,\n): string[] {\n if (typeof param === 'string') {\n return [param];\n }\n\n return [param.value, ...flattenSubResourceParam(param.subResource)];\n}\n\nfunction isSubResourceParamValue(\n value: unknown,\n): value is SubResourceParamValue {\n if (typeof value === 'string') {\n return value.length > 0;\n }\n\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const { value: slug, subResource } = value as {\n value?: unknown;\n subResource?: unknown;\n };\n\n return typeof slug === 'string' && isSubResourceParamValue(subResource);\n}\n\nfunction resolveSubResourceParam(\n node: unknown,\n param: SubResourceParamValue,\n resource: string | undefined,\n): unknown {\n const key = readSubResourceParamKey(param);\n\n if (!isConfigNode(node)) {\n throw new InvalidSubResourceError({\n subResource: key,\n resource,\n reason: `\"${key}\" cannot be read because its parent is not a configured resource`,\n });\n }\n\n const next = node[key];\n\n if (!isConfigNode(next)) {\n throw new InvalidSubResourceError({\n subResource: key,\n resource,\n validSubResources: readSubResourceKeys(node),\n });\n }\n\n if (typeof param === 'string') {\n return next;\n }\n\n return resolveSubResourceParam(next, param.subResource, resource);\n}\n\nfunction readVariable<Name extends keyof PathVariableValues>(\n variables: PathVariableValues,\n name: Name,\n path: string,\n): NonNullable<PathVariableValues[Name]> {\n const value = variables[name];\n\n if (value === undefined) {\n throw new MissingPathVariableError({\n variable: name,\n path,\n providedVariables: Object.keys(variables),\n });\n }\n\n return value as NonNullable<PathVariableValues[Name]>;\n}\n\n/**\n * Reads the value a path points at, substituting variable segments from `variables`.\n * Throws a typed error naming the segment that could not be resolved.\n */\nexport function resolveParameterizedPath(\n config: Record<string, unknown>,\n path: string,\n variables: PathVariableValues = {},\n): unknown {\n const segments = path.split('.');\n let cursor: unknown = config;\n let resource: string | undefined;\n\n for (const [index, segment] of segments.entries()) {\n const isRoot = index === 0;\n const variableName = readPathVariableName(segment);\n\n if (variableName === undefined) {\n if (!isConfigNode(cursor)) {\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" cannot be read because the value before it is not a config branch`,\n });\n }\n\n const next = cursor[segment];\n\n if (next === undefined) {\n if (isRoot) {\n throw new InvalidResourceError({\n resource: segment,\n validResources: Object.keys(config),\n });\n }\n\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" is not configured`,\n });\n }\n\n if (isRoot) {\n resource = segment;\n }\n\n cursor = next;\n continue;\n }\n\n switch (variableName) {\n case 'resource': {\n const value = readVariable(variables, 'resource', path);\n\n if (typeof value !== 'string' || !isConfigNode(config[value])) {\n throw new InvalidResourceError({\n resource: value,\n validResources: Object.keys(config),\n });\n }\n\n resource = value;\n cursor = config[value];\n break;\n }\n case 'subResource': {\n const value = readVariable(variables, 'subResource', path);\n\n if (!isSubResourceParamValue(value)) {\n throw new InvalidSubResourceError({\n subResource: value,\n resource,\n reason:\n 'A sub-resource must be a slug or an object with `value` and `subResource`',\n });\n }\n\n cursor = resolveSubResourceParam(cursor, value, resource);\n break;\n }\n case 'component': {\n const value = readVariable(variables, 'component', path);\n\n if (!isConfigNode(cursor)) {\n throw new InvalidComponentError({\n component: value,\n path,\n resource,\n reason: `\"${String(value)}\" cannot be read because the value before it is not a config branch`,\n });\n }\n\n if (typeof value !== 'string' || cursor[value] === undefined) {\n throw new InvalidComponentError({\n component: value,\n path,\n resource,\n validComponents: readComponentKeys(cursor),\n });\n }\n\n cursor = cursor[value];\n break;\n }\n default: {\n throw new InvalidPathError({\n path,\n reason: `\"${segment}\" is not a supported path variable`,\n });\n }\n }\n }\n\n return cursor;\n}\n"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { Show } from "../../utils.cjs";
2
+ import { LayoutResourceKey, ResourceDefinition, ResourceDefinitionForKey, SubResourceDefinitionsFor, SubResourceParamForResource } from "../../resource.cjs";
3
+ import { BaseResourceConfigComponents, ResourceConfigComponentKey, SharedResourceConfigOptions } from "../types.cjs";
4
+ import { ComponentPathVariable, ExtractPathVariables, PathHead, PathTail, ResourcePathVariable, SubResourcePathVariable } from "./variables.cjs";
5
+ import { JSX } from "react";
6
+
7
+ //#region src/create-config/paths/types.d.ts
8
+ /** Recursion cap for path types. Must stay aligned with `MAX_PATH_DEPTH` in `./generate`. */
9
+ type MaxPathDepth = 6;
10
+ type ComponentSlotKey = keyof BaseResourceConfigComponents;
11
+ type SharedBranchKey = keyof SharedResourceConfigOptions;
12
+ /** A component slot segment: a fixed slot key, or the `$component` variable. */
13
+ type ComponentSegment = ComponentSlotKey | ComponentPathVariable;
14
+ /**
15
+ * Path tail selecting a component on the current node: a slot, a shared branch, or a
16
+ * slot inside a shared branch (`detail.errorComponent`, `new.$component`, …).
17
+ */
18
+ type ComponentTailPath = ComponentSegment | SharedBranchKey | `${SharedBranchKey}.${ComponentSegment}`;
19
+ type NestedSubResourceDefinitions<Def extends ResourceDefinition> = Def extends {
20
+ subResources: infer Nested extends ReadonlyArray<ResourceDefinition>;
21
+ } ? Nested : readonly [];
22
+ type SubResourceTailPaths<SubDefs extends ReadonlyArray<ResourceDefinition>, DepthAcc extends readonly unknown[]> = LayoutResourceKey<SubDefs> extends infer Key extends string ? Key extends LayoutResourceKey<SubDefs> ? Key | `${Key}.${ParameterizedEntryPath<NestedSubResourceDefinitions<ResourceDefinitionForKey<SubDefs, Key>>, readonly [...DepthAcc, unknown]>}` : never : never;
23
+ /**
24
+ * Every path tail valid below one config node: component slots, declared sub-resource
25
+ * slugs, or a single `$subResource` variable. One `$subResource` segment stands for the
26
+ * whole remaining sub-resource chain, since its value may be `{ value, subResource }`.
27
+ */
28
+ type ParameterizedEntryPath<SubDefs extends ReadonlyArray<ResourceDefinition>, DepthAcc extends readonly unknown[] = readonly []> = ComponentTailPath | ([SubDefs] extends [readonly []] ? never : DepthAcc['length'] extends MaxPathDepth ? never : SubResourceTailPaths<SubDefs, DepthAcc> | SubResourcePathVariable | `${SubResourcePathVariable}.${ComponentTailPath}`);
29
+ type ParameterizedEntryPathForResource<Resources extends ReadonlyArray<ResourceDefinition>, Resource extends LayoutResourceKey<Resources>> = ParameterizedEntryPath<SubResourceDefinitionsFor<Resources, Resource>>;
30
+ type AnyParameterizedEntryPath<Resources extends ReadonlyArray<ResourceDefinition>> = LayoutResourceKey<Resources> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? ParameterizedEntryPathForResource<Resources, Resource> : never : never;
31
+ /**
32
+ * Paths accepted by `forPaths` and `createGetComponent`. Segments whose value depends on
33
+ * the config collapse into variables (`$resource`, `$subResource`, `$component`), and the
34
+ * fixed slots stay literal, so `'$resource.detail.$component'` leaves `resource` and
35
+ * `component` to the call site.
36
+ */
37
+ type ParameterizedResourcePath<Resources extends ReadonlyArray<ResourceDefinition>> = LayoutResourceKey<Resources> | ResourcePathVariable | (LayoutResourceKey<Resources> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? `${Resource}.${ParameterizedEntryPathForResource<Resources, Resource>}` : never : never) | `${ResourcePathVariable}.${AnyParameterizedEntryPath<Resources>}`;
38
+ type ConfigNodeOf<Node> = NonNullable<Node>;
39
+ /**
40
+ * Element slots configured on a node (`component`, `errorComponent`, …). `detail` and
41
+ * `new` are path segments, not `$component` values.
42
+ */
43
+ type ComponentKeysAtNode<Node> = ConfigNodeOf<Node> extends JSX.Element ? never : Extract<keyof ConfigNodeOf<Node>, ComponentSlotKey>;
44
+ /** Sub-resource keys configured on a node: every key that is not a component slot. */
45
+ type SubResourceKeysAtNode<Node> = ConfigNodeOf<Node> extends JSX.Element ? never : Exclude<keyof ConfigNodeOf<Node>, ResourceConfigComponentKey>;
46
+ type IndexNode<Node, Key> = Key extends keyof ConfigNodeOf<Node> ? NonNullable<ConfigNodeOf<Node>[Key]> : never;
47
+ type ComponentKeysAtNodes<Node> = Node extends unknown ? ComponentKeysAtNode<Node> : never;
48
+ /** Sub-resource keys on a node and on every node below it, matching nested params. */
49
+ type SubResourceKeysBelowNode<Node, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : SubResourceKeysAtNode<Node> extends infer Key ? Key extends SubResourceKeysAtNode<Node> ? Key | SubResourceKeysBelowNode<IndexNode<Node, Key>, readonly [...DepthAcc, unknown]> : never : never;
50
+ /** Every node reachable below `Node`, used when a `$subResource` value is not yet known. */
51
+ type AnySubResourceNode<Node, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : SubResourceKeysAtNode<Node> extends infer Key ? Key extends SubResourceKeysAtNode<Node> ? IndexNode<Node, Key> | AnySubResourceNode<IndexNode<Node, Key>, readonly [...DepthAcc, unknown]> : never : never;
52
+ type ResolveConfigNodeSegment<Node, Segment extends string> = Node extends unknown ? Segment extends SubResourcePathVariable ? AnySubResourceNode<Node> : Segment extends ComponentPathVariable ? IndexNode<Node, ComponentKeysAtNode<Node>> : IndexNode<Node, Segment> : never;
53
+ /**
54
+ * Walks `Path` on a config node. Open variables resolve to every value they could take,
55
+ * so `never` means the path cannot exist on that node.
56
+ */
57
+ type ResolveConfigNode<Node, Path extends string> = [Node] extends [never] ? never : Path extends '' ? Node : Path extends `${infer Head}.${infer Rest}` ? ResolveConfigNode<ResolveConfigNodeSegment<Node, Head>, Rest> : ResolveConfigNodeSegment<Node, Path>;
58
+ /** Resource keys present in a created config, falling back to every declared resource. */
59
+ type ConfigResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config> = [Extract<LayoutResourceKey<Resources>, keyof Config>] extends [never] ? LayoutResourceKey<Resources> : Extract<LayoutResourceKey<Resources>, keyof Config>;
60
+ type ResourceNode<Config, Resource> = Resource extends keyof Config ? NonNullable<Config[Resource]> : never;
61
+ /**
62
+ * Resources a path can target: for `$resource` paths, only those whose config satisfies
63
+ * the path's fixed segments, so `'$resource.detail.$component'` excludes resources
64
+ * without a `detail`.
65
+ */
66
+ type PathResourceCandidates<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathHead<Path> extends ResourcePathVariable ? ConfigResourceKeys<Resources, Config> extends infer Resource ? Resource extends ConfigResourceKeys<Resources, Config> ? [ResolveConfigNode<ResourceNode<Config, Resource>, PathTail<Path>>] extends [never] ? never : Resource : never : never : Extract<PathHead<Path>, ConfigResourceKeys<Resources, Config>>;
67
+ type StripTrailingComponentVariable<Path extends string> = Path extends ComponentPathVariable ? '' : Path extends `${infer Head}.${ComponentPathVariable}` ? Head : Path;
68
+ /** Component slot keys configured on the node a path resolves to. */
69
+ type PathComponentKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends PathResourceCandidates<Resources, Config, Path> ? ComponentKeysAtNodes<ResolveConfigNode<ResourceNode<Config, Resource>, StripTrailingComponentVariable<PathTail<Path>>>> : never : never;
70
+ /** Sub-resource keys valid for the `$subResource` segment of a path. */
71
+ type PathSubResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends PathResourceCandidates<Resources, Config, Path> ? SubResourceKeysBelowNode<ResourceNode<Config, Resource>> : never : never;
72
+ /** Sub-resource keys configured for one resource, at any depth. */
73
+ type ResourceSubResourceKeys<Config, Resource> = SubResourceKeysBelowNode<ResourceNode<Config, Resource>>;
74
+ /** Every sub-resource key configured anywhere in a config map. */
75
+ type ConfigSubResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config> = ConfigResourceKeys<Resources, Config> extends infer Resource ? Resource extends ConfigResourceKeys<Resources, Config> ? ResourceSubResourceKeys<Config, Resource> : never : never;
76
+ type ComponentKeysForPath<Config, Resource, Tail extends string> = ComponentKeysAtNodes<ResolveConfigNode<ResourceNode<Config, Resource>, StripTrailingComponentVariable<Tail>>> extends infer Keys ? [Keys] extends [never] ? ComponentSlotKey : Keys : ComponentSlotKey;
77
+ /** Params a path requires for one target resource. */
78
+ type PathVariablesForResource<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string, Resource extends LayoutResourceKey<Resources>> = Show<('resource' extends ExtractPathVariables<Path> ? {
79
+ resource: Resource;
80
+ } : {}) & ('subResource' extends ExtractPathVariables<Path> ? {
81
+ subResource: SubResourceParamForResource<Resources, Resource>;
82
+ } : {}) & ('component' extends ExtractPathVariables<Path> ? {
83
+ component: ComponentKeysForPath<Config, Resource, PathTail<Path>>;
84
+ } : {})>;
85
+ /**
86
+ * Params a path requires, as one object per resource the path can target. A path with no
87
+ * variables resolves to `{}`.
88
+ */
89
+ type PathVariables<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? PathVariablesForResource<Resources, Config, Path, Resource> : never : never;
90
+ type VariableValue<Variables, Name extends string> = Name extends keyof Variables ? Variables[Name] : never;
91
+ type ResolveSubResourceParamNode<Node, Param, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : Param extends string ? IndexNode<Node, Param> : Param extends {
92
+ value: infer Value extends string;
93
+ subResource: infer Nested;
94
+ } ? ResolveSubResourceParamNode<IndexNode<Node, Value>, Nested, readonly [...DepthAcc, unknown]> : never;
95
+ type ResolveNodeSegmentWithVariables<Node, Segment extends string, Variables> = Node extends unknown ? Segment extends SubResourcePathVariable ? ResolveSubResourceParamNode<Node, VariableValue<Variables, 'subResource'>> : Segment extends ComponentPathVariable ? IndexNode<Node, Extract<VariableValue<Variables, 'component'>, string>> : IndexNode<Node, Segment> : never;
96
+ type ResolveNodeWithVariables<Node, Path extends string, Variables> = [Node] extends [never] ? never : Path extends '' ? Node : Path extends `${infer Head}.${infer Rest}` ? ResolveNodeWithVariables<ResolveNodeSegmentWithVariables<Node, Head, Variables>, Rest, Variables> : ResolveNodeSegmentWithVariables<Node, Path, Variables>;
97
+ /**
98
+ * Config value a path resolves to once its variables are supplied. Object nodes come back
99
+ * with a `getComponent` helper attached at runtime; component slots resolve to the element.
100
+ */
101
+ type ResolveParameterizedPathValue<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string, Variables> = Variables extends unknown ? ResolveNodeWithVariables<PathHead<Path> extends ResourcePathVariable ? ResourceNode<Config, Extract<VariableValue<Variables, 'resource'>, LayoutResourceKey<Resources>>> : ResourceNode<Config, PathHead<Path>>, PathTail<Path>, Variables> : never;
102
+ //#endregion
103
+ export { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveConfigNode, ResolveParameterizedPathValue, ResourceSubResourceKeys };
104
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","names":[],"sources":["../../../src/create-config/paths/types.ts"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import { Show } from "../../utils.mjs";
2
+ import { LayoutResourceKey, ResourceDefinition, ResourceDefinitionForKey, SubResourceDefinitionsFor, SubResourceParamForResource } from "../../resource.mjs";
3
+ import { BaseResourceConfigComponents, ResourceConfigComponentKey, SharedResourceConfigOptions } from "../types.mjs";
4
+ import { ComponentPathVariable, ExtractPathVariables, PathHead, PathTail, ResourcePathVariable, SubResourcePathVariable } from "./variables.mjs";
5
+ import { JSX } from "react";
6
+
7
+ //#region src/create-config/paths/types.d.ts
8
+ /** Recursion cap for path types. Must stay aligned with `MAX_PATH_DEPTH` in `./generate`. */
9
+ type MaxPathDepth = 6;
10
+ type ComponentSlotKey = keyof BaseResourceConfigComponents;
11
+ type SharedBranchKey = keyof SharedResourceConfigOptions;
12
+ /** A component slot segment: a fixed slot key, or the `$component` variable. */
13
+ type ComponentSegment = ComponentSlotKey | ComponentPathVariable;
14
+ /**
15
+ * Path tail selecting a component on the current node: a slot, a shared branch, or a
16
+ * slot inside a shared branch (`detail.errorComponent`, `new.$component`, …).
17
+ */
18
+ type ComponentTailPath = ComponentSegment | SharedBranchKey | `${SharedBranchKey}.${ComponentSegment}`;
19
+ type NestedSubResourceDefinitions<Def extends ResourceDefinition> = Def extends {
20
+ subResources: infer Nested extends ReadonlyArray<ResourceDefinition>;
21
+ } ? Nested : readonly [];
22
+ type SubResourceTailPaths<SubDefs extends ReadonlyArray<ResourceDefinition>, DepthAcc extends readonly unknown[]> = LayoutResourceKey<SubDefs> extends infer Key extends string ? Key extends LayoutResourceKey<SubDefs> ? Key | `${Key}.${ParameterizedEntryPath<NestedSubResourceDefinitions<ResourceDefinitionForKey<SubDefs, Key>>, readonly [...DepthAcc, unknown]>}` : never : never;
23
+ /**
24
+ * Every path tail valid below one config node: component slots, declared sub-resource
25
+ * slugs, or a single `$subResource` variable. One `$subResource` segment stands for the
26
+ * whole remaining sub-resource chain, since its value may be `{ value, subResource }`.
27
+ */
28
+ type ParameterizedEntryPath<SubDefs extends ReadonlyArray<ResourceDefinition>, DepthAcc extends readonly unknown[] = readonly []> = ComponentTailPath | ([SubDefs] extends [readonly []] ? never : DepthAcc['length'] extends MaxPathDepth ? never : SubResourceTailPaths<SubDefs, DepthAcc> | SubResourcePathVariable | `${SubResourcePathVariable}.${ComponentTailPath}`);
29
+ type ParameterizedEntryPathForResource<Resources extends ReadonlyArray<ResourceDefinition>, Resource extends LayoutResourceKey<Resources>> = ParameterizedEntryPath<SubResourceDefinitionsFor<Resources, Resource>>;
30
+ type AnyParameterizedEntryPath<Resources extends ReadonlyArray<ResourceDefinition>> = LayoutResourceKey<Resources> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? ParameterizedEntryPathForResource<Resources, Resource> : never : never;
31
+ /**
32
+ * Paths accepted by `forPaths` and `createGetComponent`. Segments whose value depends on
33
+ * the config collapse into variables (`$resource`, `$subResource`, `$component`), and the
34
+ * fixed slots stay literal, so `'$resource.detail.$component'` leaves `resource` and
35
+ * `component` to the call site.
36
+ */
37
+ type ParameterizedResourcePath<Resources extends ReadonlyArray<ResourceDefinition>> = LayoutResourceKey<Resources> | ResourcePathVariable | (LayoutResourceKey<Resources> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? `${Resource}.${ParameterizedEntryPathForResource<Resources, Resource>}` : never : never) | `${ResourcePathVariable}.${AnyParameterizedEntryPath<Resources>}`;
38
+ type ConfigNodeOf<Node> = NonNullable<Node>;
39
+ /**
40
+ * Element slots configured on a node (`component`, `errorComponent`, …). `detail` and
41
+ * `new` are path segments, not `$component` values.
42
+ */
43
+ type ComponentKeysAtNode<Node> = ConfigNodeOf<Node> extends JSX.Element ? never : Extract<keyof ConfigNodeOf<Node>, ComponentSlotKey>;
44
+ /** Sub-resource keys configured on a node: every key that is not a component slot. */
45
+ type SubResourceKeysAtNode<Node> = ConfigNodeOf<Node> extends JSX.Element ? never : Exclude<keyof ConfigNodeOf<Node>, ResourceConfigComponentKey>;
46
+ type IndexNode<Node, Key> = Key extends keyof ConfigNodeOf<Node> ? NonNullable<ConfigNodeOf<Node>[Key]> : never;
47
+ type ComponentKeysAtNodes<Node> = Node extends unknown ? ComponentKeysAtNode<Node> : never;
48
+ /** Sub-resource keys on a node and on every node below it, matching nested params. */
49
+ type SubResourceKeysBelowNode<Node, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : SubResourceKeysAtNode<Node> extends infer Key ? Key extends SubResourceKeysAtNode<Node> ? Key | SubResourceKeysBelowNode<IndexNode<Node, Key>, readonly [...DepthAcc, unknown]> : never : never;
50
+ /** Every node reachable below `Node`, used when a `$subResource` value is not yet known. */
51
+ type AnySubResourceNode<Node, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : SubResourceKeysAtNode<Node> extends infer Key ? Key extends SubResourceKeysAtNode<Node> ? IndexNode<Node, Key> | AnySubResourceNode<IndexNode<Node, Key>, readonly [...DepthAcc, unknown]> : never : never;
52
+ type ResolveConfigNodeSegment<Node, Segment extends string> = Node extends unknown ? Segment extends SubResourcePathVariable ? AnySubResourceNode<Node> : Segment extends ComponentPathVariable ? IndexNode<Node, ComponentKeysAtNode<Node>> : IndexNode<Node, Segment> : never;
53
+ /**
54
+ * Walks `Path` on a config node. Open variables resolve to every value they could take,
55
+ * so `never` means the path cannot exist on that node.
56
+ */
57
+ type ResolveConfigNode<Node, Path extends string> = [Node] extends [never] ? never : Path extends '' ? Node : Path extends `${infer Head}.${infer Rest}` ? ResolveConfigNode<ResolveConfigNodeSegment<Node, Head>, Rest> : ResolveConfigNodeSegment<Node, Path>;
58
+ /** Resource keys present in a created config, falling back to every declared resource. */
59
+ type ConfigResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config> = [Extract<LayoutResourceKey<Resources>, keyof Config>] extends [never] ? LayoutResourceKey<Resources> : Extract<LayoutResourceKey<Resources>, keyof Config>;
60
+ type ResourceNode<Config, Resource> = Resource extends keyof Config ? NonNullable<Config[Resource]> : never;
61
+ /**
62
+ * Resources a path can target: for `$resource` paths, only those whose config satisfies
63
+ * the path's fixed segments, so `'$resource.detail.$component'` excludes resources
64
+ * without a `detail`.
65
+ */
66
+ type PathResourceCandidates<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathHead<Path> extends ResourcePathVariable ? ConfigResourceKeys<Resources, Config> extends infer Resource ? Resource extends ConfigResourceKeys<Resources, Config> ? [ResolveConfigNode<ResourceNode<Config, Resource>, PathTail<Path>>] extends [never] ? never : Resource : never : never : Extract<PathHead<Path>, ConfigResourceKeys<Resources, Config>>;
67
+ type StripTrailingComponentVariable<Path extends string> = Path extends ComponentPathVariable ? '' : Path extends `${infer Head}.${ComponentPathVariable}` ? Head : Path;
68
+ /** Component slot keys configured on the node a path resolves to. */
69
+ type PathComponentKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends PathResourceCandidates<Resources, Config, Path> ? ComponentKeysAtNodes<ResolveConfigNode<ResourceNode<Config, Resource>, StripTrailingComponentVariable<PathTail<Path>>>> : never : never;
70
+ /** Sub-resource keys valid for the `$subResource` segment of a path. */
71
+ type PathSubResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends PathResourceCandidates<Resources, Config, Path> ? SubResourceKeysBelowNode<ResourceNode<Config, Resource>> : never : never;
72
+ /** Sub-resource keys configured for one resource, at any depth. */
73
+ type ResourceSubResourceKeys<Config, Resource> = SubResourceKeysBelowNode<ResourceNode<Config, Resource>>;
74
+ /** Every sub-resource key configured anywhere in a config map. */
75
+ type ConfigSubResourceKeys<Resources extends ReadonlyArray<ResourceDefinition>, Config> = ConfigResourceKeys<Resources, Config> extends infer Resource ? Resource extends ConfigResourceKeys<Resources, Config> ? ResourceSubResourceKeys<Config, Resource> : never : never;
76
+ type ComponentKeysForPath<Config, Resource, Tail extends string> = ComponentKeysAtNodes<ResolveConfigNode<ResourceNode<Config, Resource>, StripTrailingComponentVariable<Tail>>> extends infer Keys ? [Keys] extends [never] ? ComponentSlotKey : Keys : ComponentSlotKey;
77
+ /** Params a path requires for one target resource. */
78
+ type PathVariablesForResource<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string, Resource extends LayoutResourceKey<Resources>> = Show<('resource' extends ExtractPathVariables<Path> ? {
79
+ resource: Resource;
80
+ } : {}) & ('subResource' extends ExtractPathVariables<Path> ? {
81
+ subResource: SubResourceParamForResource<Resources, Resource>;
82
+ } : {}) & ('component' extends ExtractPathVariables<Path> ? {
83
+ component: ComponentKeysForPath<Config, Resource, PathTail<Path>>;
84
+ } : {})>;
85
+ /**
86
+ * Params a path requires, as one object per resource the path can target. A path with no
87
+ * variables resolves to `{}`.
88
+ */
89
+ type PathVariables<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string> = PathResourceCandidates<Resources, Config, Path> extends infer Resource ? Resource extends LayoutResourceKey<Resources> ? PathVariablesForResource<Resources, Config, Path, Resource> : never : never;
90
+ type VariableValue<Variables, Name extends string> = Name extends keyof Variables ? Variables[Name] : never;
91
+ type ResolveSubResourceParamNode<Node, Param, DepthAcc extends readonly unknown[] = readonly []> = DepthAcc['length'] extends MaxPathDepth ? never : Param extends string ? IndexNode<Node, Param> : Param extends {
92
+ value: infer Value extends string;
93
+ subResource: infer Nested;
94
+ } ? ResolveSubResourceParamNode<IndexNode<Node, Value>, Nested, readonly [...DepthAcc, unknown]> : never;
95
+ type ResolveNodeSegmentWithVariables<Node, Segment extends string, Variables> = Node extends unknown ? Segment extends SubResourcePathVariable ? ResolveSubResourceParamNode<Node, VariableValue<Variables, 'subResource'>> : Segment extends ComponentPathVariable ? IndexNode<Node, Extract<VariableValue<Variables, 'component'>, string>> : IndexNode<Node, Segment> : never;
96
+ type ResolveNodeWithVariables<Node, Path extends string, Variables> = [Node] extends [never] ? never : Path extends '' ? Node : Path extends `${infer Head}.${infer Rest}` ? ResolveNodeWithVariables<ResolveNodeSegmentWithVariables<Node, Head, Variables>, Rest, Variables> : ResolveNodeSegmentWithVariables<Node, Path, Variables>;
97
+ /**
98
+ * Config value a path resolves to once its variables are supplied. Object nodes come back
99
+ * with a `getComponent` helper attached at runtime; component slots resolve to the element.
100
+ */
101
+ type ResolveParameterizedPathValue<Resources extends ReadonlyArray<ResourceDefinition>, Config, Path extends string, Variables> = Variables extends unknown ? ResolveNodeWithVariables<PathHead<Path> extends ResourcePathVariable ? ResourceNode<Config, Extract<VariableValue<Variables, 'resource'>, LayoutResourceKey<Resources>>> : ResourceNode<Config, PathHead<Path>>, PathTail<Path>, Variables> : never;
102
+ //#endregion
103
+ export { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveConfigNode, ResolveParameterizedPathValue, ResourceSubResourceKeys };
104
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../../src/create-config/paths/types.ts"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+
2
+ //#region src/create-config/paths/variables.ts
3
+ /**
4
+ * Prefix marking a path segment as a caller-supplied variable. `'$resource.detail.$component'`
5
+ * leaves `resource` and `component` open, while `detail` is fixed.
6
+ */
7
+ const PATH_VARIABLE_IDENTIFIER = "$";
8
+ function createPathVariable(name) {
9
+ return `${"$"}${name}`;
10
+ }
11
+ function isPathVariableSegment(segment) {
12
+ return segment.startsWith("$");
13
+ }
14
+ /** Variable name for a segment, or `undefined` when the segment is a fixed key. */
15
+ function readPathVariableName(segment) {
16
+ return isPathVariableSegment(segment) ? segment.slice(1) : void 0;
17
+ }
18
+ /** Variable names declared by `path`, in order of appearance and without duplicates. */
19
+ function extractPathVariables(path) {
20
+ const names = /* @__PURE__ */ new Set();
21
+ for (const segment of path.split(".")) {
22
+ const name = readPathVariableName(segment);
23
+ if (name !== void 0 && name.length > 0) names.add(name);
24
+ }
25
+ return [...names];
26
+ }
27
+
28
+ //#endregion
29
+ exports.createPathVariable = createPathVariable;
30
+ exports.extractPathVariables = extractPathVariables;
31
+ exports.readPathVariableName = readPathVariableName;
32
+ //# sourceMappingURL=variables.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.cjs","names":[],"sources":["../../../src/create-config/paths/variables.ts"],"sourcesContent":["/**\n * Prefix marking a path segment as a caller-supplied variable. `'$resource.detail.$component'`\n * leaves `resource` and `component` open, while `detail` is fixed.\n */\nexport const PATH_VARIABLE_IDENTIFIER = '$';\n\nexport type PathVariableIdentifier = typeof PATH_VARIABLE_IDENTIFIER;\n\n/** A single variable path segment, e.g. `PathVariable<'resource'>` is `'$resource'`. */\nexport type PathVariable<Name extends string> =\n `${PathVariableIdentifier}${Name}`;\n\nexport type ResourcePathVariable = PathVariable<'resource'>;\nexport type SubResourcePathVariable = PathVariable<'subResource'>;\nexport type ComponentPathVariable = PathVariable<'component'>;\n\n/** Variable names a path may leave open. */\nexport type PathVariableName = 'resource' | 'subResource' | 'component';\n\nexport type RemovePathVariableIdentifier<Segment extends string> =\n Segment extends PathVariable<infer Name> ? Name : Segment;\n\ntype ExtractSegmentVariable<Segment extends string> =\n Segment extends PathVariable<infer Name> ? Name : never;\n\n/**\n * Variable names declared by a dot-separated path.\n *\n * @example\n * ```ts\n * ExtractPathVariables<'$resource.detail.$component'>\n * // ^? 'resource' | 'component'\n * ```\n */\nexport type ExtractPathVariables<Path extends string> =\n Path extends `${infer Segment}.${infer Rest}`\n ? ExtractSegmentVariable<Segment> | ExtractPathVariables<Rest>\n : ExtractSegmentVariable<Path>;\n\n/** Whether `Path` leaves any variable open. */\nexport type PathHasVariables<Path extends string> = [\n ExtractPathVariables<Path>,\n] extends [never]\n ? false\n : true;\n\n/** First segment of a dot-separated path. */\nexport type PathHead<Path extends string> =\n Path extends `${infer Head}.${string}` ? Head : Path;\n\n/** Everything after the first segment of a dot-separated path (`''` when there is nothing left). */\nexport type PathTail<Path extends string> =\n Path extends `${string}.${infer Rest}` ? Rest : '';\n\nexport function createPathVariable<Name extends string>(\n name: Name,\n): PathVariable<Name> {\n return `${PATH_VARIABLE_IDENTIFIER}${name}`;\n}\n\nexport function isPathVariableSegment(segment: string): boolean {\n return segment.startsWith(PATH_VARIABLE_IDENTIFIER);\n}\n\n/** Variable name for a segment, or `undefined` when the segment is a fixed key. */\nexport function readPathVariableName(segment: string): string | undefined {\n return isPathVariableSegment(segment)\n ? segment.slice(PATH_VARIABLE_IDENTIFIER.length)\n : undefined;\n}\n\n/** Variable names declared by `path`, in order of appearance and without duplicates. */\nexport function extractPathVariables(path: string): string[] {\n const names = new Set<string>();\n\n for (const segment of path.split('.')) {\n const name = readPathVariableName(segment);\n\n if (name !== undefined && name.length > 0) {\n names.add(name);\n }\n }\n\n return [...names];\n}\n\nexport function pathHasVariables(path: string): boolean {\n return extractPathVariables(path).length > 0;\n}\n"],"mappings":";;;;;;AAIA,MAAa,2BAA2B;AAkDxC,SAAgB,mBACd,MACoB;CACpB,OAAO,SAA8B;AACvC;AAEA,SAAgB,sBAAsB,SAA0B;CAC9D,OAAO,QAAQ,cAAmC;AACpD;;AAGA,SAAgB,qBAAqB,SAAqC;CACxE,OAAO,sBAAsB,OAAO,IAChC,QAAQ,MAAM,CAA+B,IAC7C;AACN;;AAGA,SAAgB,qBAAqB,MAAwB;CAC3D,MAAM,wBAAQ,IAAI,IAAY;CAE9B,KAAK,MAAM,WAAW,KAAK,MAAM,GAAG,GAAG;EACrC,MAAM,OAAO,qBAAqB,OAAO;EAEzC,IAAI,SAAS,UAAa,KAAK,SAAS,GACtC,MAAM,IAAI,IAAI;CAElB;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB"}
@@ -0,0 +1,32 @@
1
+ //#region src/create-config/paths/variables.d.ts
2
+ /**
3
+ * Prefix marking a path segment as a caller-supplied variable. `'$resource.detail.$component'`
4
+ * leaves `resource` and `component` open, while `detail` is fixed.
5
+ */
6
+ declare const PATH_VARIABLE_IDENTIFIER = "$";
7
+ type PathVariableIdentifier = typeof PATH_VARIABLE_IDENTIFIER;
8
+ /** A single variable path segment, e.g. `PathVariable<'resource'>` is `'$resource'`. */
9
+ type PathVariable<Name extends string> = `${PathVariableIdentifier}${Name}`;
10
+ type ResourcePathVariable = PathVariable<'resource'>;
11
+ type SubResourcePathVariable = PathVariable<'subResource'>;
12
+ type ComponentPathVariable = PathVariable<'component'>;
13
+ type ExtractSegmentVariable<Segment extends string> = Segment extends PathVariable<infer Name> ? Name : never;
14
+ /**
15
+ * Variable names declared by a dot-separated path.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * ExtractPathVariables<'$resource.detail.$component'>
20
+ * // ^? 'resource' | 'component'
21
+ * ```
22
+ */
23
+ type ExtractPathVariables<Path extends string> = Path extends `${infer Segment}.${infer Rest}` ? ExtractSegmentVariable<Segment> | ExtractPathVariables<Rest> : ExtractSegmentVariable<Path>;
24
+ /** Whether `Path` leaves any variable open. */
25
+ type PathHasVariables<Path extends string> = [ExtractPathVariables<Path>] extends [never] ? false : true;
26
+ /** First segment of a dot-separated path. */
27
+ type PathHead<Path extends string> = Path extends `${infer Head}.${string}` ? Head : Path;
28
+ /** Everything after the first segment of a dot-separated path (`''` when there is nothing left). */
29
+ type PathTail<Path extends string> = Path extends `${string}.${infer Rest}` ? Rest : '';
30
+ //#endregion
31
+ export { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathHead, PathTail, PathVariable, PathVariableIdentifier, ResourcePathVariable, SubResourcePathVariable };
32
+ //# sourceMappingURL=variables.d.cts.map