@yahoo/uds-create-config 2.45.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/ai-lanes.d.ts +23 -0
- package/dist/ai-lanes.js +34 -0
- package/dist/authoring/define-component.d.ts +85 -0
- package/dist/configs/CanvasConfig.d.ts +3237 -0
- package/dist/configs/CanvasConfig.js +332 -0
- package/dist/configs/build-options.d.ts +10 -0
- package/dist/configs/build-options.js +68 -0
- package/dist/configs/platform.d.ts +15 -0
- package/dist/configs/platform.js +17 -0
- package/dist/configs/react-native-system.d.ts +3026 -0
- package/dist/configs/react-native-system.js +64 -0
- package/dist/configs/system.d.ts +2771 -0
- package/dist/configs/system.js +74 -0
- package/dist/css/properties.generated.d.ts +14 -0
- package/dist/css/properties.generated.js +6260 -0
- package/dist/css/value-type.d.ts +48 -0
- package/dist/css/value-type.js +131 -0
- package/dist/css/values.d.ts +33 -0
- package/dist/css/values.js +116 -0
- package/dist/entities/native/NativeModifier.d.ts +25 -0
- package/dist/entities/native/NativeModifier.js +41 -0
- package/dist/entities/native/NativeSettings.d.ts +44 -0
- package/dist/entities/native/NativeSettings.js +39 -0
- package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
- package/dist/entities/native/NativeStyleProperty.js +28 -0
- package/dist/entities/native/NativeToken.d.ts +31 -0
- package/dist/entities/native/NativeToken.js +49 -0
- package/dist/entities/system/CanvasRole.d.ts +34 -0
- package/dist/entities/system/CanvasRole.js +45 -0
- package/dist/entities/system/Component.d.ts +1287 -0
- package/dist/entities/system/Component.js +1840 -0
- package/dist/entities/system/Composite.d.ts +12 -0
- package/dist/entities/system/Composite.js +26 -0
- package/dist/entities/system/Device.d.ts +11 -0
- package/dist/entities/system/Device.js +18 -0
- package/dist/entities/system/File.d.ts +72 -0
- package/dist/entities/system/File.js +136 -0
- package/dist/entities/system/Font.d.ts +48 -0
- package/dist/entities/system/Font.js +56 -0
- package/dist/entities/system/GlobalStyle.d.ts +26 -0
- package/dist/entities/system/GlobalStyle.js +54 -0
- package/dist/entities/system/Guidance.d.ts +85 -0
- package/dist/entities/system/Guidance.js +59 -0
- package/dist/entities/system/GuidanceStyle.d.ts +14 -0
- package/dist/entities/system/GuidanceStyle.js +8 -0
- package/dist/entities/system/Icon.d.ts +46 -0
- package/dist/entities/system/Icon.js +46 -0
- package/dist/entities/system/LinkedSystem.d.ts +504 -0
- package/dist/entities/system/LinkedSystem.js +814 -0
- package/dist/entities/system/Modifier.d.ts +92 -0
- package/dist/entities/system/Modifier.js +120 -0
- package/dist/entities/system/Motion.d.ts +28 -0
- package/dist/entities/system/Motion.js +48 -0
- package/dist/entities/system/Operation.d.ts +100 -0
- package/dist/entities/system/Operation.js +236 -0
- package/dist/entities/system/Package.d.ts +42 -0
- package/dist/entities/system/Package.js +75 -0
- package/dist/entities/system/Settings.d.ts +94 -0
- package/dist/entities/system/Settings.js +166 -0
- package/dist/entities/system/StyleProperty.d.ts +135 -0
- package/dist/entities/system/StyleProperty.js +438 -0
- package/dist/entities/system/Token.d.ts +67 -0
- package/dist/entities/system/Token.js +129 -0
- package/dist/entities/system/Tool.d.ts +134 -0
- package/dist/entities/system/Tool.js +124 -0
- package/dist/entities/system/color.d.ts +64 -0
- package/dist/entities/system/color.js +123 -0
- package/dist/entities/system/component-module.d.ts +63 -0
- package/dist/entities/system/component-module.js +258 -0
- package/dist/entities/system/copy-plan.d.ts +98 -0
- package/dist/entities/system/copy-plan.js +451 -0
- package/dist/entities/system/defineComponent.d.ts +428 -0
- package/dist/entities/system/defineComponent.js +337 -0
- package/dist/entities/system/element.d.ts +101 -0
- package/dist/entities/system/element.js +171 -0
- package/dist/entities/system/icon-library.d.ts +64 -0
- package/dist/entities/system/icon-library.js +112 -0
- package/dist/entities/system/icon-metadata.d.ts +72 -0
- package/dist/entities/system/icon-metadata.js +111 -0
- package/dist/entities/system/link-declaration.d.ts +27 -0
- package/dist/entities/system/link-declaration.js +64 -0
- package/dist/entities/system/link-plan.d.ts +160 -0
- package/dist/entities/system/link-plan.js +770 -0
- package/dist/entities/system/runtime-modules.d.ts +25 -0
- package/dist/entities/system/runtime-modules.js +38 -0
- package/dist/entities/system/style-bag.d.ts +20 -0
- package/dist/entities/system/style-bag.js +246 -0
- package/dist/entities/system/token-index.d.ts +89 -0
- package/dist/entities/system/token-index.js +112 -0
- package/dist/framework/Config.d.ts +2472 -0
- package/dist/framework/Config.js +5023 -0
- package/dist/framework/Entity.d.ts +127 -0
- package/dist/framework/Entity.js +125 -0
- package/dist/framework/authoring.d.ts +24 -0
- package/dist/framework/authoring.js +7 -0
- package/dist/framework/change-hooks.d.ts +119 -0
- package/dist/framework/change-hooks.js +131 -0
- package/dist/framework/changes.d.ts +88 -0
- package/dist/framework/changes.js +246 -0
- package/dist/framework/class-names.d.ts +260 -0
- package/dist/framework/class-names.js +630 -0
- package/dist/framework/coalesce.d.ts +25 -0
- package/dist/framework/coalesce.js +60 -0
- package/dist/framework/config-op.d.ts +76 -0
- package/dist/framework/config-op.js +43 -0
- package/dist/framework/config-operation-kind.d.ts +14 -0
- package/dist/framework/config-operation-kind.js +14 -0
- package/dist/framework/config-ops.d.ts +34 -0
- package/dist/framework/config-ops.js +187 -0
- package/dist/framework/defineConfig.d.ts +196 -0
- package/dist/framework/defineConfig.js +100 -0
- package/dist/framework/defineDerivedEntity.d.ts +74 -0
- package/dist/framework/defineDerivedEntity.js +83 -0
- package/dist/framework/defineEntity.d.ts +318 -0
- package/dist/framework/defineEntity.js +183 -0
- package/dist/framework/defineSubEntity.d.ts +148 -0
- package/dist/framework/defineSubEntity.js +121 -0
- package/dist/framework/derived-mutations.d.ts +20 -0
- package/dist/framework/derived-mutations.js +38 -0
- package/dist/framework/entity-search.d.ts +29 -0
- package/dist/framework/entity-search.js +117 -0
- package/dist/framework/inline-sources.d.ts +49 -0
- package/dist/framework/inline-sources.js +388 -0
- package/dist/framework/layer-styles.d.ts +25 -0
- package/dist/framework/layer-styles.js +49 -0
- package/dist/framework/memo.d.ts +48 -0
- package/dist/framework/memo.js +84 -0
- package/dist/framework/overlay.d.ts +49 -0
- package/dist/framework/overlay.js +17 -0
- package/dist/framework/plan.d.ts +49 -0
- package/dist/framework/plan.js +73 -0
- package/dist/framework/projections.d.ts +480 -0
- package/dist/framework/projections.js +974 -0
- package/dist/framework/prop-surface.d.ts +132 -0
- package/dist/framework/prop-surface.js +278 -0
- package/dist/framework/ref-graph.d.ts +71 -0
- package/dist/framework/ref-graph.js +158 -0
- package/dist/framework/ref-integrity.d.ts +55 -0
- package/dist/framework/ref-integrity.js +171 -0
- package/dist/framework/registered.d.ts +95 -0
- package/dist/framework/registry-dir.d.ts +42 -0
- package/dist/framework/registry-dir.js +48 -0
- package/dist/framework/registry.d.ts +300 -0
- package/dist/framework/registry.js +104 -0
- package/dist/framework/rejection.d.ts +58 -0
- package/dist/framework/rejection.js +111 -0
- package/dist/framework/rename-inference.d.ts +26 -0
- package/dist/framework/rename-inference.js +50 -0
- package/dist/framework/render-spec.d.ts +296 -0
- package/dist/framework/render-spec.js +809 -0
- package/dist/framework/schema-version.d.ts +140 -0
- package/dist/framework/schema-version.js +214 -0
- package/dist/framework/schemas.d.ts +109 -0
- package/dist/framework/schemas.js +615 -0
- package/dist/framework/session.d.ts +196 -0
- package/dist/framework/session.js +367 -0
- package/dist/framework/signature.d.ts +15 -0
- package/dist/framework/signature.js +83 -0
- package/dist/framework/snapshot.d.ts +115 -0
- package/dist/framework/snapshot.js +277 -0
- package/dist/framework/source-integrity.d.ts +226 -0
- package/dist/framework/source-integrity.js +478 -0
- package/dist/framework/sources.d.ts +211 -0
- package/dist/framework/sources.js +89 -0
- package/dist/framework/utils/compiled-schema.d.ts +23 -0
- package/dist/framework/utils/compiled-schema.js +46 -0
- package/dist/framework/utils/content-key.d.ts +15 -0
- package/dist/framework/utils/content-key.js +33 -0
- package/dist/framework/utils/enumerated.d.ts +13 -0
- package/dist/framework/utils/enumerated.js +19 -0
- package/dist/framework/utils/field-path.d.ts +95 -0
- package/dist/framework/utils/field-path.js +136 -0
- package/dist/framework/utils/field-schema.d.ts +55 -0
- package/dist/framework/utils/field-schema.js +183 -0
- package/dist/framework/utils/group.d.ts +37 -0
- package/dist/framework/utils/group.js +13 -0
- package/dist/framework/utils/package-path.d.ts +37 -0
- package/dist/framework/utils/package-path.js +61 -0
- package/dist/framework/utils/refs.d.ts +194 -0
- package/dist/framework/utils/refs.js +403 -0
- package/dist/framework/validate-spec.d.ts +27 -0
- package/dist/framework/validate-spec.js +45 -0
- package/dist/framework/value-domain.d.ts +26 -0
- package/dist/framework/value-domain.js +202 -0
- package/dist/framework/views-facade.d.ts +15 -0
- package/dist/framework/views-facade.js +19 -0
- package/dist/index.d.ts +90 -42
- package/dist/index.js +86 -37
- package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
- package/dist/migrations/2.0.0/raw-css.js +72 -0
- package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
- package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
- package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
- package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
- package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
- package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
- package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
- package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
- package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
- package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.js +2 -0
- package/dist/react-native/style-keys.generated.d.ts +10 -0
- package/dist/react-native/style-keys.generated.js +167 -0
- package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
- package/dist/renderer/RendererErrorBoundary.js +59 -10
- package/dist/renderer/UdsRenderer.d.ts +11 -10
- package/dist/renderer/UdsRenderer.js +1 -1
- package/dist/renderer/assetEntries.d.ts +37 -0
- package/dist/renderer/assetEntries.js +39 -0
- package/dist/renderer/assetRenderable.d.ts +14 -6
- package/dist/renderer/assetRenderable.js +8 -2
- package/dist/renderer/componentEntry.d.ts +58 -0
- package/dist/renderer/componentEntry.js +71 -0
- package/dist/renderer/icon-library.d.ts +20 -0
- package/dist/renderer/index.d.ts +7 -7
- package/dist/renderer/index.js +5 -5
- package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
- package/dist/renderer/primitives/SlotRenderer.js +1 -1
- package/dist/renderer/runtimeComponent.d.ts +33 -0
- package/dist/renderer/runtimeComponent.js +113 -0
- package/dist/renderer/spec-content.d.ts +43 -0
- package/dist/renderer/spec-content.js +95 -0
- package/dist/renderer/wrapRegistry.d.ts +22 -37
- package/dist/renderer/wrapRegistry.js +10 -20
- package/dist/renderer/wrappers/event-bridge.js +6 -5
- package/dist/renderer/wrappers/hex-normalize.js +6 -5
- package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
- package/dist/renderer/wrappers/html-aliases.js +36 -19
- package/dist/renderer/wrappers/inline-styles.js +7 -6
- package/dist/spec/asset-jsx.d.ts +18 -5
- package/dist/spec/asset-jsx.js +27 -16
- package/dist/spec/collapse-text-labels.d.ts +5 -15
- package/dist/spec/collapse-text-labels.js +26 -19
- package/dist/spec/empty-node-slots.d.ts +56 -34
- package/dist/spec/empty-node-slots.js +87 -47
- package/dist/spec/index.d.ts +21 -10
- package/dist/spec/index.js +21 -10
- package/dist/spec/jsxToSpec.d.ts +14 -9
- package/dist/spec/jsxToSpec.js +20 -3
- package/dist/spec/preview-elements.d.ts +63 -0
- package/dist/spec/preview-elements.js +89 -0
- package/dist/spec/rewrite-refs.d.ts +58 -0
- package/dist/spec/rewrite-refs.js +250 -0
- package/dist/spec/specToJsx.js +18 -29
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +39 -52
- package/dist/AssetGroup.d.ts +0 -77
- package/dist/AssetGroup.js +0 -125
- package/dist/Component.d.ts +0 -333
- package/dist/Component.js +0 -1061
- package/dist/ComponentGroup.d.ts +0 -22
- package/dist/ComponentGroup.js +0 -51
- package/dist/CompositeStyle.d.ts +0 -30
- package/dist/CompositeStyle.js +0 -59
- package/dist/Config.d.ts +0 -528
- package/dist/Config.js +0 -1712
- package/dist/Mode.d.ts +0 -41
- package/dist/Mode.js +0 -81
- package/dist/Modifier.d.ts +0 -51
- package/dist/Modifier.js +0 -97
- package/dist/MotionDef.d.ts +0 -81
- package/dist/MotionDef.js +0 -212
- package/dist/Props.d.ts +0 -332
- package/dist/Props.js +0 -35
- package/dist/Provider.d.ts +0 -20
- package/dist/Provider.js +0 -14
- package/dist/StyleProp.d.ts +0 -145
- package/dist/StyleProp.js +0 -239
- package/dist/Token.d.ts +0 -76
- package/dist/Token.js +0 -133
- package/dist/TokenGroup.d.ts +0 -33
- package/dist/TokenGroup.js +0 -69
- package/dist/asset-kind.d.ts +0 -55
- package/dist/asset-kind.js +0 -29
- package/dist/asset-value.d.ts +0 -23
- package/dist/asset-value.js +0 -40
- package/dist/brands.d.ts +0 -30
- package/dist/brands.js +0 -20
- package/dist/captureCallerPath.d.ts +0 -48
- package/dist/captureCallerPath.js +0 -95
- package/dist/colorExpressions.d.ts +0 -131
- package/dist/colorExpressions.js +0 -148
- package/dist/component-referrers.d.ts +0 -30
- package/dist/component-referrers.js +0 -40
- package/dist/config-diagnostics.d.ts +0 -21
- package/dist/config-diagnostics.js +0 -12
- package/dist/defineAssetGroup.d.ts +0 -200
- package/dist/defineAssetGroup.js +0 -323
- package/dist/defineProvider.d.ts +0 -29
- package/dist/defineProvider.js +0 -60
- package/dist/element-marker.d.ts +0 -63
- package/dist/element-marker.js +0 -113
- package/dist/entity-utils.d.ts +0 -56
- package/dist/entity-utils.js +0 -105
- package/dist/extension.d.ts +0 -55
- package/dist/extension.js +0 -214
- package/dist/factories.d.ts +0 -863
- package/dist/factories.js +0 -475
- package/dist/font-face.d.ts +0 -25
- package/dist/font-face.js +0 -72
- package/dist/foreign-component-name.d.ts +0 -21
- package/dist/foreign-component-name.js +0 -42
- package/dist/interpolate.d.ts +0 -20
- package/dist/interpolate.js +0 -10
- package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
- package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
- package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
- package/dist/jsx/jsx-dev-runtime.js +0 -11
- package/dist/jsx/jsx-runtime.d.ts +0 -48
- package/dist/jsx/jsx-runtime.js +0 -305
- package/dist/linked-system-pins.d.ts +0 -30
- package/dist/linked-system-pins.js +0 -45
- package/dist/linkedNodePrefixes.d.ts +0 -73
- package/dist/linkedNodePrefixes.js +0 -99
- package/dist/markers.d.ts +0 -235
- package/dist/markers.js +0 -70
- package/dist/motion-constants.d.ts +0 -37
- package/dist/motion-constants.js +0 -61
- package/dist/native/NativeConfig.d.ts +0 -56
- package/dist/native/NativeConfig.js +0 -162
- package/dist/native/assets.d.ts +0 -20
- package/dist/native/assets.js +0 -17
- package/dist/native/components.d.ts +0 -139
- package/dist/native/components.js +0 -67
- package/dist/native/index.d.ts +0 -18
- package/dist/native/index.js +0 -17
- package/dist/native/modes.d.ts +0 -10
- package/dist/native/modes.js +0 -11
- package/dist/native/types.d.ts +0 -95
- package/dist/native/types.js +0 -0
- package/dist/native/validation.d.ts +0 -8
- package/dist/native/validation.js +0 -885
- package/dist/native/values.d.ts +0 -7
- package/dist/native/values.js +0 -15
- package/dist/native.d.ts +0 -12
- package/dist/native.js +0 -10
- package/dist/refs.d.ts +0 -204
- package/dist/refs.js +0 -129
- package/dist/registry-aliases.d.ts +0 -33
- package/dist/registry-aliases.js +0 -35
- package/dist/registry-dir.d.ts +0 -22
- package/dist/registry-dir.js +0 -10
- package/dist/renderer/makeRegistry.d.ts +0 -34
- package/dist/renderer/makeRegistry.js +0 -52
- package/dist/renderer/makeUdsRenderer.d.ts +0 -13
- package/dist/renderer/makeUdsRenderer.js +0 -51
- package/dist/renderer/wrappers/component-slots.d.ts +0 -41
- package/dist/renderer/wrappers/component-slots.js +0 -66
- package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
- package/dist/renderer/wrappers/slot-resolution.js +0 -68
- package/dist/renderer/wrappers/void-elements.d.ts +0 -37
- package/dist/renderer/wrappers/void-elements.js +0 -40
- package/dist/spec/layer-props.d.ts +0 -52
- package/dist/spec/layer-props.js +0 -149
- package/dist/spec/preview-controls.d.ts +0 -44
- package/dist/spec/preview-controls.js +0 -139
- package/dist/spec/slot-refs.d.ts +0 -39
- package/dist/spec/slot-refs.js +0 -56
- package/dist/token-override-rows.d.ts +0 -68
- package/dist/token-override-rows.js +0 -233
- package/dist/tokenValueType.d.ts +0 -34
- package/dist/tokenValueType.js +0 -138
- package/dist/types/css-properties.d.ts +0 -233
- package/dist/types/css-properties.js +0 -14
- package/dist/types/css-property-keywords.d.ts +0 -156
- package/dist/types/css-property-keywords.js +0 -616
- package/dist/types/css-values.d.ts +0 -63
- package/dist/types/css-values.js +0 -16
- package/dist/types.d.ts +0 -1138
- package/dist/types.js +0 -12
- package/dist/units.d.ts +0 -14
- package/dist/units.js +0 -16
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.js +0 -4
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Entity } from "./Entity.js";
|
|
2
|
+
import { RefGraph } from "./ref-graph.js";
|
|
3
|
+
import { EntityKind } from "./registry.js";
|
|
4
|
+
|
|
5
|
+
//#region src/framework/snapshot.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* How each kind reads the edges its own data implies by NAME — `kind` → its `nameEdges`.
|
|
8
|
+
*
|
|
9
|
+
* Kind metadata rather than config state, which is the whole reason a `Snapshot` can hold it: the
|
|
10
|
+
* readers are fixed once a config has registered its kinds, so no edit can make them stale.
|
|
11
|
+
*/
|
|
12
|
+
type NameEdgeReaders = ReadonlyMap<string, NonNullable<EntityKind['nameEdges']>>;
|
|
13
|
+
/** One kind's stored state. Replaced wholesale when the kind changes, shared by reference when not. */
|
|
14
|
+
interface KindSlice {
|
|
15
|
+
/** Items, in insertion order — the list a UI maps over. */
|
|
16
|
+
readonly items: ReadonlyMap<string, Entity>;
|
|
17
|
+
/** GROUP nodes (a folder's own body), keyed by the group prefix. */
|
|
18
|
+
readonly groups: ReadonlyMap<string, Entity>;
|
|
19
|
+
/** Sparse per-member overrides of a DERIVED kind — the only derived data that persists. */
|
|
20
|
+
readonly overrides: ReadonlyMap<string, Record<string, unknown>>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One edit to fold into the next snapshot. `value: undefined` deletes.
|
|
24
|
+
*
|
|
25
|
+
* `target` names WHICH of a kind's three stores is addressed, so a group-update and an item update
|
|
26
|
+
* are the same kind of thing here rather than two code paths.
|
|
27
|
+
*/
|
|
28
|
+
type EntityChange = {
|
|
29
|
+
kind: string;
|
|
30
|
+
target: 'item';
|
|
31
|
+
path: string;
|
|
32
|
+
value: Entity | undefined;
|
|
33
|
+
} | {
|
|
34
|
+
kind: string;
|
|
35
|
+
target: 'group';
|
|
36
|
+
path: string;
|
|
37
|
+
value: Entity | undefined;
|
|
38
|
+
} | {
|
|
39
|
+
kind: string;
|
|
40
|
+
target: 'override';
|
|
41
|
+
path: string;
|
|
42
|
+
value: Record<string, unknown> | undefined;
|
|
43
|
+
};
|
|
44
|
+
declare class Snapshot {
|
|
45
|
+
#private;
|
|
46
|
+
private constructor();
|
|
47
|
+
/**
|
|
48
|
+
* The same snapshot, reading name-borne edges through `readers` from here on.
|
|
49
|
+
*
|
|
50
|
+
* Set once by the `Config` that owns this lineage, from the kinds registered into it — kind
|
|
51
|
+
* METADATA, which no edit changes, so capturing it is safe in a way capturing a config would not
|
|
52
|
+
* be. Every derivation below passes it through.
|
|
53
|
+
*
|
|
54
|
+
* Re-indexes everything currently held, because the readers decide what the edges ARE: adopting
|
|
55
|
+
* them without a rebuild would leave items loaded before this call with ref-borne edges only.
|
|
56
|
+
*/
|
|
57
|
+
withNameEdges(readers: NameEdgeReaders, linkKinds?: readonly string[], singletonKinds?: readonly string[]): Snapshot;
|
|
58
|
+
/** The empty snapshot — what a freshly constructed config starts from. */
|
|
59
|
+
static empty(): Snapshot;
|
|
60
|
+
/**
|
|
61
|
+
* A snapshot's per-kind slice. Its IDENTITY is stable across any mutation that didn't touch this
|
|
62
|
+
* kind — that stability is the contract callers memoize on.
|
|
63
|
+
*/
|
|
64
|
+
slice(kind: string): KindSlice;
|
|
65
|
+
get(kind: string, path: string): Entity | undefined;
|
|
66
|
+
has(kind: string, path: string): boolean;
|
|
67
|
+
values(kind: string): Entity[];
|
|
68
|
+
group(kind: string, path: string): Entity | undefined;
|
|
69
|
+
groups(kind: string): ReadonlyMap<string, Entity>;
|
|
70
|
+
overrides(kind: string): ReadonlyMap<string, Record<string, unknown>>;
|
|
71
|
+
/** Every kind holding at least one item. Groups alone don't count — matching `ItemStore.kinds()`. */
|
|
72
|
+
kinds(): string[];
|
|
73
|
+
/** Every ref in this snapshot, indexed both ways. Built once per snapshot, lazily — most
|
|
74
|
+
* mutations never ask, and the index itself was already carried forward incrementally. */
|
|
75
|
+
get refs(): RefGraph;
|
|
76
|
+
/**
|
|
77
|
+
* The next snapshot. Only the kinds named in `changes` get new slices; every other slice is passed
|
|
78
|
+
* through by reference, which is both the structural sharing and the cache-invalidation signal.
|
|
79
|
+
*/
|
|
80
|
+
withChanges(changes: readonly EntityChange[]): Snapshot;
|
|
81
|
+
/**
|
|
82
|
+
* Move an entity to a new path, KEEPING ITS POSITION in the record.
|
|
83
|
+
*
|
|
84
|
+
* Order is key order — from the authored object literal, through the serialized artifact, into the
|
|
85
|
+
* emitted CSS — so where a key sits is meaning, not incidental. A delete-then-set would put the
|
|
86
|
+
* renamed entity at the end: a renamed token drops to the bottom of its group, and a renamed group
|
|
87
|
+
* (which is its members' shared prefix) drops to the bottom of the rail.
|
|
88
|
+
*
|
|
89
|
+
* So the map is rebuilt in order with the key swapped in place. A rename ONTO an existing key
|
|
90
|
+
* collapses onto that key's slot, which is the only sensible reading — there is one key afterwards,
|
|
91
|
+
* so there is one position.
|
|
92
|
+
*/
|
|
93
|
+
withRenamed(kind: string, target: 'item' | 'group', from: string, to: string, value: Entity): Snapshot;
|
|
94
|
+
/**
|
|
95
|
+
* Rearrange a record's keys — the operation that MOVES something, since order is key order.
|
|
96
|
+
*
|
|
97
|
+
* The named keys are permuted among **the slots they already occupy**, and everything unnamed stays
|
|
98
|
+
* exactly where it is. That is what makes a partial order safe: a drag inside one group names only
|
|
99
|
+
* that group's entries, and reordering them must not shuffle a neighbouring group past a third one.
|
|
100
|
+
* For a full order — every key named — this is simply that order.
|
|
101
|
+
*
|
|
102
|
+
* A name that is no longer present is skipped rather than refused. A reorder is replayed after the
|
|
103
|
+
* patches before it, one of which may have deleted something this one names; rejecting would make the
|
|
104
|
+
* whole patch undroppable for a reason that has nothing to do with what it was trying to do.
|
|
105
|
+
*/
|
|
106
|
+
withOrder(kind: string, target: 'item' | 'group', order: readonly string[]): Snapshot;
|
|
107
|
+
/** The wire form the config serializes from — `{ items, groups, overrides }` per kind. */
|
|
108
|
+
toJSON(): {
|
|
109
|
+
items: Record<string, Record<string, unknown>>;
|
|
110
|
+
groups: Record<string, Record<string, unknown>>;
|
|
111
|
+
overrides: Record<string, Record<string, Record<string, unknown>>>;
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { EntityChange, KindSlice, Snapshot };
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { buildRefIndex, refGraphOf, updateRefIndex } from "./ref-graph.js";
|
|
2
|
+
//#region src/framework/snapshot.ts
|
|
3
|
+
/** Whether two link-kind lists say the same thing — the other half of `withNameEdges`' short-circuit. */
|
|
4
|
+
function sameKinds(left, right) {
|
|
5
|
+
return left.length === right.length && left.every((k, i) => k === right[i]);
|
|
6
|
+
}
|
|
7
|
+
/** Whether two reader maps say the same thing — the identity check that keeps `withNameEdges` free
|
|
8
|
+
* on the path where a config registers content into kinds it already declared. */
|
|
9
|
+
function sameReaders(left, right) {
|
|
10
|
+
if (left === right) return true;
|
|
11
|
+
if (left.size !== right.size) return false;
|
|
12
|
+
for (const [kind, read] of left) if (right.get(kind) !== read) return false;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
const emptySlice = () => Object.freeze({
|
|
16
|
+
items: /* @__PURE__ */ new Map(),
|
|
17
|
+
groups: /* @__PURE__ */ new Map(),
|
|
18
|
+
overrides: /* @__PURE__ */ new Map()
|
|
19
|
+
});
|
|
20
|
+
/** Apply one change to a mutable draft of a slice. */
|
|
21
|
+
function applyToSlice(draft, change) {
|
|
22
|
+
let store;
|
|
23
|
+
if (change.target === "item") store = draft.items;
|
|
24
|
+
else if (change.target === "group") store = draft.groups;
|
|
25
|
+
else store = draft.overrides;
|
|
26
|
+
if (change.value === void 0) store.delete(change.path);
|
|
27
|
+
else store.set(change.path, change.value);
|
|
28
|
+
}
|
|
29
|
+
var Snapshot = class Snapshot {
|
|
30
|
+
#nameEdges;
|
|
31
|
+
/** The kinds a `@slug` resolves against — see `edgesOf`. Kind metadata, captured with the readers
|
|
32
|
+
* and for the same reason: no edit can change it. */
|
|
33
|
+
#linkKinds;
|
|
34
|
+
/** The kinds whose one item a ref may address by field path — see `edgesOf`. Kind metadata, as
|
|
35
|
+
* `#linkKinds` is. */
|
|
36
|
+
#singletonKinds;
|
|
37
|
+
#slices;
|
|
38
|
+
#refIndex;
|
|
39
|
+
/** Canonical empty slices for kinds this snapshot holds nothing of, so `slice()` is identity-stable
|
|
40
|
+
* for them too. Shared along a LINEAGE (derived snapshots inherit the map) but never across
|
|
41
|
+
* independent configs — a global singleton would make two unrelated configs that both lack a kind
|
|
42
|
+
* collide on one memo key, and each would serve the other's cached result. */
|
|
43
|
+
#empties;
|
|
44
|
+
#graph;
|
|
45
|
+
constructor(slices, refIndex, empties, nameEdges = /* @__PURE__ */ new Map(), linkKinds = [], singletonKinds = []) {
|
|
46
|
+
this.#slices = slices;
|
|
47
|
+
this.#refIndex = refIndex;
|
|
48
|
+
this.#empties = empties;
|
|
49
|
+
this.#nameEdges = nameEdges;
|
|
50
|
+
this.#linkKinds = linkKinds;
|
|
51
|
+
this.#singletonKinds = singletonKinds;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The same snapshot, reading name-borne edges through `readers` from here on.
|
|
55
|
+
*
|
|
56
|
+
* Set once by the `Config` that owns this lineage, from the kinds registered into it — kind
|
|
57
|
+
* METADATA, which no edit changes, so capturing it is safe in a way capturing a config would not
|
|
58
|
+
* be. Every derivation below passes it through.
|
|
59
|
+
*
|
|
60
|
+
* Re-indexes everything currently held, because the readers decide what the edges ARE: adopting
|
|
61
|
+
* them without a rebuild would leave items loaded before this call with ref-borne edges only.
|
|
62
|
+
*/
|
|
63
|
+
withNameEdges(readers, linkKinds = [], singletonKinds = []) {
|
|
64
|
+
if (sameReaders(this.#nameEdges, readers) && sameKinds(this.#linkKinds, linkKinds) && sameKinds(this.#singletonKinds, singletonKinds)) return this;
|
|
65
|
+
const entries = [];
|
|
66
|
+
for (const [kind, slice] of this.#slices) {
|
|
67
|
+
const read = readers.get(kind);
|
|
68
|
+
for (const [path, entity] of slice.items) {
|
|
69
|
+
const data = entity.toJSON();
|
|
70
|
+
entries.push({
|
|
71
|
+
ref: `${kind}:${path}`,
|
|
72
|
+
data,
|
|
73
|
+
extra: read?.(data)
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
for (const [path, entity] of slice.groups) {
|
|
77
|
+
const data = entity.toJSON();
|
|
78
|
+
entries.push({
|
|
79
|
+
ref: `${kind}:${path}`,
|
|
80
|
+
data,
|
|
81
|
+
extra: read?.(data)
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return new Snapshot(this.#slices, buildRefIndex(entries, linkKinds, singletonKinds), this.#empties, readers, linkKinds, singletonKinds);
|
|
86
|
+
}
|
|
87
|
+
/** The empty snapshot — what a freshly constructed config starts from. */
|
|
88
|
+
static empty() {
|
|
89
|
+
return new Snapshot(/* @__PURE__ */ new Map(), buildRefIndex([]), /* @__PURE__ */ new Map());
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A snapshot's per-kind slice. Its IDENTITY is stable across any mutation that didn't touch this
|
|
93
|
+
* kind — that stability is the contract callers memoize on.
|
|
94
|
+
*/
|
|
95
|
+
slice(kind) {
|
|
96
|
+
const found = this.#slices.get(kind);
|
|
97
|
+
if (found) return found;
|
|
98
|
+
let empty = this.#empties.get(kind);
|
|
99
|
+
if (!empty) {
|
|
100
|
+
empty = emptySlice();
|
|
101
|
+
this.#empties.set(kind, empty);
|
|
102
|
+
}
|
|
103
|
+
return empty;
|
|
104
|
+
}
|
|
105
|
+
get(kind, path) {
|
|
106
|
+
return this.#slices.get(kind)?.items.get(path);
|
|
107
|
+
}
|
|
108
|
+
has(kind, path) {
|
|
109
|
+
return this.#slices.get(kind)?.items.has(path) ?? false;
|
|
110
|
+
}
|
|
111
|
+
values(kind) {
|
|
112
|
+
return [...this.#slices.get(kind)?.items.values() ?? []];
|
|
113
|
+
}
|
|
114
|
+
group(kind, path) {
|
|
115
|
+
return this.#slices.get(kind)?.groups.get(path);
|
|
116
|
+
}
|
|
117
|
+
groups(kind) {
|
|
118
|
+
return this.slice(kind).groups;
|
|
119
|
+
}
|
|
120
|
+
overrides(kind) {
|
|
121
|
+
return this.slice(kind).overrides;
|
|
122
|
+
}
|
|
123
|
+
/** Every kind holding at least one item. Groups alone don't count — matching `ItemStore.kinds()`. */
|
|
124
|
+
kinds() {
|
|
125
|
+
const out = [];
|
|
126
|
+
for (const [kind, slice] of this.#slices) if (slice.items.size > 0) out.push(kind);
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
/** Every ref in this snapshot, indexed both ways. Built once per snapshot, lazily — most
|
|
130
|
+
* mutations never ask, and the index itself was already carried forward incrementally. */
|
|
131
|
+
get refs() {
|
|
132
|
+
this.#graph ??= refGraphOf(this.#refIndex);
|
|
133
|
+
return this.#graph;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The next snapshot. Only the kinds named in `changes` get new slices; every other slice is passed
|
|
137
|
+
* through by reference, which is both the structural sharing and the cache-invalidation signal.
|
|
138
|
+
*/
|
|
139
|
+
withChanges(changes) {
|
|
140
|
+
if (changes.length === 0) return this;
|
|
141
|
+
const byKind = /* @__PURE__ */ new Map();
|
|
142
|
+
for (const change of changes) {
|
|
143
|
+
const list = byKind.get(change.kind);
|
|
144
|
+
if (list) list.push(change);
|
|
145
|
+
else byKind.set(change.kind, [change]);
|
|
146
|
+
}
|
|
147
|
+
const slices = new Map(this.#slices);
|
|
148
|
+
for (const [kind, kindChanges] of byKind) {
|
|
149
|
+
const current = this.slice(kind);
|
|
150
|
+
const draft = {
|
|
151
|
+
items: new Map(current.items),
|
|
152
|
+
groups: new Map(current.groups),
|
|
153
|
+
overrides: new Map(current.overrides)
|
|
154
|
+
};
|
|
155
|
+
for (const change of kindChanges) applyToSlice(draft, change);
|
|
156
|
+
slices.set(kind, Object.freeze(draft));
|
|
157
|
+
}
|
|
158
|
+
return new Snapshot(slices, updateRefIndex(this.#refIndex, refChanges(changes, this.#nameEdges), this.#linkKinds, this.#singletonKinds), this.#empties, this.#nameEdges, this.#linkKinds, this.#singletonKinds);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Move an entity to a new path, KEEPING ITS POSITION in the record.
|
|
162
|
+
*
|
|
163
|
+
* Order is key order — from the authored object literal, through the serialized artifact, into the
|
|
164
|
+
* emitted CSS — so where a key sits is meaning, not incidental. A delete-then-set would put the
|
|
165
|
+
* renamed entity at the end: a renamed token drops to the bottom of its group, and a renamed group
|
|
166
|
+
* (which is its members' shared prefix) drops to the bottom of the rail.
|
|
167
|
+
*
|
|
168
|
+
* So the map is rebuilt in order with the key swapped in place. A rename ONTO an existing key
|
|
169
|
+
* collapses onto that key's slot, which is the only sensible reading — there is one key afterwards,
|
|
170
|
+
* so there is one position.
|
|
171
|
+
*/
|
|
172
|
+
withRenamed(kind, target, from, to, value) {
|
|
173
|
+
const current = this.slice(kind);
|
|
174
|
+
const store = target === "item" ? current.items : current.groups;
|
|
175
|
+
if (!store.has(from)) return this;
|
|
176
|
+
const rebuilt = /* @__PURE__ */ new Map();
|
|
177
|
+
for (const [path, entity] of store) if (path === from) rebuilt.set(to, value);
|
|
178
|
+
else if (path !== to) rebuilt.set(path, entity);
|
|
179
|
+
const slices = new Map(this.#slices);
|
|
180
|
+
slices.set(kind, Object.freeze({
|
|
181
|
+
...current,
|
|
182
|
+
[target === "item" ? "items" : "groups"]: rebuilt
|
|
183
|
+
}));
|
|
184
|
+
return new Snapshot(slices, updateRefIndex(this.#refIndex, [{
|
|
185
|
+
ref: `${kind}:${from}`,
|
|
186
|
+
data: void 0
|
|
187
|
+
}, {
|
|
188
|
+
ref: `${kind}:${to}`,
|
|
189
|
+
data: value.toJSON(),
|
|
190
|
+
extra: this.#nameEdges.get(kind)?.(value.toJSON())
|
|
191
|
+
}], this.#linkKinds, this.#singletonKinds), this.#empties, this.#nameEdges, this.#linkKinds, this.#singletonKinds);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Rearrange a record's keys — the operation that MOVES something, since order is key order.
|
|
195
|
+
*
|
|
196
|
+
* The named keys are permuted among **the slots they already occupy**, and everything unnamed stays
|
|
197
|
+
* exactly where it is. That is what makes a partial order safe: a drag inside one group names only
|
|
198
|
+
* that group's entries, and reordering them must not shuffle a neighbouring group past a third one.
|
|
199
|
+
* For a full order — every key named — this is simply that order.
|
|
200
|
+
*
|
|
201
|
+
* A name that is no longer present is skipped rather than refused. A reorder is replayed after the
|
|
202
|
+
* patches before it, one of which may have deleted something this one names; rejecting would make the
|
|
203
|
+
* whole patch undroppable for a reason that has nothing to do with what it was trying to do.
|
|
204
|
+
*/
|
|
205
|
+
withOrder(kind, target, order) {
|
|
206
|
+
const current = this.slice(kind);
|
|
207
|
+
const store = target === "item" ? current.items : current.groups;
|
|
208
|
+
const moving = order.filter((path) => store.has(path));
|
|
209
|
+
if (moving.length === 0) return this;
|
|
210
|
+
const slots = [];
|
|
211
|
+
const keys = [...store.keys()];
|
|
212
|
+
keys.forEach((path, index) => {
|
|
213
|
+
if (moving.includes(path)) slots.push(index);
|
|
214
|
+
});
|
|
215
|
+
const redealt = [...keys];
|
|
216
|
+
slots.forEach((slot, i) => {
|
|
217
|
+
const path = moving[i];
|
|
218
|
+
if (path !== void 0) redealt[slot] = path;
|
|
219
|
+
});
|
|
220
|
+
const rebuilt = /* @__PURE__ */ new Map();
|
|
221
|
+
for (const path of redealt) {
|
|
222
|
+
const entity = store.get(path);
|
|
223
|
+
if (entity) rebuilt.set(path, entity);
|
|
224
|
+
}
|
|
225
|
+
const slices = new Map(this.#slices);
|
|
226
|
+
slices.set(kind, Object.freeze({
|
|
227
|
+
...current,
|
|
228
|
+
[target === "item" ? "items" : "groups"]: rebuilt
|
|
229
|
+
}));
|
|
230
|
+
return new Snapshot(slices, this.#refIndex, this.#empties, this.#nameEdges, this.#linkKinds, this.#singletonKinds);
|
|
231
|
+
}
|
|
232
|
+
/** The wire form the config serializes from — `{ items, groups, overrides }` per kind. */
|
|
233
|
+
toJSON() {
|
|
234
|
+
const items = {};
|
|
235
|
+
const groups = {};
|
|
236
|
+
const overrides = {};
|
|
237
|
+
for (const [kind, slice] of this.#slices) {
|
|
238
|
+
if (slice.items.size) {
|
|
239
|
+
items[kind] = {};
|
|
240
|
+
for (const [path, entity] of slice.items) items[kind][path] = entity.toJSON();
|
|
241
|
+
}
|
|
242
|
+
if (slice.groups.size) {
|
|
243
|
+
groups[kind] = {};
|
|
244
|
+
for (const [path, entity] of slice.groups) groups[kind][path] = entity.toJSON();
|
|
245
|
+
}
|
|
246
|
+
if (slice.overrides.size) overrides[kind] = Object.fromEntries(slice.overrides);
|
|
247
|
+
}
|
|
248
|
+
return {
|
|
249
|
+
items,
|
|
250
|
+
groups,
|
|
251
|
+
overrides
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* The ref-index edits a batch of entity changes implies.
|
|
257
|
+
*
|
|
258
|
+
* Items and GROUP nodes both hold refs (an icon library names the component its icons render
|
|
259
|
+
* through), and a group ref is the same `kind:path` shape as an item's — so both are ordinary nodes
|
|
260
|
+
* in the graph. A group path is a strict PREFIX of its items' paths, so the two never collide on one
|
|
261
|
+
* key. Overrides are sparse field patches on a derived kind and contribute no edges.
|
|
262
|
+
*/
|
|
263
|
+
function refChanges(changes, nameEdges) {
|
|
264
|
+
const out = [];
|
|
265
|
+
for (const change of changes) {
|
|
266
|
+
if (change.target === "override") continue;
|
|
267
|
+
const data = change.value?.toJSON();
|
|
268
|
+
out.push({
|
|
269
|
+
ref: `${change.kind}:${change.path}`,
|
|
270
|
+
data,
|
|
271
|
+
extra: data === void 0 ? void 0 : nameEdges.get(change.kind)?.(data)
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
export { Snapshot };
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { LocalOverlay } from "./sources.js";
|
|
2
|
+
import { Config } from "./Config.js";
|
|
3
|
+
|
|
4
|
+
//#region src/framework/source-integrity.d.ts
|
|
5
|
+
/** One ref that names something its source does not have. */
|
|
6
|
+
interface DanglingRef {
|
|
7
|
+
/** The entity holding the ref — `token:color/primary`. */
|
|
8
|
+
from: string;
|
|
9
|
+
/** The ref itself — `token:brand/cores@ds`. */
|
|
10
|
+
ref: string;
|
|
11
|
+
/** The link it points through. */
|
|
12
|
+
slug: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Every `@source` ref in `config` that does not resolve against its attached source.
|
|
16
|
+
*
|
|
17
|
+
* This is the guarantee the emitted types can only approximate. A union narrows what an author can type, but
|
|
18
|
+
* nothing types a Studio-authored patch, a js consumer, or a config whose source moved on since the last
|
|
19
|
+
* install — and an unresolvable ref renders as the empty string, so the stylesheet gets `--x: ;`: syntactically
|
|
20
|
+
* a declaration, semantically nothing, and silent. Precisely the failure mode a build should refuse.
|
|
21
|
+
*
|
|
22
|
+
* Only sourced refs are checked here. A dangling local ref is the dependency graph's own complaint and has its
|
|
23
|
+
* own reporting; this is about the seam between systems, where the other side can change without us.
|
|
24
|
+
*
|
|
25
|
+
* Walks what this config authored, not what it currently resolves to, and the difference is two bugs
|
|
26
|
+
* rather than a nicety. Resolution loses the subject in both directions:
|
|
27
|
+
*
|
|
28
|
+
* • An extension whose base cannot be found resolves to nothing, so the item drops out of `list` and
|
|
29
|
+
* the broken ref goes unreported — a build passing on a config whose token has silently vanished.
|
|
30
|
+
* That is the case a `Token.ref('palette@ds')` naming a group produces, since a group is not an
|
|
31
|
+
* item and the lookup misses.
|
|
32
|
+
* • An extension that can be found resolves to its source's fields merged over ours, so the walk sees
|
|
33
|
+
* the source's refs through the source's slugs. A source that itself borrows made this config
|
|
34
|
+
* report `@upstream` — a slug it never declared and cannot resolve — and refuse a legitimate chain.
|
|
35
|
+
*
|
|
36
|
+
* The authored body has neither problem: it is exactly the set of refs this config is answerable for.
|
|
37
|
+
*/
|
|
38
|
+
declare function danglingSourcedRefs(config: Config): DanglingRef[];
|
|
39
|
+
/** One borrow whose body this config's own kind refuses. */
|
|
40
|
+
interface UnreadableBorrow {
|
|
41
|
+
/** The entity holding it — `modifier:pressed`. */
|
|
42
|
+
from: string;
|
|
43
|
+
/** The pointer it is stored as — `modifier:pressed@mobile-demo`. */
|
|
44
|
+
ref: string;
|
|
45
|
+
/** The link it points through. */
|
|
46
|
+
slug: string;
|
|
47
|
+
/** Which fields crossed badly, and what that means — {@link Config.canBorrow}'s own sentence. */
|
|
48
|
+
error: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Every extended borrow whose merged body this config's kind will not parse.
|
|
52
|
+
*
|
|
53
|
+
* The third way a link can be broken, and the only one that is nobody's mistake: the source resolved
|
|
54
|
+
* perfectly and said something this config has no way to hold. Two config types need not share a
|
|
55
|
+
* value domain — a native modifier activates on `{ state: 'pressed' }` where a web one takes a CSS
|
|
56
|
+
* fragment, a mode, a composite or a list of modes — so the same kind string can name two shapes
|
|
57
|
+
* neither of which contains the other. `mobile-app`'s `size/control` is the same crossing answered
|
|
58
|
+
* rather than broken: `1rem` has no arm in `NativeToken`, and the local `extend: { value: 16 }` is
|
|
59
|
+
* what makes the merged body legal.
|
|
60
|
+
*
|
|
61
|
+
* A report rather than a throw. Reads answer "nothing" for
|
|
62
|
+
* a row they cannot express, because they must: `list`, `sourceClosure` and `toJSON` all reach stored
|
|
63
|
+
* rows, and a throw from inside serialization has no caller in a position to catch it. So the refusal
|
|
64
|
+
* has to live somewhere a caller asks, which is here — a build refuses on it, and a surface says which
|
|
65
|
+
* Entity and which field.
|
|
66
|
+
*
|
|
67
|
+
* Walks what this config authored, for the reason {@link danglingSourcedRefs} does: a row that fails
|
|
68
|
+
* to resolve is absent from `list`, so a walk over resolved entities is a walk with the subject
|
|
69
|
+
* already removed from it.
|
|
70
|
+
*/
|
|
71
|
+
declare function unreadableBorrows(config: Config): UnreadableBorrow[];
|
|
72
|
+
/** One ref spelled through a link at an entity this config already names locally. */
|
|
73
|
+
interface RedundantQualifier {
|
|
74
|
+
/** The entity holding the ref — `token:color/brand`, or `token group:palette`. */
|
|
75
|
+
from: string;
|
|
76
|
+
/** The ref as written — `token:palette/violet@ds`. */
|
|
77
|
+
ref: string;
|
|
78
|
+
/** The link it points through. */
|
|
79
|
+
slug: string;
|
|
80
|
+
/** The spelling that names the same entity — `token:palette/violet`. */
|
|
81
|
+
local: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Every sourced ref whose target this config already holds at that path, so the qualifier says
|
|
85
|
+
* nothing the bare path doesn't.
|
|
86
|
+
*
|
|
87
|
+
* A link brings a row per entity it takes, at the path the source spells it, so after the build
|
|
88
|
+
* `token:palette/violet` and `token:palette/violet@ds` are one entity with two names. Two spellings
|
|
89
|
+
* for one thing is what this refuses. It reads as harmless and isn't: the qualified form resolves
|
|
90
|
+
* through the seam, so it breaks the moment the pin is retargeted or dropped while the bare form
|
|
91
|
+
* follows the row wherever it goes, and a config with both in it has half its references surviving the
|
|
92
|
+
* pin's deletion.
|
|
93
|
+
*
|
|
94
|
+
* The one qualified spelling that stays is an entity pointer — `Token.ref('violet@ds').extend({ … })`
|
|
95
|
+
* stored as the row's own body, and a linked folder's `ref`. Both are authored at the local key the
|
|
96
|
+
* bare form would name, so there is nothing else they could say. Everything below that key is a value
|
|
97
|
+
* pointing at another entity, and that is what this walks.
|
|
98
|
+
*
|
|
99
|
+
* A row the pin declares is the subject, never one reachability derived. `sourceClosure` seeds from
|
|
100
|
+
* this config's own refs too, so a hand-written borrow with no `link` declaration derives a row at its
|
|
101
|
+
* target — and telling that author to drop the qualifier would delete the only reason the row exists,
|
|
102
|
+
* leaving a bare ref pointing at nothing. Hence {@link Config.adoptedFrom}: what stands without the
|
|
103
|
+
* ref asking.
|
|
104
|
+
*
|
|
105
|
+
* Walks what this config authored, for the reason {@link danglingSourcedRefs} does — a resolved
|
|
106
|
+
* borrow carries its source's refs through its source's slugs, none of which this config wrote.
|
|
107
|
+
*/
|
|
108
|
+
declare function redundantQualifiers(config: Config): RedundantQualifier[];
|
|
109
|
+
/** A verb the pin declared that the source disagrees with. */
|
|
110
|
+
interface MisdeclaredOverlay {
|
|
111
|
+
slug: string;
|
|
112
|
+
kind: string;
|
|
113
|
+
/** The path as the source spells it. */
|
|
114
|
+
path: string;
|
|
115
|
+
/** The verb the pin used. */
|
|
116
|
+
declared: 'override' | 'extend';
|
|
117
|
+
/** The field it was wrong about, addressed from the entity body as segments. */
|
|
118
|
+
field: readonly string[];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* A leaf address: dotted, or spelled as segments where a member key can itself contain a dot (a
|
|
122
|
+
* compound condition like `dark.lg` is one key under `overrides`).
|
|
123
|
+
*/
|
|
124
|
+
type LeafAddress = string | readonly string[];
|
|
125
|
+
/** Every leaf address under `body`, as segments, so a member key that contains a dot stays one key. */
|
|
126
|
+
declare function leafAddresses(body: unknown): (readonly string[])[];
|
|
127
|
+
/** The value at a leaf address, or `undefined` where the body has none. A ref is one value, not walked into. */
|
|
128
|
+
declare function valueAt(body: unknown, field: LeafAddress): unknown;
|
|
129
|
+
/** The two things a local leaf can be to the source: a value it defines, replaced, or one it lacks, added. */
|
|
130
|
+
type OverlayVerb = 'override' | 'extend';
|
|
131
|
+
/**
|
|
132
|
+
* The verb one local leaf is against the source's value at the same address: `extend` where the
|
|
133
|
+
* source has nothing there, `override` where it has something different, and `undefined` where
|
|
134
|
+
* nothing local sits there or the two agree. A leaf carried along unchanged is not overlaid: a sub-op
|
|
135
|
+
* copies the whole record it touched into the delta, so a token given one local condition holds the
|
|
136
|
+
* source's other conditions beside it.
|
|
137
|
+
*/
|
|
138
|
+
declare function leafVerb({
|
|
139
|
+
ours,
|
|
140
|
+
theirs
|
|
141
|
+
}: {
|
|
142
|
+
ours: unknown;
|
|
143
|
+
theirs: unknown;
|
|
144
|
+
}): OverlayVerb | undefined;
|
|
145
|
+
/**
|
|
146
|
+
* Which verb this config's value at `field` is, in the pin's vocabulary — `override` where the source
|
|
147
|
+
* defines the leaf, `extend` where it does not — and `undefined` where nothing local sits there. A
|
|
148
|
+
* record field answers `override` when any member under it does, else `extend` when any was added.
|
|
149
|
+
*/
|
|
150
|
+
declare function overlayVerb(overlay: LocalOverlay, field: LeafAddress): OverlayVerb | undefined;
|
|
151
|
+
/**
|
|
152
|
+
* Every overlay whose verb the source disagrees with — an `extend` at a field they already define, or
|
|
153
|
+
* an `override` at one they do not.
|
|
154
|
+
*
|
|
155
|
+
* The verb is derivable, and this is the derivation. It runs anyway because a declared verb is the
|
|
156
|
+
* only thing that notices the source moving: a field they add in a later version turns an extension
|
|
157
|
+
* into an override, and without the declaration there is nothing for that to contradict. The same
|
|
158
|
+
* check catches the first-order mistake, which is writing an extension for something they already had.
|
|
159
|
+
*
|
|
160
|
+
* Judged leaf by leaf, because one entity legitimately carries both — a token overridden under one
|
|
161
|
+
* modifier and extended under another is one body with two verbs, and a whole-entity comparison would
|
|
162
|
+
* have to call it one or the other.
|
|
163
|
+
*/
|
|
164
|
+
declare function misdeclaredOverlays(config: Config): MisdeclaredOverlay[];
|
|
165
|
+
/** A directive aimed at a path whose kind the pin never adopted. */
|
|
166
|
+
interface UnadoptedDirective {
|
|
167
|
+
slug: string;
|
|
168
|
+
kind: string;
|
|
169
|
+
path: string;
|
|
170
|
+
/** Which act the pin declared there. */
|
|
171
|
+
act: 'hide';
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Every hide the pin aims at a kind it does not adopt.
|
|
175
|
+
*
|
|
176
|
+
* A hide takes a name back, and a config that never adopted the kind never had it: their entity is
|
|
177
|
+
* reachable only qualified either way, so the entry changes nothing and reads as though it did.
|
|
178
|
+
* Reported rather than ignored, because the fix is usually the missing adoption.
|
|
179
|
+
*
|
|
180
|
+
* An overlay on an unadopted path is a different question and is not this one — it would be laid over
|
|
181
|
+
* a row that is never minted, which is worth reporting too, but the message is about a body rather
|
|
182
|
+
* than about a name.
|
|
183
|
+
*/
|
|
184
|
+
declare function unadoptedDirectives(config: Config): UnadoptedDirective[];
|
|
185
|
+
/** A directive whose accessor or path reaches nothing. */
|
|
186
|
+
interface DanglingDirective {
|
|
187
|
+
slug: string;
|
|
188
|
+
/** The accessor as written — this config may have no kind under it. */
|
|
189
|
+
accessor: string;
|
|
190
|
+
path: string;
|
|
191
|
+
/** `accessor` when no kind is registered under that name, `path` when the source has no such entity. */
|
|
192
|
+
missing: 'accessor' | 'path';
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Every directive aimed at nothing — an accessor this config has no kind for, or a path the source
|
|
196
|
+
* does not have.
|
|
197
|
+
*
|
|
198
|
+
* The one mistake the other checks structurally cannot see. Each of them answers for a path it is
|
|
199
|
+
* already holding, so it asks "does the declaration mention this one" — and a name nobody has is
|
|
200
|
+
* never a question anyone puts. `toknes` and `palette/nope` both simply cover nothing, silently, and
|
|
201
|
+
* an overlay that covers nothing looks exactly like one that was never needed.
|
|
202
|
+
*
|
|
203
|
+
* Also what notices the source dropping a path. A directive written against an entity a later version
|
|
204
|
+
* removed keeps parsing and keeps doing nothing, which is the same failure the declared verb exists to
|
|
205
|
+
* catch one level down.
|
|
206
|
+
*/
|
|
207
|
+
declare function danglingDirectives(config: Config): DanglingDirective[];
|
|
208
|
+
/** A borrowed token whose conditional value names a modifier this config does not declare. */
|
|
209
|
+
interface UnstatableCondition {
|
|
210
|
+
slug: string;
|
|
211
|
+
/** The source's token path. */
|
|
212
|
+
token: string;
|
|
213
|
+
/** The modifier its override names. */
|
|
214
|
+
modifier: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Every borrowed token that varies under a modifier this config does not declare.
|
|
218
|
+
*
|
|
219
|
+
* A borrowed token's conditional values apply under your modifier of that name — so if you don't have the
|
|
220
|
+
* name, the condition is unstatable and the token silently behaves like a lesser version of itself: one
|
|
221
|
+
* colour where the source had two. Refusing is the same rule inlining already enforces; this is the other
|
|
222
|
+
* path to the same place, for a token a consumer references directly rather than one that got inlined.
|
|
223
|
+
*/
|
|
224
|
+
declare function unstatableConditions(config: Config): UnstatableCondition[];
|
|
225
|
+
//#endregion
|
|
226
|
+
export { DanglingDirective, DanglingRef, LeafAddress, MisdeclaredOverlay, OverlayVerb, RedundantQualifier, UnadoptedDirective, UnreadableBorrow, UnstatableCondition, danglingDirectives, danglingSourcedRefs, leafAddresses, leafVerb, misdeclaredOverlays, overlayVerb, redundantQualifiers, unadoptedDirectives, unreadableBorrows, unstatableConditions, valueAt };
|