@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.
@@ -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 rules = propMappingRulesSchema.safeParse(op.data?.rules);
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?.props) continue;
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 props = mapProps(walk, componentOf(element.type), element.props, "props");
205
- if (!props) continue;
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
- props
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 };