@yahoo/uds-create-config 5.70.0 → 5.72.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.
- package/dist/configs/system.js +2 -0
- package/dist/entities/system/Component.d.ts +10 -4
- package/dist/entities/system/Component.js +22 -12
- package/dist/entities/system/link-plan.d.ts +17 -1
- package/dist/entities/system/link-plan.js +88 -52
- package/dist/framework/Config.d.ts +1 -1
- package/dist/framework/Config.js +1 -1
- package/dist/framework/schema-version.d.ts +1 -1
- package/dist/framework/schema-version.js +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/migrations/20261102193912_map_props_from.d.ts +12 -0
- package/dist/migrations/20261102193912_map_props_from.js +10 -0
- package/dist/spec/index.d.ts +2 -2
- package/dist/spec/index.js +2 -2
- package/dist/spec/prop-mapping.d.ts +34 -2
- package/dist/spec/prop-mapping.js +47 -10
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -15,10 +15,19 @@ interface PropMappingRule {
|
|
|
15
15
|
readonly unset?: readonly string[];
|
|
16
16
|
}
|
|
17
17
|
interface PropMapping {
|
|
18
|
-
/** The component whose instances it rewrites, as a path. */
|
|
18
|
+
/** The component whose instances it rewrites, as a path. With `from`, the one they become. */
|
|
19
19
|
readonly component: string;
|
|
20
|
+
/** The component whose instances become `component`'s, as a path; it needn't exist anymore. */
|
|
21
|
+
readonly from?: string;
|
|
22
|
+
/** Limits it to some nodes of one design file, by its canvas id and their ids: Create's alone. */
|
|
23
|
+
readonly only?: MappingScope;
|
|
20
24
|
readonly rules: readonly PropMappingRule[];
|
|
21
25
|
}
|
|
26
|
+
/** Some nodes of one design file. */
|
|
27
|
+
interface MappingScope {
|
|
28
|
+
readonly canvas: string;
|
|
29
|
+
readonly nodes: readonly string[];
|
|
30
|
+
}
|
|
22
31
|
/** A rule as a tool takes it: the shape every surface that applies a mapping parses its input with. */
|
|
23
32
|
declare const propMappingRuleSchema: z.ZodObject<{
|
|
24
33
|
when: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
@@ -31,6 +40,29 @@ declare const propMappingRulesSchema: z.ZodArray<z.ZodObject<{
|
|
|
31
40
|
set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
32
41
|
unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
33
42
|
}, z.core.$strip>>;
|
|
43
|
+
/** A swap's rules: none is a swap that keeps every prop, and `when: {}` reaches every swapped instance. */
|
|
44
|
+
declare const swapMappingRulesSchema: z.ZodArray<z.ZodObject<{
|
|
45
|
+
when: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
46
|
+
set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
47
|
+
unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
48
|
+
}, z.core.$strip>>;
|
|
49
|
+
/**
|
|
50
|
+
* A mapping's rules as `map-props` takes them: at least one for a mapping, any number for a swap
|
|
51
|
+
* (`from`), where none keeps the swapped instances' props and `when: {}` reaches every one of them.
|
|
52
|
+
* Required by the op's own check rather than the schema, so one shape serves both.
|
|
53
|
+
*/
|
|
54
|
+
declare const mapPropsRulesSchema: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
55
|
+
when: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
|
|
56
|
+
set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
57
|
+
unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
58
|
+
}, z.core.$strip>>>;
|
|
59
|
+
/** `only` as a tool takes it. */
|
|
60
|
+
declare const mappingScopeSchema: z.ZodObject<{
|
|
61
|
+
canvas: z.ZodString;
|
|
62
|
+
nodes: z.ZodArray<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
/** `from` as a tool takes it. */
|
|
65
|
+
declare const mappingFromSchema: z.ZodString;
|
|
34
66
|
/**
|
|
35
67
|
* The mappings a batch of edits carries, in order: each `component/map-props` op as the mapping it
|
|
36
68
|
* applies. The op changes nothing in the config, so the host that ran the batch applies these to the
|
|
@@ -94,4 +126,4 @@ type MappedProps = {
|
|
|
94
126
|
*/
|
|
95
127
|
declare function mapComponentProps(config: Config, mapping: PropMapping, instances: readonly Record<string, unknown>[]): MappedProps;
|
|
96
128
|
//#endregion
|
|
97
|
-
export { MappedInstance, MappedProps, MatchedValue, PropMapping, PropMappingConflict, PropMappingResult, PropMappingRule, applyPropMapping, mapComponentProps, onlyMapsProps, propMappingErrors, propMappingRuleSchema, propMappingRulesSchema, propMappingsIn };
|
|
129
|
+
export { MappedInstance, MappedProps, MappingScope, MatchedValue, PropMapping, PropMappingConflict, PropMappingResult, PropMappingRule, applyPropMapping, mapComponentProps, mapPropsRulesSchema, mappingFromSchema, mappingScopeSchema, onlyMapsProps, propMappingErrors, propMappingRuleSchema, propMappingRulesSchema, propMappingsIn, swapMappingRulesSchema };
|
|
@@ -22,6 +22,11 @@ import { z } from "zod";
|
|
|
22
22
|
* Positions follow the rename rewriter's: an element's own props, every modifier block nested in
|
|
23
23
|
* them (`_hover: { variant: … }` is the same element's props under a condition), and each
|
|
24
24
|
* `layerProps` bag whose layer renders the component.
|
|
25
|
+
*
|
|
26
|
+
* A mapping with `from` also swaps the component: instances of `from`, a component the system
|
|
27
|
+
* may no longer have (the Bridge's `SelectContent`, after a take made in code replaced it), become
|
|
28
|
+
* instances of `component`, and the rules move their props onto it. Which component replaces which
|
|
29
|
+
* is as much a decision as a prop's new spelling, so it comes from the person too.
|
|
25
30
|
*/
|
|
26
31
|
/** A rule as a tool takes it: the shape every surface that applies a mapping parses its input with. */
|
|
27
32
|
const propMappingRuleSchema = z.object({
|
|
@@ -35,6 +40,21 @@ const propMappingRuleSchema = z.object({
|
|
|
35
40
|
});
|
|
36
41
|
/** The rules of a mapping, as a tool takes them. */
|
|
37
42
|
const propMappingRulesSchema = z.array(propMappingRuleSchema).min(1).describe("Every rule whose `when` matches an instance as stored applies to it, so separate props are mapped by separate rules, and a combination by one rule naming both.");
|
|
43
|
+
/** A swap's rules: none is a swap that keeps every prop, and `when: {}` reaches every swapped instance. */
|
|
44
|
+
const swapMappingRulesSchema = z.array(propMappingRuleSchema).describe("The rules for the swapped instances, as a mapping has them. `when: {}` applies to every one of them (to `unset` a prop the new component lacks), and none keeps their props as they are.");
|
|
45
|
+
/**
|
|
46
|
+
* A mapping's rules as `map-props` takes them: at least one for a mapping, any number for a swap
|
|
47
|
+
* (`from`), where none keeps the swapped instances' props and `when: {}` reaches every one of them.
|
|
48
|
+
* Required by the op's own check rather than the schema, so one shape serves both.
|
|
49
|
+
*/
|
|
50
|
+
const mapPropsRulesSchema = z.array(propMappingRuleSchema).default([]).describe("Every rule whose `when` matches an instance as stored applies to it, so separate props are mapped by separate rules, and a combination by one rule naming both. A mapping needs at least one. With `from`, none keeps the swapped instances' props, and `when: {}` reaches every swapped instance.");
|
|
51
|
+
/** `only` as a tool takes it. */
|
|
52
|
+
const mappingScopeSchema = z.object({
|
|
53
|
+
canvas: z.string().min(1).describe("The design file's canvas id."),
|
|
54
|
+
nodes: z.array(z.string().min(1)).min(1).describe("The ids of the nodes it reaches, in that design file.")
|
|
55
|
+
}).describe("Create only: limits the mapping to these nodes of one design file, for fixing one instance before asking about the rest. A checkout's call sites aren't nodes, so there it isn't taken.");
|
|
56
|
+
/** `from` as a tool takes it. */
|
|
57
|
+
const mappingFromSchema = z.string().min(1).describe("The component whose instances become this one's, as a path: the one a design file still names after the system lost it (`SelectContent`, replaced by `SelectMenu`). It needn't exist. Which component replaces which is the user's call: propose it, and apply it only once they confirm.");
|
|
38
58
|
/**
|
|
39
59
|
* The mappings a batch of edits carries, in order: each `component/map-props` op as the mapping it
|
|
40
60
|
* applies. The op changes nothing in the config, so the host that ran the batch applies these to the
|
|
@@ -45,10 +65,15 @@ function propMappingsIn(edits) {
|
|
|
45
65
|
return edits.flatMap((edit) => {
|
|
46
66
|
const { op } = editOp(edit);
|
|
47
67
|
if (op.kind !== "component" || op.operation !== "map-props") return [];
|
|
48
|
-
const
|
|
68
|
+
const data = op.data;
|
|
69
|
+
const from = typeof data?.from === "string" ? data.from : void 0;
|
|
70
|
+
const only = mappingScopeSchema.safeParse(data?.only);
|
|
71
|
+
const rules = (from ? swapMappingRulesSchema : propMappingRulesSchema).safeParse(data?.rules ?? (from ? [] : void 0));
|
|
49
72
|
if (!rules.success || typeof op.path !== "string") return [];
|
|
50
73
|
return [{
|
|
51
74
|
component: op.path.replace(/^component:/, ""),
|
|
75
|
+
...from ? { from: from.replace(/^component:/, "") } : {},
|
|
76
|
+
...only.success ? { only: only.data } : {},
|
|
52
77
|
rules: rules.data
|
|
53
78
|
}];
|
|
54
79
|
});
|
|
@@ -81,9 +106,10 @@ function valueRefusal(config, component, prop, value) {
|
|
|
81
106
|
*/
|
|
82
107
|
function propMappingErrors(config, mapping) {
|
|
83
108
|
if (!config.resolve("component", mapping.component)) return [`No component "${mapping.component}"`];
|
|
109
|
+
if (mapping.from === mapping.component) return [`"${mapping.component}" can't replace itself: \`from\` names the component its instances are now`];
|
|
84
110
|
const errors = [];
|
|
85
111
|
mapping.rules.forEach((rule, i) => {
|
|
86
|
-
if (Object.keys(rule.when).length === 0) errors.push(`Rule ${i + 1} matches every instance: name what it matches in \`when\``);
|
|
112
|
+
if (Object.keys(rule.when).length === 0 && mapping.from === void 0) errors.push(`Rule ${i + 1} matches every instance: name what it matches in \`when\``);
|
|
87
113
|
for (const [name, value] of Object.entries(rule.set ?? {})) {
|
|
88
114
|
const prop = surfaceProp(config, mapping.component, name);
|
|
89
115
|
if (!prop) {
|
|
@@ -125,6 +151,11 @@ function mapBag(bag, rules) {
|
|
|
125
151
|
bag: next
|
|
126
152
|
};
|
|
127
153
|
}
|
|
154
|
+
/** A stored type naming `to` in place of what it names, keeping the source it was placed through. */
|
|
155
|
+
function retyped(type, to) {
|
|
156
|
+
const at = type.lastIndexOf("@");
|
|
157
|
+
return `component:${to}${type.includes(":") && at > 0 ? type.slice(at) : ""}`;
|
|
158
|
+
}
|
|
128
159
|
/**
|
|
129
160
|
* A props bag on `component`, with the mapping applied to it when it's the mapped component's, and
|
|
130
161
|
* to the modifier blocks and layer overrides inside it either way. `undefined` when nothing moved.
|
|
@@ -192,8 +223,10 @@ function applyPropMapping(config, spec, mapping) {
|
|
|
192
223
|
let elements;
|
|
193
224
|
let changed = 0;
|
|
194
225
|
const conflicts = [];
|
|
226
|
+
const reached = mapping.only ? new Set(mapping.only.nodes) : void 0;
|
|
195
227
|
for (const [key, element] of Object.entries(spec.elements ?? {})) {
|
|
196
|
-
if (!element
|
|
228
|
+
if (!element) continue;
|
|
229
|
+
if (reached && !reached.has(key)) continue;
|
|
197
230
|
const walk = {
|
|
198
231
|
config,
|
|
199
232
|
mapping,
|
|
@@ -201,14 +234,18 @@ function applyPropMapping(config, spec, mapping) {
|
|
|
201
234
|
conflicts,
|
|
202
235
|
changed: 0
|
|
203
236
|
};
|
|
204
|
-
const
|
|
205
|
-
|
|
237
|
+
const component = componentOf(element.type);
|
|
238
|
+
const swapped = mapping.from !== void 0 && component === mapping.from && typeof element.type === "string";
|
|
239
|
+
if (!swapped && !element.props) continue;
|
|
240
|
+
const props = mapProps(walk, swapped ? mapping.component : component, element.props ?? {}, "props");
|
|
241
|
+
if (!props && !swapped) continue;
|
|
206
242
|
elements ??= { ...spec.elements };
|
|
207
243
|
elements[key] = {
|
|
208
244
|
...element,
|
|
209
|
-
|
|
245
|
+
...swapped ? { type: retyped(element.type, mapping.component) } : {},
|
|
246
|
+
...props ? { props } : {}
|
|
210
247
|
};
|
|
211
|
-
changed += walk.changed;
|
|
248
|
+
changed += walk.changed + (swapped && walk.changed === 0 ? 1 : 0);
|
|
212
249
|
}
|
|
213
250
|
return elements ? {
|
|
214
251
|
spec: {
|
|
@@ -236,7 +273,7 @@ function mapComponentProps(config, mapping, instances) {
|
|
|
236
273
|
errors
|
|
237
274
|
};
|
|
238
275
|
const { spec, conflicts } = applyPropMapping(config, { elements: Object.fromEntries(instances.map((props, i) => [String(i), {
|
|
239
|
-
type: `component:${mapping.component}`,
|
|
276
|
+
type: `component:${mapping.from ?? mapping.component}`,
|
|
240
277
|
props
|
|
241
278
|
}])) }, mapping);
|
|
242
279
|
return {
|
|
@@ -245,11 +282,11 @@ function mapComponentProps(config, mapping, instances) {
|
|
|
245
282
|
const after = spec.elements?.[String(i)]?.props ?? props;
|
|
246
283
|
return {
|
|
247
284
|
props: after,
|
|
248
|
-
changed: after !== props,
|
|
285
|
+
changed: after !== props || mapping.from !== void 0,
|
|
249
286
|
conflicts: conflicts.filter((conflict) => conflict.element === String(i)).flatMap((conflict) => conflict.props)
|
|
250
287
|
};
|
|
251
288
|
})
|
|
252
289
|
};
|
|
253
290
|
}
|
|
254
291
|
//#endregion
|
|
255
|
-
export { applyPropMapping, mapComponentProps, onlyMapsProps, propMappingErrors, propMappingRuleSchema, propMappingRulesSchema, propMappingsIn };
|
|
292
|
+
export { applyPropMapping, mapComponentProps, mapPropsRulesSchema, mappingFromSchema, mappingScopeSchema, onlyMapsProps, propMappingErrors, propMappingRuleSchema, propMappingRulesSchema, propMappingsIn, swapMappingRulesSchema };
|