@yahoo/uds-create-config 5.59.0 → 5.59.2
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/react-native-system.d.ts +2 -970
- package/dist/configs/system.d.ts +2 -974
- package/dist/entities/system/Component.d.ts +1 -1
- package/dist/entities/system/LinkedSystem.js +3 -3
- package/dist/entities/system/Motion.d.ts +3 -2
- package/dist/entities/system/defineComponent.d.ts +32 -5
- package/dist/entities/system/link-plan.d.ts +12 -1
- package/dist/entities/system/link-plan.js +75 -2
- package/dist/framework/Config.js +78 -8
- package/dist/framework/defineEntity.d.ts +14 -8
- package/dist/framework/source-integrity.d.ts +13 -4
- package/dist/framework/source-integrity.js +40 -3
- package/dist/index.d.ts +5 -5
- package/dist/migrations/2.0.0/v1-artifact.d.ts +2 -973
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1004,4 +1004,4 @@ interface ComponentClass extends Omit<typeof ComponentEntity, 'ref' | 'item'> {
|
|
|
1004
1004
|
instance: typeof instanceAt;
|
|
1005
1005
|
}
|
|
1006
1006
|
//#endregion
|
|
1007
|
-
export { AuthoredPropBody, Component, ComponentBody, ComponentClass, ComponentCreateInput, ComponentElementBody, ComponentItemInput, ComponentPropBody, ComponentReference, ComponentStyleBody, ContractStyleRules, ElementVisibility, ElementVisibilityInput, ElementVisibilitySchema, ExtendedComponentRef, ProjectedVisibility, PropShapeSchema, SLOT_CODE_FORMS, VariantValueBody, VariantValues, blankComponentBody, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
1007
|
+
export { AnatomyNodeClass, AuthoredPropBody, Component, ComponentBody, ComponentClass, ComponentCreateInput, ComponentElementBody, ComponentItemInput, ComponentPropBody, ComponentReference, ComponentStyleBody, ContractStyleRules, ElementVisibility, ElementVisibilityInput, ElementVisibilitySchema, ExtendedComponentRef, ForwardClass, LayerClass, ProjectedVisibility, PropClass, PropShapeSchema, SLOT_CODE_FORMS, VariantValueBody, VariantValues, blankComponentBody, canonicalWhen, forwardedNames, layerRef, ownValues, ownsItsValues, valueRef };
|
|
@@ -303,8 +303,8 @@ const LinkedSystemDefinition = defineEntity({
|
|
|
303
303
|
* Draw entities from a linked system: the pin's `link` declaration grows to cover them and the
|
|
304
304
|
* build mints a pointer row per entity, in this one op. A row of this config's own at a covered
|
|
305
305
|
* path is deleted so theirs shows through; a row held through another pin becomes an extension
|
|
306
|
-
* through this one when `onLinked` is `'take'
|
|
307
|
-
* is written.
|
|
306
|
+
* through this one when `onLinked` is `'take'`, and the other pin's `options` entry there goes with
|
|
307
|
+
* it. `link-plan` says what that replaces before anything is written.
|
|
308
308
|
*/
|
|
309
309
|
link: {
|
|
310
310
|
input: linkInput,
|
|
@@ -332,7 +332,7 @@ const LinkedSystemDefinition = defineEntity({
|
|
|
332
332
|
input: linkInput,
|
|
333
333
|
readOnly: true,
|
|
334
334
|
label: "Plan a link",
|
|
335
|
-
description: "What `link` with the same input replaces — rows of yours deleted so the source shows through, every path another linked system provides (`linked`, turned into extensions when `onLinked` says take), members left alone because they are already here from the same origin, paths another linked system declares that the link reaches as a different entity (`settled`), whose row stays, and why the config would refuse the link (`blocked`), a collision it would leave among them. Writes nothing.",
|
|
335
|
+
description: "What `link` with the same input replaces — rows of yours deleted so the source shows through, every path another linked system provides (`linked`, turned into extensions when `onLinked` says take), the `options` entries another linked system holds at what a take moves, which it removes since they would apply to nothing (`dropped`), members left alone because they are already here from the same origin, paths another linked system declares that the link reaches as a different entity (`settled`), whose row stays, and why the config would refuse the link (`blocked`), a collision it would leave among them. Writes nothing.",
|
|
336
336
|
scope: "item",
|
|
337
337
|
title: (entity) => `Plan a link from ${entity}`,
|
|
338
338
|
example: linkExample,
|
|
@@ -33,7 +33,7 @@ declare const inlineJsMotion: z.ZodObject<{
|
|
|
33
33
|
/** The fields of a JS preset that `motion.create` reads as props, in schema order. The emitter
|
|
34
34
|
* reads this rather than restating the schema, so a field added here reaches every emitted preset. */
|
|
35
35
|
declare const jsMotionPropFields: readonly string[];
|
|
36
|
-
declare const
|
|
36
|
+
declare const MotionEntity: EntityClass<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
37
37
|
type: z.ZodLiteral<"react-native-reanimated">;
|
|
38
38
|
value: z.ZodUnion<readonly [z.ZodObject<{
|
|
39
39
|
transitionProperty: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
@@ -1003,6 +1003,7 @@ declare const Motion: EntityClass<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1003
1003
|
}, z.core.$strip>;
|
|
1004
1004
|
};
|
|
1005
1005
|
}, Record<never, never>, false, Record<never, never>, Record<never, never>>;
|
|
1006
|
-
|
|
1006
|
+
interface MotionClass extends Named<typeof MotionEntity> {}
|
|
1007
|
+
declare const Motion: MotionClass;
|
|
1007
1008
|
//#endregion
|
|
1008
1009
|
export { Motion, MotionClass, inlineJsMotion, jsMotionPropFields };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Ref as Ref$1 } from "../../framework/utils/refs.js";
|
|
2
2
|
import { RegisteredComponentHandles, RegisteredGroupPaths, RegisteredModifiers, RegisteredPaths, RegisteredStyleProps } from "../../framework/registered.js";
|
|
3
3
|
import { Authored } from "../../framework/authoring.js";
|
|
4
|
+
import { KindRef } from "../../framework/defineEntity.js";
|
|
4
5
|
import { StyleValue } from "./style-bag.js";
|
|
6
|
+
import { StylePropertyClass } from "./StyleProperty.js";
|
|
5
7
|
import { ComponentSourceInput } from "./component-source-fields.js";
|
|
6
8
|
import { PropsOrRules } from "./prop-rules.js";
|
|
7
9
|
import { VariantValues } from "./Component.js";
|
|
@@ -725,6 +727,30 @@ type RenderArgs<L extends LayerMap, P extends PropMap, S extends StateMap = Reco
|
|
|
725
727
|
} & ([keyof S] extends [never] ? Record<never, never> : {
|
|
726
728
|
readonly states: StatesHelper<S, L>;
|
|
727
729
|
}) & DeclaredProps<P, L, unknown, 'render'> & Record<string, unknown>;
|
|
730
|
+
/** A prop map's entries that are the style property of their own name: `bg: StyleProperty.ref('bg')`. */
|
|
731
|
+
type StyleRefs<K extends string> = { readonly [Q in K]: KindRef<StylePropertyClass, 'style-property', Q> };
|
|
732
|
+
/** The same entries in their declared form: `bg: { type: 'styleProperty', value: StyleProperty.ref('bg') }`. */
|
|
733
|
+
type StyleRefProps<K extends string> = { readonly [Q in K]: {
|
|
734
|
+
readonly type: 'styleProperty';
|
|
735
|
+
readonly value: KindRef<StylePropertyClass, 'style-property', Q>;
|
|
736
|
+
} };
|
|
737
|
+
/** The keys of `P` whose entry is exactly the one `M` gives that key. */
|
|
738
|
+
type MatchingKeys<P, M> = { [K in keyof P]: K extends keyof M ? [P[K]] extends [M[K]] ? [M[K]] extends [P[K]] ? K : never : never : never }[keyof P];
|
|
739
|
+
type StyleRefKeys<P> = MatchingKeys<P, StyleRefs<keyof P & string>>;
|
|
740
|
+
type StyleRefPropKeys<P> = MatchingKeys<P, StyleRefProps<keyof P & string>>;
|
|
741
|
+
/** `T`, or nothing to intersect when `K` is empty. */
|
|
742
|
+
type WhenAny<K, T> = [K] extends [never] ? unknown : T;
|
|
743
|
+
/**
|
|
744
|
+
* `P` with its entries that are the style property of their own name gathered into a
|
|
745
|
+
* {@link StyleRefs} and a {@link StyleRefProps}. It's the same type, but a declaration writes it as a
|
|
746
|
+
* list of key names rather than a `KindRef` per entry. A component's type holds the prop map of every
|
|
747
|
+
* layer it reaches, so a system's Box, with an entry for each style property, is otherwise restated in
|
|
748
|
+
* full at every layer that renders it, until the declaration is too long to write (TS7056).
|
|
749
|
+
*
|
|
750
|
+
* The rest of `P` is a mapped type with `as` rather than an `Omit`, which a declaration would write
|
|
751
|
+
* with `P` in full as its type argument.
|
|
752
|
+
*/
|
|
753
|
+
type CompactProps<P extends PropMap> = [StyleRefKeys<P> | StyleRefPropKeys<P>] extends [never] ? P : { [K in keyof P as K extends StyleRefKeys<P> | StyleRefPropKeys<P> ? never : K]: P[K] } & WhenAny<StyleRefKeys<P>, StyleRefs<StyleRefKeys<P> & string>> & WhenAny<StyleRefPropKeys<P>, StyleRefProps<StyleRefPropKeys<P> & string>>;
|
|
728
754
|
interface ComponentBuilder<L extends LayerMap, P extends PropMap,
|
|
729
755
|
/** Props the RENDER takes that the config doesn't describe — React handlers, mostly (`onPress`).
|
|
730
756
|
* They're part of the component's surface but not of its data, which is why they're declared at
|
|
@@ -767,7 +793,7 @@ F extends string = never, /** The states `.states()` declared — what the rende
|
|
|
767
793
|
* provide. The callback and its `layer`/`bind` helpers are gone — they only ever split a path string
|
|
768
794
|
* that the parameter's own type now checks.
|
|
769
795
|
*/
|
|
770
|
-
props<const P2 extends PropMap<LayerPath<L>>>(props: P2 & NoInfer<{ [K in keyof P2]: Exact<P2[K], AuthoredProp<LayerPath<L>>> }>): ComponentBuilder<L, P2
|
|
796
|
+
props<const P2 extends PropMap<LayerPath<L>>>(props: P2 & NoInfer<{ [K in keyof P2]: Exact<P2[K], AuthoredProp<LayerPath<L>>> }>): ComponentBuilder<L, CompactProps<P2>, E, D, F, S>;
|
|
771
797
|
/**
|
|
772
798
|
* What the render knows that a style rule keys on — the field has a value, the image loaded, the
|
|
773
799
|
* indicator is sliding: `{ filled: { type: 'boolean' } }`, `{ phase: { type: 'variant', value:
|
|
@@ -873,9 +899,10 @@ type AuthoredComponent = ComponentBuilder<LayerMap, PropMap, unknown, unknown>;
|
|
|
873
899
|
* forward through it (HStack's `root: Box`) then offers what the linked Box takes.
|
|
874
900
|
*
|
|
875
901
|
* Everything else (the render's extras, the defaults, the forwards, the states) is read off the
|
|
876
|
-
* handle's type rather than restated, so the two can't drift.
|
|
902
|
+
* handle's type rather than restated, so the two can't drift. The laid-over props are compacted
|
|
903
|
+
* again, since laying them over spells the source's {@link StyleRefs} out entry by entry.
|
|
877
904
|
*/
|
|
878
|
-
type LinkedHandle<Handle, Props extends PropMap = Record<never, never>, Layers extends Record<string, LayerElement> = Record<never, never>> = Handle extends ComponentBuilder<infer L extends LayerMap, infer P extends PropMap, infer E, infer D, infer F extends string, infer S extends StateMap> ? ComponentBuilder<Without<L, keyof Layers> & Layers extends infer Swapped extends LayerMap ? Swapped : L, Without<P, keyof Props> & Props
|
|
905
|
+
type LinkedHandle<Handle, Props extends PropMap = Record<never, never>, Layers extends Record<string, LayerElement> = Record<never, never>> = Handle extends ComponentBuilder<infer L extends LayerMap, infer P extends PropMap, infer E, infer D, infer F extends string, infer S extends StateMap> ? ComponentBuilder<Without<L, keyof Layers> & Layers extends infer Swapped extends LayerMap ? Swapped : L, CompactProps<Without<P, keyof Props> & Props>, E, D, F, S> : Handle;
|
|
879
906
|
interface DefineComponent {
|
|
880
907
|
/** The one-layer form: the element IS the component. */
|
|
881
908
|
<const El extends LayerElement>(element: El): ComponentBuilder<{
|
|
@@ -894,7 +921,7 @@ interface DefineComponent {
|
|
|
894
921
|
* The type argument is explicit so the builder does not INFER `P2` from an already-exact value: it
|
|
895
922
|
* would then apply the guard over its own output, which nothing satisfies.
|
|
896
923
|
*/
|
|
897
|
-
declare function definePropsFirst<const P extends PropMap<LayerPath>>(props: P & NoInfer<{ [K in keyof P]: Exact<P[K], AuthoredProp<LayerPath>> }>): ComponentBuilder<LayerMap, P
|
|
924
|
+
declare function definePropsFirst<const P extends PropMap<LayerPath>>(props: P & NoInfer<{ [K in keyof P]: Exact<P[K], AuthoredProp<LayerPath>> }>): ComponentBuilder<LayerMap, CompactProps<P>>;
|
|
898
925
|
declare const defineComponent: DefineComponent;
|
|
899
926
|
//#endregion
|
|
900
|
-
export { AsInput, AuthoredComponent, AuthoredDefaultsOf, AuthoredProp, ComponentBuilder, ComponentPropsOf, GlyphComponent, GlyphValue, LayerElement, LayerMap, LinkedHandle, ModifierProps, PhantomCallProps, PhantomReadProps, PropCondition, PropDecl, PropMap, RegisteredMembers, RenderArgs, SlotCodeForm, SlotDecl, StateMap, StyleProps, StyleRuleInput, UnconditionalDefaults, defineComponent };
|
|
927
|
+
export { AsInput, AuthoredComponent, AuthoredDefaultsOf, AuthoredProp, ComponentBuilder, ComponentPropsOf, GlyphComponent, GlyphValue, LayerElement, LayerMap, LinkedHandle, ModifierProps, PhantomCallProps, PhantomReadProps, PropCondition, PropDecl, PropMap, RegisteredMembers, RenderArgs, SlotCodeForm, SlotDecl, StateMap, StyleProps, StyleRefProps, StyleRefs, StyleRuleInput, UnconditionalDefaults, defineComponent };
|
|
@@ -22,6 +22,13 @@ interface LinkedElsewhere extends EntityAddress {
|
|
|
22
22
|
/** The slug of the pin it comes through. */
|
|
23
23
|
readonly from: string;
|
|
24
24
|
}
|
|
25
|
+
/** An entry in another pin's `options` that a take leaves applying to nothing, and removes. */
|
|
26
|
+
interface DroppedDirective extends EntityAddress {
|
|
27
|
+
/** The slug of the pin whose entry it was. */
|
|
28
|
+
readonly from: string;
|
|
29
|
+
/** The accessor the entry sits under in that pin's `options`. */
|
|
30
|
+
readonly accessor: string;
|
|
31
|
+
}
|
|
25
32
|
/** One row a link mints. `named` when a path the call named covers it; otherwise it comes along
|
|
26
33
|
* because something linked points at it. */
|
|
27
34
|
interface LinkArrival extends EntityAddress {
|
|
@@ -40,6 +47,10 @@ interface LinkPlan {
|
|
|
40
47
|
readonly linked: readonly LinkedElsewhere[];
|
|
41
48
|
/** Rows held through another pin, turned into extensions through this one. */
|
|
42
49
|
readonly extended: readonly EntityAddress[];
|
|
50
|
+
/** The other pins' `options` entries at what the take moves, removed with it: they adjust only the
|
|
51
|
+
* rows their pin derives, and the row there follows this one now. Not carried onto the taken row,
|
|
52
|
+
* since an entry corrects what that pin brings rather than stating a value of this config's own. */
|
|
53
|
+
readonly dropped: readonly DroppedDirective[];
|
|
43
54
|
/** Members already here from the source's own origin, left alone and kept out of the declaration. */
|
|
44
55
|
readonly shared: readonly EntityAddress[];
|
|
45
56
|
/** Paths another pin offers that a `hybrid` link reaches as a different entity. The other pin's
|
|
@@ -193,4 +204,4 @@ declare function sourceRowStates({
|
|
|
193
204
|
readonly slug: string;
|
|
194
205
|
}): SourceRowState[];
|
|
195
206
|
//#endregion
|
|
196
|
-
export { BreakOutcome, BreakPlan, BreakPlanInput, BreakPlanRow, BreakReach, LinkArrival, LinkPaths, LinkPlan, LinkPlanInput, LinkedElsewhere, OnLinked, SourceRowState, UnlinkPlan, UnlinkPlanInput, planBreak, planLink, planUnlink, sourceRowStates };
|
|
207
|
+
export { BreakOutcome, BreakPlan, BreakPlanInput, BreakPlanRow, BreakReach, DroppedDirective, LinkArrival, LinkPaths, LinkPlan, LinkPlanInput, LinkedElsewhere, OnLinked, SourceRowState, UnlinkPlan, UnlinkPlanInput, planBreak, planLink, planUnlink, sourceRowStates };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { collectRefs, isMintedRow, ref, sourceOf, splitRef } from "../../framework/utils/refs.js";
|
|
2
2
|
import { isConfigRejection, rejectData } from "../../framework/rejection.js";
|
|
3
3
|
import { blockedBy } from "../../framework/plan.js";
|
|
4
|
-
import { excludedCondition } from "../../framework/source-integrity.js";
|
|
4
|
+
import { danglingDirectives, excludedCondition } from "../../framework/source-integrity.js";
|
|
5
5
|
import { sameOrigin } from "../../framework/Config.js";
|
|
6
6
|
import { PIN_KIND, covers, declarationOf, entriesFor, excludePaths, excludes, includePaths, narrowDeclaration } from "./link-declaration.js";
|
|
7
7
|
import { planCopy, sourceEntries } from "./copy-plan.js";
|
|
@@ -238,11 +238,20 @@ function planLink({ config, input }) {
|
|
|
238
238
|
}
|
|
239
239
|
declared = Object.keys(next).length === 0 ? current : next;
|
|
240
240
|
}
|
|
241
|
-
const
|
|
241
|
+
const planned = [
|
|
242
242
|
...takes,
|
|
243
243
|
...declares,
|
|
244
244
|
...shadows
|
|
245
245
|
];
|
|
246
|
+
const { dropped, patches: drops } = takes.length > 0 ? directivesTakenFrom({
|
|
247
|
+
config,
|
|
248
|
+
slug,
|
|
249
|
+
patches: planned
|
|
250
|
+
}) : {
|
|
251
|
+
dropped: [],
|
|
252
|
+
patches: []
|
|
253
|
+
};
|
|
254
|
+
const patches = [...planned, ...drops];
|
|
246
255
|
return {
|
|
247
256
|
declared,
|
|
248
257
|
...outcome({
|
|
@@ -255,10 +264,74 @@ function planLink({ config, input }) {
|
|
|
255
264
|
addresses,
|
|
256
265
|
linked,
|
|
257
266
|
extended,
|
|
267
|
+
dropped,
|
|
258
268
|
shared,
|
|
259
269
|
patches
|
|
260
270
|
};
|
|
261
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* The other pins' `options` entries a take leaves applying to nothing, and the pin edits that remove
|
|
274
|
+
* them.
|
|
275
|
+
*
|
|
276
|
+
* An entry adjusts the rows its pin derives. A take writes this config's own row at the path, one that
|
|
277
|
+
* follows `slug`, so the other pin's entry stays in its `options` reading as though it still applied,
|
|
278
|
+
* and the build refuses it ({@link danglingDirectives}). Read off the config the take leaves, so a
|
|
279
|
+
* folder whose members all moved counts the way the build will count it, and only what the take
|
|
280
|
+
* itself left behind: an entry that already applied to nothing is the build's to report, not this
|
|
281
|
+
* take's to remove.
|
|
282
|
+
*
|
|
283
|
+
* Nothing when the take is refused; `outcome` says why.
|
|
284
|
+
*/
|
|
285
|
+
function directivesTakenFrom({ config, slug, patches }) {
|
|
286
|
+
let after;
|
|
287
|
+
try {
|
|
288
|
+
after = config.applyAll(patches).withDerivedRows();
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (!isConfigRejection(error)) throw error;
|
|
291
|
+
return {
|
|
292
|
+
dropped: [],
|
|
293
|
+
patches: []
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
const key = (at) => `${at.slug}\u0000${at.accessor}\u0000${at.path}`;
|
|
297
|
+
const already = new Set(danglingDirectives(config).map(key));
|
|
298
|
+
const dropped = [];
|
|
299
|
+
for (const at of danglingDirectives(after)) {
|
|
300
|
+
if (at.missing !== "row" || at.heldBy !== slug || already.has(key(at))) continue;
|
|
301
|
+
dropped.push({
|
|
302
|
+
kind: config.accessors()[at.accessor]?.kind ?? at.accessor,
|
|
303
|
+
path: at.path,
|
|
304
|
+
from: at.slug,
|
|
305
|
+
accessor: at.accessor
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
const edits = [];
|
|
309
|
+
for (const pin of new Set(dropped.map((at) => at.from))) {
|
|
310
|
+
const options = config.storedBody("linked-system", pin).options ?? {};
|
|
311
|
+
const data = {};
|
|
312
|
+
let emptied = 0;
|
|
313
|
+
for (const [accessor, entries] of Object.entries(options)) {
|
|
314
|
+
const going = dropped.filter((at) => at.from === pin && at.accessor === accessor).map((at) => at.path);
|
|
315
|
+
if (going.length === 0) continue;
|
|
316
|
+
if (Object.keys(entries ?? {}).filter((path) => !going.includes(path)).length > 0) {
|
|
317
|
+
for (const path of going) data[`options.${accessor}.${path}`] = null;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
data[`options.${accessor}`] = null;
|
|
321
|
+
emptied += 1;
|
|
322
|
+
}
|
|
323
|
+
edits.push({
|
|
324
|
+
kind: PIN_KIND,
|
|
325
|
+
operation: "update",
|
|
326
|
+
path: pin,
|
|
327
|
+
data: emptied === Object.keys(options).length ? { options: null } : data
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
dropped,
|
|
332
|
+
patches: edits
|
|
333
|
+
};
|
|
334
|
+
}
|
|
262
335
|
/** What a plan reports of a refusal: its message, and the collisions when that's what it names. */
|
|
263
336
|
function refusal(error) {
|
|
264
337
|
const collisions = error.issues.flatMap((issue) => issue.collisions ?? []);
|
package/dist/framework/Config.js
CHANGED
|
@@ -5138,6 +5138,40 @@ var Config = class Config {
|
|
|
5138
5138
|
const folders = [];
|
|
5139
5139
|
/** Folders this pass leaves as they stand — already held, over rows it still claims. */
|
|
5140
5140
|
const standing = /* @__PURE__ */ new Set();
|
|
5141
|
+
const taken = [];
|
|
5142
|
+
for (const kind of this.ownedKinds()) for (const [path, stored] of this.state.snapshot.slice(kind).items) {
|
|
5143
|
+
const body = stored.toJSON();
|
|
5144
|
+
if (!isExtendedRef(body) || isMintedRow(body)) continue;
|
|
5145
|
+
if (pathOf(body) !== path) continue;
|
|
5146
|
+
const slug = sourceOf(body);
|
|
5147
|
+
if (slug !== void 0) taken.push({
|
|
5148
|
+
kind,
|
|
5149
|
+
path,
|
|
5150
|
+
slug
|
|
5151
|
+
});
|
|
5152
|
+
}
|
|
5153
|
+
/** Every folder a pin has a member under this pass, claimed or taken, as `slug kind path`. */
|
|
5154
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
5155
|
+
const occupy = (slug, kind, path) => {
|
|
5156
|
+
const segments = path.split("/");
|
|
5157
|
+
for (let depth = 1; depth < segments.length; depth++) occupied.add(`${slug}\u0000${kind}\u0000${segments.slice(0, depth).join("/")}`);
|
|
5158
|
+
};
|
|
5159
|
+
for (const [target, slug] of claimedFrom) occupy(slug, kindOf(target), pathOf(target));
|
|
5160
|
+
for (const { kind, path, slug } of taken) occupy(slug, kind, path);
|
|
5161
|
+
/**
|
|
5162
|
+
* Whether a folder already here stays as it is. One this config authored does, and so does one
|
|
5163
|
+
* minted through a pin that still has a member under it. One minted through a pin that has none
|
|
5164
|
+
* left there goes to the pin its members follow now: after a take, a `colorMode` whose modes all
|
|
5165
|
+
* follow Yahoo OS kept pointing at the Bridge's, its fields read from a system none of it follows.
|
|
5166
|
+
*/
|
|
5167
|
+
const stands = (kind, path) => {
|
|
5168
|
+
const held = this.state.snapshot.group(kind, path)?.toJSON();
|
|
5169
|
+
if (held === void 0) return false;
|
|
5170
|
+
if (!isMintedRow(held)) return true;
|
|
5171
|
+
const pointer = held.ref;
|
|
5172
|
+
const through = isRef(pointer) ? sourceOf(pointer) : void 0;
|
|
5173
|
+
return through !== void 0 && occupied.has(`${through}\u0000${kind}\u0000${path}`);
|
|
5174
|
+
};
|
|
5141
5175
|
for (const [slug, paths] of offeredBy) {
|
|
5142
5176
|
const source = this.sourceFor(slug);
|
|
5143
5177
|
if (!source) continue;
|
|
@@ -5149,7 +5183,7 @@ var Config = class Config {
|
|
|
5149
5183
|
for (const group of source.groups(kind)) {
|
|
5150
5184
|
const prefix = `${group.path}/`;
|
|
5151
5185
|
if (!under.some((path) => path.startsWith(prefix))) continue;
|
|
5152
|
-
if (
|
|
5186
|
+
if (stands(kind, group.path)) {
|
|
5153
5187
|
standing.add(`group:${kind}:${group.path}`);
|
|
5154
5188
|
continue;
|
|
5155
5189
|
}
|
|
@@ -5162,6 +5196,27 @@ var Config = class Config {
|
|
|
5162
5196
|
}
|
|
5163
5197
|
}
|
|
5164
5198
|
}
|
|
5199
|
+
const derivedFolders = new Set(folders.map(({ kind, path }) => `${kind}:${path}`));
|
|
5200
|
+
for (const { kind, path, slug } of taken) {
|
|
5201
|
+
const source = this.sourceFor(slug);
|
|
5202
|
+
if (!source || !this.entityOf(kind)) continue;
|
|
5203
|
+
for (const group of source.groups(kind)) {
|
|
5204
|
+
if (!path.startsWith(`${group.path}/`)) continue;
|
|
5205
|
+
const target = `${kind}:${group.path}`;
|
|
5206
|
+
if (derivedFolders.has(target) || standing.has(`group:${target}`)) continue;
|
|
5207
|
+
if (stands(kind, group.path)) {
|
|
5208
|
+
standing.add(`group:${target}`);
|
|
5209
|
+
continue;
|
|
5210
|
+
}
|
|
5211
|
+
derivedFolders.add(target);
|
|
5212
|
+
folders.push({
|
|
5213
|
+
kind,
|
|
5214
|
+
path: group.path,
|
|
5215
|
+
slug
|
|
5216
|
+
});
|
|
5217
|
+
claimedFrom.set(target, slug);
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5165
5220
|
for (const [target, slug] of claimedFrom) {
|
|
5166
5221
|
if (folders.some(({ kind, path }) => `${kind}:${path}` === target)) continue;
|
|
5167
5222
|
changes.push(derivedItemChange(kindOf(target), pathOf(target), ref(kindOf(target), pathOf(target), slug).__ref, overlayBody({
|
|
@@ -5324,7 +5379,22 @@ var Config = class Config {
|
|
|
5324
5379
|
const source = this.sourceFor(slug);
|
|
5325
5380
|
if (!source) return [];
|
|
5326
5381
|
const members = /* @__PURE__ */ new Set();
|
|
5327
|
-
|
|
5382
|
+
/**
|
|
5383
|
+
* Every entity or folder visited, and whether a linked row reached it.
|
|
5384
|
+
*
|
|
5385
|
+
* A taken row is visited twice — first as an authored row, then as one its pin adopts — and only a
|
|
5386
|
+
* linked visit lands the items a body points at. Remembering only THAT a target was visited let the
|
|
5387
|
+
* unlinked pass claim the style properties and token folders it found, so the linked pass skipped
|
|
5388
|
+
* them and a mode their tokens vary under never got a row. A target reached unlinked is visited
|
|
5389
|
+
* again when a linked row reaches it; one reached linked is done.
|
|
5390
|
+
*/
|
|
5391
|
+
const reached = /* @__PURE__ */ new Map();
|
|
5392
|
+
const reaching = (target, linked) => {
|
|
5393
|
+
const prior = reached.get(target);
|
|
5394
|
+
if (prior === true || prior === false && !linked) return false;
|
|
5395
|
+
reached.set(target, linked);
|
|
5396
|
+
return true;
|
|
5397
|
+
};
|
|
5328
5398
|
/**
|
|
5329
5399
|
* A style bag's KEYS name style properties, and a borrowed bag's name the SOURCE's.
|
|
5330
5400
|
*
|
|
@@ -5342,11 +5412,11 @@ var Config = class Config {
|
|
|
5342
5412
|
if (!sites) return;
|
|
5343
5413
|
for (const { bag } of sites(body)) for (const prop of Object.keys(bag)) {
|
|
5344
5414
|
const target = `style-property:${prop}`;
|
|
5345
|
-
if (members.has(target)) continue;
|
|
5346
5415
|
const local = this.storedBody("style-property", prop);
|
|
5347
5416
|
if (local && !isMintedRow(local)) continue;
|
|
5348
5417
|
const declared = source.resolve("style-property", prop);
|
|
5349
5418
|
if (!declared) continue;
|
|
5419
|
+
if (!reaching(target, linked)) continue;
|
|
5350
5420
|
members.add(target);
|
|
5351
5421
|
visitEntity("style-property", declared.toJSON(), true, linked);
|
|
5352
5422
|
}
|
|
@@ -5377,19 +5447,19 @@ var Config = class Config {
|
|
|
5377
5447
|
const target = `${kind}:${path}`;
|
|
5378
5448
|
const item = source.resolve(kind, path);
|
|
5379
5449
|
if (item) {
|
|
5380
|
-
if (!linked ||
|
|
5450
|
+
if (!linked || !reaching(target, true)) continue;
|
|
5381
5451
|
members.add(target);
|
|
5382
5452
|
visitEntity(kind, item.toJSON(), true, true);
|
|
5383
5453
|
continue;
|
|
5384
5454
|
}
|
|
5385
|
-
if (
|
|
5386
|
-
walked.add(target);
|
|
5455
|
+
if (!reaching(target, linked)) continue;
|
|
5387
5456
|
if (!source.groups(kind).some((node) => node.path === path)) continue;
|
|
5388
5457
|
const prefix = `${path}/`;
|
|
5389
5458
|
for (const member of source.list(kind)) {
|
|
5390
5459
|
if (!member.path.startsWith(prefix)) continue;
|
|
5391
|
-
|
|
5392
|
-
|
|
5460
|
+
const at = `${kind}:${member.path}`;
|
|
5461
|
+
members.add(at);
|
|
5462
|
+
if (reaching(at, linked)) visitEntity(kind, member.toJSON(), true, linked);
|
|
5393
5463
|
}
|
|
5394
5464
|
}
|
|
5395
5465
|
};
|
|
@@ -60,6 +60,9 @@ type Read<F extends FieldsSchema, C extends ComputedFields> = Entity & z.infer<F
|
|
|
60
60
|
type KindRef<E, K extends string, P extends string> = ExtendableRef<Partial<CreateInputOf<E>>> & {
|
|
61
61
|
readonly __ref: `${K}:${P}`;
|
|
62
62
|
};
|
|
63
|
+
/** What an entity's `item` hands back: a body `E` creates from, or the shorthand for its primary
|
|
64
|
+
* field. */
|
|
65
|
+
type ItemInput<E> = CreateInputOf<E> | string | number | Ref;
|
|
63
66
|
/** The body `E` creates an item from, read off its `create`. Open when `E` is no entity, as for a
|
|
64
67
|
* `ref` called detached from one. */
|
|
65
68
|
type CreateInputOf<E> = E extends {
|
|
@@ -94,7 +97,7 @@ type OpInputsOf<S extends UserSchemas> = { readonly [V in keyof S as S[V] extend
|
|
|
94
97
|
} ? {
|
|
95
98
|
readonly input: I;
|
|
96
99
|
} : never };
|
|
97
|
-
|
|
100
|
+
interface EntityClass<F extends FieldsSchema, G extends FieldsSchema,
|
|
98
101
|
/** The kind as a literal, so `ref` can narrow to the paths a consumer's config declares. Defaults
|
|
99
102
|
* to `string`, which is what every 2-argument use of this type keeps getting. */
|
|
100
103
|
K extends string = string,
|
|
@@ -112,7 +115,7 @@ Single extends boolean = false,
|
|
|
112
115
|
GC extends GroupComputedFields = Record<never, never>,
|
|
113
116
|
/** The kind's `groupInputs` as written, so `group()` takes each input key at its handler's declared
|
|
114
117
|
* type. Defaults to none. */
|
|
115
|
-
GI extends GroupInputs = Record<never, never>>
|
|
118
|
+
GI extends GroupInputs = Record<never, never>> extends Omit<RefSchema, 'extend'> {
|
|
116
119
|
readonly kind: K;
|
|
117
120
|
/** Whether the kind has exactly one item — see `singleton` on `defineEntity`. A property rather than
|
|
118
121
|
* only a type parameter so a conditional type can tell the two apart: `get`'s signature differs by
|
|
@@ -136,7 +139,7 @@ GI extends GroupInputs = Record<never, never>> = Omit<RefSchema, 'extend'> & {
|
|
|
136
139
|
readonly ref: Single extends true ? <E, P extends PathOf<K>>(this: E, path?: P) => KindRef<E, K, P> : <E, P extends PathOf<K>>(this: E, path: P) => KindRef<E, K, P>;
|
|
137
140
|
/** Typed constructor for one item — a full body, or a bare value/ref that's shorthand
|
|
138
141
|
* for the kind's primary field. Returned as-is; `register` normalizes the shorthand. */
|
|
139
|
-
item(def: CreateInput<F> | string | number | Ref):
|
|
142
|
+
item(def: CreateInput<F> | string | number | Ref): ItemInput<this>;
|
|
140
143
|
/** Typed constructor for a group node — branded so `register` routes it to the group
|
|
141
144
|
* store; input is the group fields' create body, plus any registration-time input the kind
|
|
142
145
|
* declares (`groupInputs`), which is consumed here and never stored. */
|
|
@@ -148,7 +151,8 @@ GI extends GroupInputs = Record<never, never>> = Omit<RefSchema, 'extend'> & {
|
|
|
148
151
|
get(config: Config, ...pathOrRef: Single extends true ? [pathOrRef?: string | Ref] : [pathOrRef: string | Ref]): Read<F, C> | undefined;
|
|
149
152
|
/** Every item of this kind, typed off the fields — `Component.list(config)`. Total by default;
|
|
150
153
|
* `{ retired: false }` is the offer surface's read (see `Config.list`). */
|
|
151
|
-
list(config: Config, opts?: ListOptions): Read<F, C>[];
|
|
154
|
+
list(config: Config, opts?: ListOptions): Read<F, C>[];
|
|
155
|
+
/** This kind's items as a folder/file tree — `Component.tree(config)` (the sidebar). */
|
|
152
156
|
tree(config: Config): TreeNode[];
|
|
153
157
|
/** This kind's group nodes and their metadata — `Package.groups(config)`, the packages a system
|
|
154
158
|
* depends on. The enumeration `list`/`tree` can't give: both derive from item paths, so a group
|
|
@@ -162,11 +166,13 @@ GI extends GroupInputs = Record<never, never>> = Omit<RefSchema, 'extend'> & {
|
|
|
162
166
|
dependents(config: Config, path: string, opts?: TraverseOptions): string[];
|
|
163
167
|
/** Create an item of this kind — `Component.create(config, 'Button', {…})`. Typed body; returns
|
|
164
168
|
* the config for chaining. (The typed twin of `config.apply({kind, operation:'create', …})`.) */
|
|
165
|
-
create<C extends Config>(config: C, path: string, data: CreateInput<F>): C;
|
|
169
|
+
create<C extends Config>(config: C, path: string, data: CreateInput<F>): C;
|
|
170
|
+
/** Update an item — a partial patch merged over the current value. */
|
|
166
171
|
update<C extends Config>(config: C, path: string, data: Partial<z.infer<F>>): C;
|
|
167
172
|
/** Delete an item, with whatever cannot exist without it ({@link EntityKind.structuralBody}). Refused
|
|
168
173
|
* while anything else still references it. */
|
|
169
|
-
delete<C extends Config>(config: C, path: string): C;
|
|
174
|
+
delete<C extends Config>(config: C, path: string): C;
|
|
175
|
+
/** Rename an item's path — references cascade. */
|
|
170
176
|
rename<C extends Config>(config: C, path: string, to: string): C;
|
|
171
177
|
/**
|
|
172
178
|
* Make a variant of this kind — same kind, different rules, stating only the differences.
|
|
@@ -206,7 +212,7 @@ GI extends GroupInputs = Record<never, never>> = Omit<RefSchema, 'extend'> & {
|
|
|
206
212
|
* Config that never imported it. See {@link EntityKind.entityName}. */
|
|
207
213
|
entityName?: string;
|
|
208
214
|
}): EntityClass<ExtendedFields<F, F2>, ExtendedFields<G, G2>, K, [S2] extends [never] ? S : OpInputsOf<S2>, C, Single, GC, GI>;
|
|
209
|
-
}
|
|
215
|
+
}
|
|
210
216
|
declare function defineEntity<F extends FieldsSchema, G extends FieldsSchema = z.ZodObject<Record<never, never>>, K extends string = string, const S extends UserSchemas = Record<never, never>, const C extends ComputedFields = Record<never, never>, Single extends boolean = false, const GC extends GroupComputedFields = Record<never, never>, const GI extends GroupInputs = Record<never, never>>(spec: {
|
|
211
217
|
kind: K;
|
|
212
218
|
/** The kind's fields, or a factory over the write's context (`config`, `body`) when a field's
|
|
@@ -401,4 +407,4 @@ type OpInput<E extends {
|
|
|
401
407
|
input: infer I extends z.ZodTypeAny;
|
|
402
408
|
} ? z.input<I> : never;
|
|
403
409
|
//#endregion
|
|
404
|
-
export { EntityClass, GroupComputedInput, ItemOf, KindRef, OpInput, defineEntity };
|
|
410
|
+
export { EntityClass, GroupComputedInput, ItemInput, ItemOf, KindRef, OpInput, defineEntity };
|
|
@@ -239,12 +239,17 @@ interface DanglingDirective {
|
|
|
239
239
|
/** The accessor as written — this config may have no kind under it. */
|
|
240
240
|
accessor: string;
|
|
241
241
|
path: string;
|
|
242
|
-
/**
|
|
243
|
-
|
|
242
|
+
/**
|
|
243
|
+
* `accessor` when no kind is registered under that name, `path` when the source has no such entity,
|
|
244
|
+
* `row` when the source has it but the row here isn't one the pin derives.
|
|
245
|
+
*/
|
|
246
|
+
missing: 'accessor' | 'path' | 'row';
|
|
247
|
+
/** With `row`: the pin the row there follows instead, absent when it is this config's own. */
|
|
248
|
+
heldBy?: string;
|
|
244
249
|
}
|
|
245
250
|
/**
|
|
246
|
-
* Every directive aimed at nothing — an accessor this config has no kind for,
|
|
247
|
-
* does not have.
|
|
251
|
+
* Every directive aimed at nothing — an accessor this config has no kind for, a path the source
|
|
252
|
+
* does not have, or a path where the row here isn't one the pin derives.
|
|
248
253
|
*
|
|
249
254
|
* The one mistake the other checks structurally cannot see. Each of them answers for a path it is
|
|
250
255
|
* already holding, so it asks "does the declaration mention this one" — and a name nobody has is
|
|
@@ -254,6 +259,10 @@ interface DanglingDirective {
|
|
|
254
259
|
* Also what notices the source dropping a path. A directive written against an entity a later version
|
|
255
260
|
* removed keeps parsing and keeps doing nothing, which is the same failure the declared verb exists to
|
|
256
261
|
* catch one level down.
|
|
262
|
+
*
|
|
263
|
+
* And what notices a path leaving the pin. A row taken through another pin (`linked-system/link` with
|
|
264
|
+
* `onLinked: 'take'`), or authored here, stands where the pin's row stood, and the entry the pin
|
|
265
|
+
* still carries for it applies to nothing.
|
|
257
266
|
*/
|
|
258
267
|
declare function danglingDirectives(config: Config): DanglingDirective[];
|
|
259
268
|
/** A borrowed token whose condition is missing or has a different category here. */
|
|
@@ -489,8 +489,25 @@ function unadoptedDirectives(config) {
|
|
|
489
489
|
return found;
|
|
490
490
|
}
|
|
491
491
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
492
|
+
* Who holds the row at a path a directive names, when it isn't the directive's own pin: the slug of
|
|
493
|
+
* the pin the row follows instead, `null` for a row of this config's own, `undefined` when the pin's
|
|
494
|
+
* row is there or nothing is.
|
|
495
|
+
*
|
|
496
|
+
* A pin's `options` lay over the rows its declaration derives, and nothing else. A row taken through
|
|
497
|
+
* another pin, or authored here, stands at the path in its place, so the entry applies to nothing.
|
|
498
|
+
*/
|
|
499
|
+
function heldElsewhere(config, { slug, kind, path }) {
|
|
500
|
+
const item = config.storedBody(kind, path);
|
|
501
|
+
const group = item === void 0 ? config.groupMeta(kind, path) : void 0;
|
|
502
|
+
if (item === void 0 && group === void 0) return void 0;
|
|
503
|
+
const pointer = item ?? group?.ref;
|
|
504
|
+
const through = isRef(pointer) ? sourceOf(pointer) : void 0;
|
|
505
|
+
if (through === slug) return void 0;
|
|
506
|
+
return through ?? null;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Every directive aimed at nothing — an accessor this config has no kind for, a path the source
|
|
510
|
+
* does not have, or a path where the row here isn't one the pin derives.
|
|
494
511
|
*
|
|
495
512
|
* The one mistake the other checks structurally cannot see. Each of them answers for a path it is
|
|
496
513
|
* already holding, so it asks "does the declaration mention this one" — and a name nobody has is
|
|
@@ -500,6 +517,10 @@ function unadoptedDirectives(config) {
|
|
|
500
517
|
* Also what notices the source dropping a path. A directive written against an entity a later version
|
|
501
518
|
* removed keeps parsing and keeps doing nothing, which is the same failure the declared verb exists to
|
|
502
519
|
* catch one level down.
|
|
520
|
+
*
|
|
521
|
+
* And what notices a path leaving the pin. A row taken through another pin (`linked-system/link` with
|
|
522
|
+
* `onLinked: 'take'`), or authored here, stands where the pin's row stood, and the entry the pin
|
|
523
|
+
* still carries for it applies to nothing.
|
|
503
524
|
*/
|
|
504
525
|
function danglingDirectives(config) {
|
|
505
526
|
const found = [];
|
|
@@ -516,7 +537,23 @@ function danglingDirectives(config) {
|
|
|
516
537
|
});
|
|
517
538
|
continue;
|
|
518
539
|
}
|
|
519
|
-
if (source.resolve(kind, path) || source.members(kind, path).length > 0)
|
|
540
|
+
if (source.resolve(kind, path) || source.members(kind, path).length > 0) {
|
|
541
|
+
if (config.sourceOverlay(slug, kind, path)?.hidden === true) continue;
|
|
542
|
+
const heldBy = heldElsewhere(config, {
|
|
543
|
+
slug,
|
|
544
|
+
kind,
|
|
545
|
+
path
|
|
546
|
+
});
|
|
547
|
+
if (heldBy === void 0) continue;
|
|
548
|
+
found.push({
|
|
549
|
+
slug,
|
|
550
|
+
accessor,
|
|
551
|
+
path,
|
|
552
|
+
missing: "row",
|
|
553
|
+
...heldBy === null ? {} : { heldBy }
|
|
554
|
+
});
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
520
557
|
found.push({
|
|
521
558
|
slug,
|
|
522
559
|
accessor,
|