@yahoo/uds-create-config 2.44.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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
|
@@ -1,885 +0,0 @@
|
|
|
1
|
-
import { isAssetRef, isTokenRef } from "../refs.js";
|
|
2
|
-
import { isMixExpr } from "../colorExpressions.js";
|
|
3
|
-
import { EXACT_SEMVER_RE, UUID_RE } from "../linked-system-pins.js";
|
|
4
|
-
import { createModeBackedModifierLookup, modifierTreeToOverrideRows, resolveOverrideRow } from "../token-override-rows.js";
|
|
5
|
-
import { isOperatingSystemValue } from "./values.js";
|
|
6
|
-
import { validRange } from "semver";
|
|
7
|
-
//#region src/native/validation.ts
|
|
8
|
-
const TOP_LEVEL_KEYS = new Set([
|
|
9
|
-
"schemaVersion",
|
|
10
|
-
"platform",
|
|
11
|
-
"builtAt",
|
|
12
|
-
"namespace",
|
|
13
|
-
"styleEngine",
|
|
14
|
-
"buildOptions",
|
|
15
|
-
"dependencyPolicy",
|
|
16
|
-
"defaultModes",
|
|
17
|
-
"modes",
|
|
18
|
-
"tokenGroups",
|
|
19
|
-
"assetGroups",
|
|
20
|
-
"components",
|
|
21
|
-
"componentGroups",
|
|
22
|
-
"linkedSystems"
|
|
23
|
-
]);
|
|
24
|
-
const LINKED_SYSTEM_PIN_KEYS = new Set(["name", "version"]);
|
|
25
|
-
const BUILD_OPTIONS_KEYS = new Set(["componentsDir"]);
|
|
26
|
-
const DEPENDENCY_POLICY_KEYS = new Set(["providedBy", "version"]);
|
|
27
|
-
const COMPONENT_KEYS = new Set([
|
|
28
|
-
"id",
|
|
29
|
-
"layers",
|
|
30
|
-
"props",
|
|
31
|
-
"defaultProps",
|
|
32
|
-
"styles",
|
|
33
|
-
"label",
|
|
34
|
-
"description"
|
|
35
|
-
]);
|
|
36
|
-
const COMPONENT_CONFIG_KEYS = new Set([
|
|
37
|
-
"base",
|
|
38
|
-
"variants",
|
|
39
|
-
"booleans",
|
|
40
|
-
"runtimeStates",
|
|
41
|
-
"values",
|
|
42
|
-
"description"
|
|
43
|
-
]);
|
|
44
|
-
const LAYER_KEYS = new Set(["kind", "styleProp"]);
|
|
45
|
-
const COMPONENT_GROUP_KEYS = new Set([
|
|
46
|
-
"components",
|
|
47
|
-
"label",
|
|
48
|
-
"description"
|
|
49
|
-
]);
|
|
50
|
-
const GROUP_KEYS = new Set([
|
|
51
|
-
"tokens",
|
|
52
|
-
"label",
|
|
53
|
-
"description"
|
|
54
|
-
]);
|
|
55
|
-
const ASSET_GROUP_KEYS = new Set([
|
|
56
|
-
"assetKind",
|
|
57
|
-
"members",
|
|
58
|
-
"label",
|
|
59
|
-
"description"
|
|
60
|
-
]);
|
|
61
|
-
const ASSET_MEMBER_KEYS = new Set(["fontFamily"]);
|
|
62
|
-
const MODE_OPTION_KEYS = new Set([
|
|
63
|
-
"modifier",
|
|
64
|
-
"label",
|
|
65
|
-
"description",
|
|
66
|
-
"appearance",
|
|
67
|
-
"minWidth",
|
|
68
|
-
"css",
|
|
69
|
-
"media"
|
|
70
|
-
]);
|
|
71
|
-
const APPEARANCES = new Set(["light", "dark"]);
|
|
72
|
-
const OS_KEYS = new Set([
|
|
73
|
-
"__kind",
|
|
74
|
-
"default",
|
|
75
|
-
"ios",
|
|
76
|
-
"android"
|
|
77
|
-
]);
|
|
78
|
-
const TOKEN_REF_KEYS = new Set(["__kind", "ref"]);
|
|
79
|
-
const MIX_KEYS = new Set([
|
|
80
|
-
"__kind",
|
|
81
|
-
"from",
|
|
82
|
-
"to",
|
|
83
|
-
"amount",
|
|
84
|
-
"colorSpace"
|
|
85
|
-
]);
|
|
86
|
-
const COLOR_SPACES = new Set([
|
|
87
|
-
"srgb",
|
|
88
|
-
"srgb-linear",
|
|
89
|
-
"oklab",
|
|
90
|
-
"oklch",
|
|
91
|
-
"lab",
|
|
92
|
-
"lch",
|
|
93
|
-
"hsl",
|
|
94
|
-
"hwb"
|
|
95
|
-
]);
|
|
96
|
-
function validateSerializedNativeConfig(input, expectedSchemaVersion = 4) {
|
|
97
|
-
const diagnostics = [];
|
|
98
|
-
const configDefinition = { kind: "config" };
|
|
99
|
-
if (!isRecord(input)) {
|
|
100
|
-
push(diagnostics, "INVALID_SCHEMA", [], configDefinition, "Native config must be a plain object.");
|
|
101
|
-
return diagnostics;
|
|
102
|
-
}
|
|
103
|
-
reportUnknownKeys(input, TOP_LEVEL_KEYS, [], configDefinition, diagnostics);
|
|
104
|
-
if (input.schemaVersion !== expectedSchemaVersion) push(diagnostics, typeof input.schemaVersion === "number" ? "UNSUPPORTED_SCHEMA_VERSION" : "INVALID_SCHEMA", ["schemaVersion"], configDefinition, `Native config schema version must be ${expectedSchemaVersion}; received ${String(input.schemaVersion)}.`);
|
|
105
|
-
if (input.platform !== "native") push(diagnostics, "PLATFORM_MISMATCH", ["platform"], configDefinition, "Native config must declare platform: \"native\".");
|
|
106
|
-
if (input.builtAt !== void 0 && typeof input.builtAt !== "string") push(diagnostics, "INVALID_SCHEMA", ["builtAt"], configDefinition, "builtAt must be a string when present.");
|
|
107
|
-
validateNamespace(input.namespace, diagnostics);
|
|
108
|
-
validateStyleEngine(input.styleEngine, diagnostics);
|
|
109
|
-
validateBuildOptions(input.buildOptions, diagnostics);
|
|
110
|
-
validateDependencyPolicy(input.dependencyPolicy, diagnostics);
|
|
111
|
-
validateModes(input.modes, diagnostics);
|
|
112
|
-
validateDefaultModes(input.defaultModes, input.modes, diagnostics);
|
|
113
|
-
validateAssetGroups(input.assetGroups, diagnostics);
|
|
114
|
-
validateTokenGroups(input.tokenGroups, diagnostics);
|
|
115
|
-
validateComponents(input.components, diagnostics);
|
|
116
|
-
validateComponentGroups(input.componentGroups, input.components, diagnostics);
|
|
117
|
-
validateLinkedSystems(input.linkedSystems, diagnostics);
|
|
118
|
-
validateReferences(input, diagnostics);
|
|
119
|
-
validateModifierOwnership(input, diagnostics);
|
|
120
|
-
return dedupe(diagnostics);
|
|
121
|
-
}
|
|
122
|
-
function validateDependencyPolicy(value, diagnostics) {
|
|
123
|
-
if (value === void 0) return;
|
|
124
|
-
const definition = { kind: "config" };
|
|
125
|
-
if (!isRecord(value)) {
|
|
126
|
-
push(diagnostics, "INVALID_DEPENDENCY_POLICY", ["dependencyPolicy"], definition, "dependencyPolicy must be a record keyed by npm package name.");
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
for (const [name, policy] of Object.entries(value)) {
|
|
130
|
-
const path = ["dependencyPolicy", name];
|
|
131
|
-
if (!isValidPackageName(name)) push(diagnostics, "INVALID_DEPENDENCY_POLICY", path, definition, `"${name}" is not a valid npm package name.`);
|
|
132
|
-
if (!isRecord(policy)) {
|
|
133
|
-
push(diagnostics, "INVALID_DEPENDENCY_POLICY", path, definition, "Dependency policy entries must be plain objects.");
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
reportUnknownKeys(policy, DEPENDENCY_POLICY_KEYS, path, definition, diagnostics);
|
|
137
|
-
if (policy.providedBy !== "consumer" && policy.providedBy !== "registry") push(diagnostics, "INVALID_DEPENDENCY_POLICY", [...path, "providedBy"], definition, "providedBy must be either \"consumer\" or \"registry\".");
|
|
138
|
-
if (typeof policy.version !== "string" || validRange(policy.version) === null) push(diagnostics, "INVALID_DEPENDENCY_POLICY", [...path, "version"], definition, "version must be a valid semver range.");
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
function isValidPackageName(name) {
|
|
142
|
-
if (name.length === 0 || name.length > 214 || name !== name.toLowerCase()) return false;
|
|
143
|
-
return /^(?:@[a-z0-9~][a-z0-9._~-]*\/)?[a-z0-9~][a-z0-9._~-]*$/.test(name);
|
|
144
|
-
}
|
|
145
|
-
function validateLinkedSystems(value, diagnostics) {
|
|
146
|
-
if (value === void 0) return;
|
|
147
|
-
const definition = { kind: "config" };
|
|
148
|
-
if (!isRecord(value)) {
|
|
149
|
-
push(diagnostics, "INVALID_SCHEMA", ["linkedSystems"], definition, "linkedSystems must be a record keyed by source-system UUID.");
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
for (const [systemId, pin] of Object.entries(value)) {
|
|
153
|
-
const path = ["linkedSystems", systemId];
|
|
154
|
-
if (!UUID_RE.test(systemId)) push(diagnostics, "INVALID_SCHEMA", path, definition, "Linked-system pins are keyed by the source system UUID.");
|
|
155
|
-
if (!isRecord(pin)) {
|
|
156
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, "A linked-system pin must be an object with name and version.");
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
reportUnknownKeys(pin, LINKED_SYSTEM_PIN_KEYS, path, definition, diagnostics);
|
|
160
|
-
if (typeof pin.name !== "string" || pin.name.trim().length === 0) push(diagnostics, "INVALID_SCHEMA", [...path, "name"], definition, "A linked-system pin requires a non-empty display name.");
|
|
161
|
-
if (typeof pin.version !== "string" || !EXACT_SEMVER_RE.test(pin.version)) push(diagnostics, "INVALID_SCHEMA", [...path, "version"], definition, "A linked-system pin requires an exact semver version (no ranges).");
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
function validateBuildOptions(value, diagnostics) {
|
|
165
|
-
if (value === void 0) return;
|
|
166
|
-
if (!isRecord(value)) {
|
|
167
|
-
push(diagnostics, "INVALID_SCHEMA", ["buildOptions"], { kind: "config" }, "Native buildOptions must be an object.");
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
reportUnknownKeys(value, BUILD_OPTIONS_KEYS, ["buildOptions"], { kind: "config" }, diagnostics);
|
|
171
|
-
if (value.componentsDir !== void 0 && (typeof value.componentsDir !== "string" || value.componentsDir.length === 0)) push(diagnostics, "INVALID_SCHEMA", ["buildOptions", "componentsDir"], { kind: "config" }, "Native componentsDir must be a non-empty path string.");
|
|
172
|
-
}
|
|
173
|
-
function validateComponents(value, diagnostics) {
|
|
174
|
-
if (value === void 0) return;
|
|
175
|
-
if (!isRecord(value)) {
|
|
176
|
-
push(diagnostics, "INVALID_SCHEMA", ["components"], { kind: "config" }, "Native components must be a record.");
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
const ids = /* @__PURE__ */ new Map();
|
|
180
|
-
for (const [componentName, component] of Object.entries(value)) {
|
|
181
|
-
const path = ["components", componentName];
|
|
182
|
-
const definition = {
|
|
183
|
-
kind: "component",
|
|
184
|
-
name: componentName
|
|
185
|
-
};
|
|
186
|
-
if (!isRecord(component)) {
|
|
187
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, `Native component "${componentName}" must be an object.`);
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
reportUnknownKeys(component, COMPONENT_KEYS, path, definition, diagnostics);
|
|
191
|
-
if (typeof component.id !== "string" || component.id.length === 0) push(diagnostics, "INVALID_SCHEMA", [...path, "id"], definition, `Native component "${componentName}" must declare a stable id.`);
|
|
192
|
-
else {
|
|
193
|
-
const owner = ids.get(component.id);
|
|
194
|
-
if (owner !== void 0) push(diagnostics, "INVALID_SCHEMA", [...path, "id"], definition, `Native component id "${component.id}" is already registered as "${owner}".`);
|
|
195
|
-
else ids.set(component.id, componentName);
|
|
196
|
-
}
|
|
197
|
-
const layerNames = validateComponentLayers(component.layers, [...path, "layers"], definition, diagnostics);
|
|
198
|
-
validateComponentConfig(component.styles, [...path, "styles"], definition, layerNames, diagnostics);
|
|
199
|
-
validateComponentProps(component.props, path, definition, diagnostics);
|
|
200
|
-
validateComponentStyleProps(component, path, definition, diagnostics);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
function validateComponentStyleProps(component, path, definition, diagnostics) {
|
|
204
|
-
const props = isRecord(component.props) ? component.props : {};
|
|
205
|
-
const styles = isRecord(component.styles) ? component.styles : {};
|
|
206
|
-
for (const [groupName, expectedKind] of [["variants", "variant"], ["booleans", "boolean"]]) {
|
|
207
|
-
const groups = styles[groupName];
|
|
208
|
-
if (!isRecord(groups)) continue;
|
|
209
|
-
for (const [propName, options] of Object.entries(groups)) {
|
|
210
|
-
const marker = props[propName];
|
|
211
|
-
if (!isRecord(marker) || marker.__kind !== expectedKind) {
|
|
212
|
-
push(diagnostics, "INVALID_REFERENCE", [
|
|
213
|
-
...path,
|
|
214
|
-
"styles",
|
|
215
|
-
groupName,
|
|
216
|
-
propName
|
|
217
|
-
], definition, `Native ${groupName} styles must target a ${expectedKind} component prop.`);
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
if (!isRecord(options)) continue;
|
|
221
|
-
const allowedOptions = expectedKind === "variant" && Array.isArray(marker.values) ? new Set(marker.values.map(String)) : new Set(["true", "false"]);
|
|
222
|
-
for (const optionName of Object.keys(options)) if (!allowedOptions.has(optionName)) push(diagnostics, "INVALID_REFERENCE", [
|
|
223
|
-
...path,
|
|
224
|
-
"styles",
|
|
225
|
-
groupName,
|
|
226
|
-
propName,
|
|
227
|
-
optionName
|
|
228
|
-
], definition, expectedKind === "variant" ? `Native variant style option "${optionName}" is not declared by prop "${propName}".` : `Native boolean style option "${optionName}" must be true or false.`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function validateComponentProps(value, componentPath, definition, diagnostics) {
|
|
233
|
-
if (!isRecord(value)) {
|
|
234
|
-
push(diagnostics, "INVALID_SCHEMA", [...componentPath, "props"], definition, "Native component props must be a record.");
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
for (const [propName, marker] of Object.entries(value)) {
|
|
238
|
-
if (!isRecord(marker) || ![
|
|
239
|
-
"slot",
|
|
240
|
-
"boolean",
|
|
241
|
-
"string",
|
|
242
|
-
"number",
|
|
243
|
-
"variant"
|
|
244
|
-
].includes(String(marker.__kind))) {
|
|
245
|
-
push(diagnostics, "INVALID_SCHEMA", [
|
|
246
|
-
...componentPath,
|
|
247
|
-
"props",
|
|
248
|
-
propName
|
|
249
|
-
], definition, `Unknown native component prop marker "${String(isRecord(marker) ? marker.__kind : marker)}".`);
|
|
250
|
-
continue;
|
|
251
|
-
}
|
|
252
|
-
if (marker.__kind === "variant") {
|
|
253
|
-
if (!Array.isArray(marker.values) || marker.values.length === 0 || marker.values.some((option) => typeof option !== "string" && typeof option !== "number" || typeof option === "number" && !Number.isFinite(option))) push(diagnostics, "INVALID_SCHEMA", [
|
|
254
|
-
...componentPath,
|
|
255
|
-
"props",
|
|
256
|
-
propName,
|
|
257
|
-
"values"
|
|
258
|
-
], definition, "Native variant props require at least one finite number or string option.");
|
|
259
|
-
else if (new Set(marker.values.map(String)).size !== marker.values.length) push(diagnostics, "INVALID_SCHEMA", [
|
|
260
|
-
...componentPath,
|
|
261
|
-
"props",
|
|
262
|
-
propName,
|
|
263
|
-
"values"
|
|
264
|
-
], definition, "Native variant prop options must remain unique when serialized as object keys.");
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
function validateComponentLayers(value, path, definition, diagnostics) {
|
|
269
|
-
const names = /* @__PURE__ */ new Set();
|
|
270
|
-
if (!isRecord(value) || Object.keys(value).length === 0) {
|
|
271
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, "A native component must declare at least one layer.");
|
|
272
|
-
return names;
|
|
273
|
-
}
|
|
274
|
-
for (const [layerName, layer] of Object.entries(value)) {
|
|
275
|
-
names.add(layerName);
|
|
276
|
-
const layerPath = [...path, layerName];
|
|
277
|
-
if (!isRecord(layer)) {
|
|
278
|
-
push(diagnostics, "INVALID_SCHEMA", layerPath, definition, `Native layer "${layerName}" must be an object.`);
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
reportUnknownKeys(layer, LAYER_KEYS, layerPath, definition, diagnostics);
|
|
282
|
-
if (layer.kind !== "view" && layer.kind !== "text" && layer.kind !== "image") push(diagnostics, "INVALID_SCHEMA", [...layerPath, "kind"], definition, `Native layer "${layerName}" must use view, text, or image styles.`);
|
|
283
|
-
if (layer.styleProp !== void 0 && (typeof layer.styleProp !== "string" || layer.styleProp.length === 0)) push(diagnostics, "INVALID_SCHEMA", [...layerPath, "styleProp"], definition, "A public style prop name must be a non-empty string.");
|
|
284
|
-
}
|
|
285
|
-
return names;
|
|
286
|
-
}
|
|
287
|
-
function validateComponentConfig(value, path, definition, layerNames, diagnostics) {
|
|
288
|
-
if (!isRecord(value)) {
|
|
289
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, "Native component styles must be an object.");
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
reportUnknownKeys(value, COMPONENT_CONFIG_KEYS, path, definition, diagnostics);
|
|
293
|
-
validateLayerStyleMap(value.base, [...path, "base"], definition, layerNames, diagnostics);
|
|
294
|
-
for (const key of ["variants", "booleans"]) {
|
|
295
|
-
const groups = value[key];
|
|
296
|
-
if (groups === void 0) continue;
|
|
297
|
-
if (!isRecord(groups)) {
|
|
298
|
-
push(diagnostics, "INVALID_SCHEMA", [...path, key], definition, `${key} must be a record.`);
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
for (const [propName, values] of Object.entries(groups)) {
|
|
302
|
-
if (!isRecord(values)) {
|
|
303
|
-
push(diagnostics, "INVALID_SCHEMA", [
|
|
304
|
-
...path,
|
|
305
|
-
key,
|
|
306
|
-
propName
|
|
307
|
-
], definition, `${key} styles for "${propName}" must be an option record.`);
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
for (const [optionName, styles] of Object.entries(values)) validateLayerStyleMap(styles, [
|
|
311
|
-
...path,
|
|
312
|
-
key,
|
|
313
|
-
propName,
|
|
314
|
-
optionName
|
|
315
|
-
], definition, layerNames, diagnostics);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
if (value.runtimeStates !== void 0) if (!isRecord(value.runtimeStates)) push(diagnostics, "INVALID_SCHEMA", [...path, "runtimeStates"], definition, "Native runtimeStates must be a record.");
|
|
319
|
-
else for (const [stateName, styles] of Object.entries(value.runtimeStates)) validateLayerStyleMap(styles, [
|
|
320
|
-
...path,
|
|
321
|
-
"runtimeStates",
|
|
322
|
-
stateName
|
|
323
|
-
], definition, layerNames, diagnostics);
|
|
324
|
-
if (value.values !== void 0) if (!isRecord(value.values)) push(diagnostics, "INVALID_SCHEMA", [...path, "values"], definition, "Native named values must be a record.");
|
|
325
|
-
else for (const [name, namedValue] of Object.entries(value.values)) validateNativeValue(namedValue, [
|
|
326
|
-
...path,
|
|
327
|
-
"values",
|
|
328
|
-
name
|
|
329
|
-
], definition, diagnostics, true);
|
|
330
|
-
}
|
|
331
|
-
function validateLayerStyleMap(value, path, definition, layerNames, diagnostics) {
|
|
332
|
-
if (value === void 0) return;
|
|
333
|
-
if (!isRecord(value)) {
|
|
334
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, "Native component styles must be a layer record.");
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
for (const [layerName, styles] of Object.entries(value)) {
|
|
338
|
-
if (!layerNames.has(layerName)) {
|
|
339
|
-
push(diagnostics, "INVALID_REFERENCE", [...path, layerName], definition, `Native layer "${layerName}" is not declared by this component.`);
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
if (!isRecord(styles)) {
|
|
343
|
-
push(diagnostics, "INVALID_SCHEMA", [...path, layerName], definition, `Styles for layer "${layerName}" must be an object.`);
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
for (const [property, styleValue] of Object.entries(styles)) validateComponentStyleValue(styleValue, [
|
|
347
|
-
...path,
|
|
348
|
-
layerName,
|
|
349
|
-
property
|
|
350
|
-
], definition, diagnostics);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
function validateComponentStyleValue(value, path, definition, diagnostics) {
|
|
354
|
-
if (Array.isArray(value)) {
|
|
355
|
-
value.forEach((entry, index) => {
|
|
356
|
-
validateComponentStyleValue(entry, [...path, index], definition, diagnostics);
|
|
357
|
-
});
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
if (isRecord(value) && !("__kind" in value)) {
|
|
361
|
-
for (const [key, nested] of Object.entries(value)) validateComponentStyleValue(nested, [...path, key], definition, diagnostics);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
validateNativeValue(value, path, definition, diagnostics, true);
|
|
365
|
-
}
|
|
366
|
-
function validateComponentGroups(value, components, diagnostics) {
|
|
367
|
-
if (value === void 0) return;
|
|
368
|
-
if (!isRecord(value)) {
|
|
369
|
-
push(diagnostics, "INVALID_SCHEMA", ["componentGroups"], { kind: "config" }, "Native componentGroups must be a record.");
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const registered = isRecord(components) ? components : {};
|
|
373
|
-
for (const [groupName, group] of Object.entries(value)) {
|
|
374
|
-
const path = ["componentGroups", groupName];
|
|
375
|
-
const definition = {
|
|
376
|
-
kind: "componentGroup",
|
|
377
|
-
name: groupName
|
|
378
|
-
};
|
|
379
|
-
if (!isRecord(group)) {
|
|
380
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, `Native component group "${groupName}" must be an object.`);
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
reportUnknownKeys(group, COMPONENT_GROUP_KEYS, path, definition, diagnostics);
|
|
384
|
-
if (!Array.isArray(group.components) || group.components.length === 0) push(diagnostics, "INVALID_SCHEMA", [...path, "components"], definition, "A native component group must contain at least one component.");
|
|
385
|
-
else for (const [index, componentName] of group.components.entries()) if (typeof componentName !== "string" || !(componentName in registered)) push(diagnostics, "INVALID_REFERENCE", [
|
|
386
|
-
...path,
|
|
387
|
-
"components",
|
|
388
|
-
index
|
|
389
|
-
], definition, `Native component "${String(componentName)}" is not registered.`);
|
|
390
|
-
for (const key of ["label", "description"]) if (group[key] !== void 0 && typeof group[key] !== "string") push(diagnostics, "INVALID_SCHEMA", [...path, key], definition, `${key} must be a string.`);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
function validateStyleEngine(value, diagnostics) {
|
|
394
|
-
if (value !== void 0 && value !== "react-native" && value !== "unistyles") push(diagnostics, "INVALID_SCHEMA", ["styleEngine"], { kind: "config" }, "Native styleEngine must be \"react-native\" or \"unistyles\" when present.");
|
|
395
|
-
}
|
|
396
|
-
function validateNamespace(value, diagnostics) {
|
|
397
|
-
if (value === void 0) return;
|
|
398
|
-
if (typeof value !== "string" || value.length === 0 || value.includes(":") || /\s/.test(value)) push(diagnostics, "INVALID_NAMESPACE", ["namespace"], { kind: "config" }, "Native config namespace must be a non-empty string without whitespace or \":\".");
|
|
399
|
-
}
|
|
400
|
-
function validateModes(value, diagnostics) {
|
|
401
|
-
if (value === void 0) return;
|
|
402
|
-
if (!isRecord(value)) {
|
|
403
|
-
push(diagnostics, "INVALID_SCHEMA", ["modes"], { kind: "config" }, "modes must be a record.");
|
|
404
|
-
return;
|
|
405
|
-
}
|
|
406
|
-
const kindOwners = /* @__PURE__ */ new Map();
|
|
407
|
-
const modifierOwners = /* @__PURE__ */ new Map();
|
|
408
|
-
for (const [modeName, options] of Object.entries(value)) {
|
|
409
|
-
const definition = {
|
|
410
|
-
kind: "mode",
|
|
411
|
-
name: modeName
|
|
412
|
-
};
|
|
413
|
-
const modePath = ["modes", modeName];
|
|
414
|
-
if (!isRecord(options)) {
|
|
415
|
-
push(diagnostics, "INVALID_SCHEMA", modePath, definition, `Mode "${modeName}" must be an option record.`);
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
if (Object.keys(options).length === 0) push(diagnostics, "INVALID_MODE_CONDITION", modePath, definition, `Native mode "${modeName}" must define at least one appearance or viewport option.`);
|
|
419
|
-
let modeKind;
|
|
420
|
-
const conditionValues = /* @__PURE__ */ new Map();
|
|
421
|
-
for (const [optionName, option] of Object.entries(options)) {
|
|
422
|
-
const optionPath = [...modePath, optionName];
|
|
423
|
-
if (!isRecord(option)) {
|
|
424
|
-
push(diagnostics, "INVALID_SCHEMA", optionPath, definition, `Mode option "${modeName}/${optionName}" must be an object.`);
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
reportUnknownKeys(option, MODE_OPTION_KEYS, optionPath, definition, diagnostics);
|
|
428
|
-
for (const key of [
|
|
429
|
-
"modifier",
|
|
430
|
-
"label",
|
|
431
|
-
"description"
|
|
432
|
-
]) if (option[key] !== void 0 && typeof option[key] !== "string") push(diagnostics, "INVALID_SCHEMA", [...optionPath, key], definition, `${key} must be a string when present.`);
|
|
433
|
-
if (typeof option.modifier === "string" && !option.modifier.startsWith("_")) push(diagnostics, "INVALID_SCHEMA", [...optionPath, "modifier"], definition, "Native mode modifiers must start with \"_\".");
|
|
434
|
-
for (const key of ["css", "media"]) if (option[key] !== void 0) push(diagnostics, "UNSUPPORTED_NATIVE_FIELD", [...optionPath, key], definition, `Mode option field "${key}" is web-only and is not supported by NativeConfig.`);
|
|
435
|
-
const hasAppearance = option.appearance !== void 0;
|
|
436
|
-
if (hasAppearance === (option.minWidth !== void 0)) {
|
|
437
|
-
push(diagnostics, "INVALID_MODE_CONDITION", optionPath, definition, `Native mode option "${modeName}/${optionName}" must define exactly one condition: appearance or minWidth.`);
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
const optionKind = hasAppearance ? "appearance" : "viewport";
|
|
441
|
-
if (modeKind !== void 0 && modeKind !== optionKind) push(diagnostics, "INVALID_MODE_CONDITION", optionPath, definition, `Native mode "${modeName}" cannot mix appearance and viewport options.`);
|
|
442
|
-
else modeKind = optionKind;
|
|
443
|
-
let conditionValue;
|
|
444
|
-
if (hasAppearance) if (typeof option.appearance !== "string" || !APPEARANCES.has(option.appearance)) push(diagnostics, "INVALID_MODE_CONDITION", [...optionPath, "appearance"], definition, "Native appearance must be \"light\" or \"dark\".");
|
|
445
|
-
else conditionValue = option.appearance;
|
|
446
|
-
else if (typeof option.minWidth !== "number" || !Number.isFinite(option.minWidth) || option.minWidth < 0) push(diagnostics, "INVALID_MODE_CONDITION", [...optionPath, "minWidth"], definition, "Native minWidth must be a finite, non-negative number.");
|
|
447
|
-
else conditionValue = option.minWidth;
|
|
448
|
-
if (conditionValue !== void 0) {
|
|
449
|
-
const previous = conditionValues.get(conditionValue);
|
|
450
|
-
if (previous !== void 0) push(diagnostics, "INVALID_MODE_CONDITION", optionPath, definition, `Native mode options "${modeName}/${previous}" and "${modeName}/${optionName}" describe the same condition.`);
|
|
451
|
-
else conditionValues.set(conditionValue, optionName);
|
|
452
|
-
}
|
|
453
|
-
const modifier = typeof option.modifier === "string" ? option.modifier : `_${optionName}`;
|
|
454
|
-
const previousModifierOwner = modifierOwners.get(modifier);
|
|
455
|
-
if (previousModifierOwner !== void 0) push(diagnostics, "DUPLICATE_MODIFIER", [...optionPath, "modifier"], definition, `Modifier "${modifier}" is already owned by mode option "${previousModifierOwner}".`);
|
|
456
|
-
else modifierOwners.set(modifier, `${modeName}/${optionName}`);
|
|
457
|
-
}
|
|
458
|
-
if (modeKind !== void 0) {
|
|
459
|
-
const previousKindOwner = kindOwners.get(modeKind);
|
|
460
|
-
if (previousKindOwner !== void 0) push(diagnostics, "INVALID_MODE_CONDITION", modePath, definition, `Native ${modeKind} conditions are already registered by mode "${previousKindOwner}".`);
|
|
461
|
-
else kindOwners.set(modeKind, modeName);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
function validateDefaultModes(value, modes, diagnostics) {
|
|
466
|
-
if (value === void 0) return;
|
|
467
|
-
if (!isRecord(value)) {
|
|
468
|
-
push(diagnostics, "INVALID_DEFAULT_MODE", ["defaultModes"], { kind: "config" }, "defaultModes must be a record of registered mode selections.");
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
const registeredModes = isRecord(modes) ? modes : {};
|
|
472
|
-
for (const [modeName, optionName] of Object.entries(value)) {
|
|
473
|
-
const path = ["defaultModes", modeName];
|
|
474
|
-
const options = registeredModes[modeName];
|
|
475
|
-
if (!isRecord(options)) {
|
|
476
|
-
push(diagnostics, "INVALID_DEFAULT_MODE", path, {
|
|
477
|
-
kind: "mode",
|
|
478
|
-
name: modeName
|
|
479
|
-
}, `Default mode "${modeName}" is not registered.`);
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
if (typeof optionName !== "string" || !isRecord(options[optionName])) push(diagnostics, "INVALID_DEFAULT_MODE", path, {
|
|
483
|
-
kind: "mode",
|
|
484
|
-
name: modeName
|
|
485
|
-
}, `Default mode "${modeName}" must select a registered option.`);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
function validateAssetGroups(value, diagnostics) {
|
|
489
|
-
if (value === void 0) return;
|
|
490
|
-
if (!isRecord(value)) {
|
|
491
|
-
push(diagnostics, "INVALID_SCHEMA", ["assetGroups"], { kind: "config" }, "assetGroups must be a record.");
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
for (const [groupName, group] of Object.entries(value)) {
|
|
495
|
-
const definition = {
|
|
496
|
-
kind: "asset-group",
|
|
497
|
-
name: groupName
|
|
498
|
-
};
|
|
499
|
-
const groupPath = ["assetGroups", groupName];
|
|
500
|
-
if (!isRecord(group)) {
|
|
501
|
-
push(diagnostics, "INVALID_SCHEMA", groupPath, definition, `Asset group "${groupName}" must be an object.`);
|
|
502
|
-
continue;
|
|
503
|
-
}
|
|
504
|
-
reportUnknownKeys(group, ASSET_GROUP_KEYS, groupPath, definition, diagnostics);
|
|
505
|
-
if (group.assetKind !== "font") push(diagnostics, "INVALID_SCHEMA", [...groupPath, "assetKind"], definition, `Native asset group "${groupName}" must currently use assetKind "font".`);
|
|
506
|
-
for (const key of ["label", "description"]) if (group[key] !== void 0 && typeof group[key] !== "string") push(diagnostics, "INVALID_SCHEMA", [...groupPath, key], definition, `${key} must be a string when present.`);
|
|
507
|
-
if (!isRecord(group.members)) {
|
|
508
|
-
push(diagnostics, "INVALID_SCHEMA", [...groupPath, "members"], definition, `Native font asset group "${groupName}" must have a members record.`);
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
for (const [memberName, member] of Object.entries(group.members)) {
|
|
512
|
-
const memberDefinition = {
|
|
513
|
-
kind: "asset",
|
|
514
|
-
name: `${groupName}/${memberName}`
|
|
515
|
-
};
|
|
516
|
-
const memberPath = [
|
|
517
|
-
...groupPath,
|
|
518
|
-
"members",
|
|
519
|
-
memberName
|
|
520
|
-
];
|
|
521
|
-
if (!isRecord(member)) {
|
|
522
|
-
push(diagnostics, "INVALID_SCHEMA", memberPath, memberDefinition, `Native font asset "${groupName}/${memberName}" must be an object.`);
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
reportUnknownKeys(member, ASSET_MEMBER_KEYS, memberPath, memberDefinition, diagnostics);
|
|
526
|
-
if (typeof member.fontFamily !== "string" || member.fontFamily.length === 0) push(diagnostics, "INVALID_SCHEMA", [...memberPath, "fontFamily"], memberDefinition, `Native font asset "${groupName}/${memberName}" requires a non-empty fontFamily.`);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
function validateTokenGroups(value, diagnostics) {
|
|
531
|
-
if (value === void 0) return;
|
|
532
|
-
if (!isRecord(value)) {
|
|
533
|
-
push(diagnostics, "INVALID_SCHEMA", ["tokenGroups"], { kind: "config" }, "tokenGroups must be a record.");
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
for (const [groupName, group] of Object.entries(value)) {
|
|
537
|
-
const groupDefinition = {
|
|
538
|
-
kind: "token-group",
|
|
539
|
-
name: groupName
|
|
540
|
-
};
|
|
541
|
-
const groupPath = ["tokenGroups", groupName];
|
|
542
|
-
if (!isRecord(group)) {
|
|
543
|
-
push(diagnostics, "INVALID_SCHEMA", groupPath, groupDefinition, `Token group "${groupName}" must be an object.`);
|
|
544
|
-
continue;
|
|
545
|
-
}
|
|
546
|
-
reportUnknownKeys(group, GROUP_KEYS, groupPath, groupDefinition, diagnostics);
|
|
547
|
-
for (const key of ["label", "description"]) if (group[key] !== void 0 && typeof group[key] !== "string") push(diagnostics, "INVALID_SCHEMA", [...groupPath, key], groupDefinition, `${key} must be a string when present.`);
|
|
548
|
-
if (!isRecord(group.tokens)) {
|
|
549
|
-
push(diagnostics, "INVALID_SCHEMA", [...groupPath, "tokens"], groupDefinition, `Token group "${groupName}" must have a tokens record.`);
|
|
550
|
-
continue;
|
|
551
|
-
}
|
|
552
|
-
for (const [tokenName, token] of Object.entries(group.tokens)) validateTokenDefinition(token, [
|
|
553
|
-
...groupPath,
|
|
554
|
-
"tokens",
|
|
555
|
-
tokenName
|
|
556
|
-
], {
|
|
557
|
-
kind: "token",
|
|
558
|
-
name: `${groupName}/${tokenName}`
|
|
559
|
-
}, diagnostics);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
function validateTokenDefinition(value, path, definition, diagnostics) {
|
|
563
|
-
if (!isRecord(value)) {
|
|
564
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, `Native token "${definition.name ?? ""}" must be an object.`);
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
if (!("value" in value)) push(diagnostics, "INVALID_SCHEMA", [...path, "value"], definition, `Native token "${definition.name ?? ""}" requires a value.`);
|
|
568
|
-
else validateNativeValue(value.value, [...path, "value"], definition, diagnostics, true);
|
|
569
|
-
if (value.type !== void 0 && typeof value.type !== "string") push(diagnostics, "INVALID_SCHEMA", [...path, "type"], definition, "Token type must be a string when present.");
|
|
570
|
-
validateSystemLink(value.link, [...path, "link"], definition, diagnostics);
|
|
571
|
-
for (const [key, modifier] of Object.entries(value)) {
|
|
572
|
-
if (key === "value" || key === "type" || key === "link") continue;
|
|
573
|
-
if (!key.startsWith("_")) {
|
|
574
|
-
push(diagnostics, "INVALID_SCHEMA", [...path, key], definition, `Unknown token definition field "${key}"; modifier fields must start with "_".`);
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
if (looksLikeTokenDefinition(modifier)) validateTokenDefinition(modifier, [...path, key], definition, diagnostics);
|
|
578
|
-
else validateNativeValue(modifier, [...path, key], definition, diagnostics, true);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
function validateSystemLink(value, path, definition, diagnostics) {
|
|
582
|
-
if (value === void 0) return;
|
|
583
|
-
if (!isRecord(value)) {
|
|
584
|
-
push(diagnostics, "INVALID_SCHEMA", path, definition, "Token link provenance must be an object.");
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
reportUnknownKeys(value, new Set([
|
|
588
|
-
"kind",
|
|
589
|
-
"systemId",
|
|
590
|
-
"systemVersion",
|
|
591
|
-
"sourceKey"
|
|
592
|
-
]), path, definition, diagnostics);
|
|
593
|
-
if (value.kind !== "token") push(diagnostics, "INVALID_SCHEMA", [...path, "kind"], definition, "Token link provenance must use kind \"token\".");
|
|
594
|
-
for (const key of [
|
|
595
|
-
"systemId",
|
|
596
|
-
"systemVersion",
|
|
597
|
-
"sourceKey"
|
|
598
|
-
]) if (typeof value[key] !== "string" || value[key].length === 0) push(diagnostics, "INVALID_SCHEMA", [...path, key], definition, `Token link provenance requires a non-empty ${key}.`);
|
|
599
|
-
}
|
|
600
|
-
function validateNativeValue(value, path, definition, diagnostics, allowOperatingSystem) {
|
|
601
|
-
if (typeof value === "string" || typeof value === "boolean") return;
|
|
602
|
-
if (typeof value === "number") {
|
|
603
|
-
if (!Number.isFinite(value)) push(diagnostics, "INVALID_NATIVE_VALUE", path, definition, "Native numeric values must be finite.");
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
if (!isRecord(value)) {
|
|
607
|
-
push(diagnostics, "INVALID_NATIVE_VALUE", path, definition, "Native token values must be serializable strings, numbers, booleans, references, supported color expressions, or operatingSystem() values.");
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
if (isTokenRef(value) || isAssetRef(value)) {
|
|
611
|
-
reportUnknownKeys(value, TOKEN_REF_KEYS, path, definition, diagnostics);
|
|
612
|
-
if (typeof value.ref !== "string" || value.ref.length === 0) push(diagnostics, "INVALID_REFERENCE", [...path, "ref"], definition, "Reference markers require a non-empty ref string.");
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
if (isOperatingSystemValue(value)) {
|
|
616
|
-
if (!allowOperatingSystem) {
|
|
617
|
-
push(diagnostics, "NESTED_OS_VALUE", path, definition, "An operatingSystem() branch cannot contain another operatingSystem() value.");
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
validateOperatingSystem(value, path, definition, diagnostics);
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
if (isMixExpr(value)) {
|
|
624
|
-
validateMix(value, path, definition, diagnostics);
|
|
625
|
-
return;
|
|
626
|
-
}
|
|
627
|
-
const kind = typeof value.__kind === "string" ? value.__kind : void 0;
|
|
628
|
-
if (kind === "darken" || kind === "lighten" || kind === "linear-gradient" || kind === "radial-gradient") {
|
|
629
|
-
push(diagnostics, "UNSUPPORTED_COLOR_EXPRESSION", path, definition, `Color expression "${kind}" does not yet have cross-platform native semantics; use mix(), alpha(), or a resolved native color.`);
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
push(diagnostics, "INVALID_NATIVE_VALUE", path, definition, "Native token values do not support arbitrary objects or arrays.");
|
|
633
|
-
}
|
|
634
|
-
function validateOperatingSystem(value, path, definition, diagnostics) {
|
|
635
|
-
reportUnknownKeys(value, OS_KEYS, path, definition, diagnostics);
|
|
636
|
-
if (value.default === void 0 && (value.ios === void 0 || value.android === void 0)) push(diagnostics, "INCOMPLETE_OS_VALUE", path, definition, "operatingSystem() requires a default value or explicit ios and android values.");
|
|
637
|
-
for (const key of [
|
|
638
|
-
"default",
|
|
639
|
-
"ios",
|
|
640
|
-
"android"
|
|
641
|
-
]) if (value[key] !== void 0) validateNativeValue(value[key], [...path, key], definition, diagnostics, false);
|
|
642
|
-
}
|
|
643
|
-
function validateMix(value, path, definition, diagnostics) {
|
|
644
|
-
reportUnknownKeys(value, MIX_KEYS, path, definition, diagnostics);
|
|
645
|
-
validateColorOperand(value.from, [...path, "from"], definition, diagnostics);
|
|
646
|
-
validateColorOperand(value.to, [...path, "to"], definition, diagnostics);
|
|
647
|
-
const amount = typeof value.amount === "string" ? /^(-?(?:\d+(?:\.\d+)?|\.\d+))%$/.exec(value.amount) : null;
|
|
648
|
-
const amountNumber = amount ? Number(amount[1]) : NaN;
|
|
649
|
-
if (!Number.isFinite(amountNumber) || amountNumber < 0 || amountNumber > 100) push(diagnostics, "INVALID_NATIVE_VALUE", [...path, "amount"], definition, "mix() amount must be a percentage between 0% and 100%.");
|
|
650
|
-
if (value.colorSpace !== void 0 && !COLOR_SPACES.has(value.colorSpace)) push(diagnostics, "INVALID_NATIVE_VALUE", [...path, "colorSpace"], definition, `mix() colorSpace "${String(value.colorSpace)}" is unsupported.`);
|
|
651
|
-
}
|
|
652
|
-
function validateColorOperand(value, path, definition, diagnostics) {
|
|
653
|
-
if (typeof value === "string") return;
|
|
654
|
-
if (isTokenRef(value)) {
|
|
655
|
-
validateNativeValue(value, path, definition, diagnostics, false);
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
if (isMixExpr(value)) {
|
|
659
|
-
validateMix(value, path, definition, diagnostics);
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
push(diagnostics, "INVALID_NATIVE_VALUE", path, definition, "Native color expressions accept color strings, token references, or nested mix() expressions.");
|
|
663
|
-
}
|
|
664
|
-
function validateReferences(config, diagnostics) {
|
|
665
|
-
const tokenGroups = isRecord(config.tokenGroups) ? config.tokenGroups : {};
|
|
666
|
-
const tokens = /* @__PURE__ */ new Map();
|
|
667
|
-
for (const [groupName, group] of Object.entries(tokenGroups)) {
|
|
668
|
-
if (!isRecord(group) || !isRecord(group.tokens)) continue;
|
|
669
|
-
for (const [tokenName, definition] of Object.entries(group.tokens)) {
|
|
670
|
-
if (!isRecord(definition)) continue;
|
|
671
|
-
tokens.set(`${groupName}/${tokenName}`, {
|
|
672
|
-
definition,
|
|
673
|
-
path: [
|
|
674
|
-
"tokenGroups",
|
|
675
|
-
groupName,
|
|
676
|
-
"tokens",
|
|
677
|
-
tokenName
|
|
678
|
-
]
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
const assets = isRecord(config.assetGroups) ? config.assetGroups : {};
|
|
683
|
-
const modifierLookup = createNativeModifierLookup(config.modes);
|
|
684
|
-
const contexts = buildModifierContexts(config.modes);
|
|
685
|
-
for (const [tokenRef, token] of tokens) {
|
|
686
|
-
collectAllReferences(token.definition, token.path, {
|
|
687
|
-
kind: "token",
|
|
688
|
-
name: tokenRef
|
|
689
|
-
}, tokens, assets, diagnostics);
|
|
690
|
-
for (const modifiers of contexts) resolveTokenContext(tokenRef, modifiers, modifierLookup, tokens, diagnostics, [], token.path);
|
|
691
|
-
}
|
|
692
|
-
for (const [componentName, component] of Object.entries(config.components ?? {})) collectComponentReferences(component, ["components", componentName], {
|
|
693
|
-
kind: "component",
|
|
694
|
-
name: componentName
|
|
695
|
-
}, tokens, assets, diagnostics);
|
|
696
|
-
}
|
|
697
|
-
function collectComponentReferences(value, path, definition, tokens, assets, diagnostics) {
|
|
698
|
-
if (Array.isArray(value)) {
|
|
699
|
-
value.forEach((entry, index) => {
|
|
700
|
-
collectComponentReferences(entry, [...path, index], definition, tokens, assets, diagnostics);
|
|
701
|
-
});
|
|
702
|
-
return;
|
|
703
|
-
}
|
|
704
|
-
if (!isRecord(value)) return;
|
|
705
|
-
if (isTokenRef(value)) {
|
|
706
|
-
if (typeof value.ref === "string" && !tokens.has(value.ref)) push(diagnostics, "UNRESOLVED_TOKEN_REFERENCE", path, definition, `Token reference "${value.ref}" does not resolve within this native config.`);
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
if (isAssetRef(value)) {
|
|
710
|
-
collectAllReferences(value, path, definition, tokens, assets, diagnostics);
|
|
711
|
-
return;
|
|
712
|
-
}
|
|
713
|
-
for (const [key, nested] of Object.entries(value)) collectComponentReferences(nested, [...path, key], definition, tokens, assets, diagnostics);
|
|
714
|
-
}
|
|
715
|
-
function collectAllReferences(value, path, definition, tokens, assets, diagnostics) {
|
|
716
|
-
walkValues(value, path, (entry, entryPath) => {
|
|
717
|
-
if (isTokenRef(entry)) {
|
|
718
|
-
if (typeof entry.ref === "string" && !tokens.has(entry.ref)) push(diagnostics, "UNRESOLVED_TOKEN_REFERENCE", entryPath, definition, `Token reference "${entry.ref}" does not resolve within this native config.`);
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
if (!isAssetRef(entry) || typeof entry.ref !== "string") return;
|
|
722
|
-
const slash = entry.ref.indexOf("/");
|
|
723
|
-
const groupName = slash > 0 ? entry.ref.slice(0, slash) : "";
|
|
724
|
-
const memberName = slash > 0 ? entry.ref.slice(slash + 1) : "";
|
|
725
|
-
const group = assets[groupName];
|
|
726
|
-
if (!groupName || !memberName || !group || group.assetKind !== "font" || !isRecord(group.members) || !group.members[memberName]) push(diagnostics, "UNRESOLVED_ASSET_REFERENCE", entryPath, definition, `Asset reference "${entry.ref}" does not resolve to a registered native font asset.`);
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
function resolveTokenContext(ref, activeModes, modifierLookup, tokens, diagnostics, stack, sourcePath) {
|
|
730
|
-
if (stack.includes(ref)) {
|
|
731
|
-
const cycle = [...stack.slice(stack.indexOf(ref)), ref].join(" -> ");
|
|
732
|
-
push(diagnostics, "TOKEN_REFERENCE_CYCLE", sourcePath, {
|
|
733
|
-
kind: "token",
|
|
734
|
-
name: stack[0] ?? ref
|
|
735
|
-
}, `Native token reference cycle detected: ${cycle}.`);
|
|
736
|
-
return;
|
|
737
|
-
}
|
|
738
|
-
const token = tokens.get(ref);
|
|
739
|
-
if (!token) return;
|
|
740
|
-
const selected = selectTokenValue(token.definition, token.path, activeModes, modifierLookup);
|
|
741
|
-
const nextStack = [...stack, ref];
|
|
742
|
-
walkValues(selected.value, selected.path, (entry, entryPath) => {
|
|
743
|
-
if (isTokenRef(entry) && typeof entry.ref === "string") resolveTokenContext(entry.ref, activeModes, modifierLookup, tokens, diagnostics, nextStack, entryPath);
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
function selectTokenValue(definition, path, activeModes, modifierLookup) {
|
|
747
|
-
const selected = resolveOverrideRow(modifierTreeToOverrideRows(definition, modifierLookup), activeModes);
|
|
748
|
-
if (!selected) return {
|
|
749
|
-
value: definition.value,
|
|
750
|
-
path: [...path, "value"]
|
|
751
|
-
};
|
|
752
|
-
let source = definition;
|
|
753
|
-
for (const modifier of selected.sourceModifierPath) source = source[modifier];
|
|
754
|
-
return {
|
|
755
|
-
value: selected.value,
|
|
756
|
-
path: [
|
|
757
|
-
...path,
|
|
758
|
-
...selected.sourceModifierPath,
|
|
759
|
-
...looksLikeTokenDefinition(source) ? ["value"] : []
|
|
760
|
-
]
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
function buildModifierContexts(modes) {
|
|
764
|
-
let contexts = [/* @__PURE__ */ new Set()];
|
|
765
|
-
for (const [modeName, options] of Object.entries(modes ?? {})) {
|
|
766
|
-
if (!isRecord(options)) continue;
|
|
767
|
-
const modeRefs = Object.entries(options).filter((entry) => isRecord(entry[1])).map(([optionName]) => `${modeName}.${optionName}`);
|
|
768
|
-
contexts = contexts.flatMap((context) => [context, ...modeRefs.map((modeRef) => new Set([...context, modeRef]))]);
|
|
769
|
-
}
|
|
770
|
-
return contexts;
|
|
771
|
-
}
|
|
772
|
-
function createNativeModifierLookup(modes) {
|
|
773
|
-
return createModeBackedModifierLookup(Object.entries(modes ?? {}).flatMap(([modeName, options], modeOrder) => {
|
|
774
|
-
if (!isRecord(options)) return [];
|
|
775
|
-
return Object.entries(options).flatMap(([optionName, option], optionOrder) => {
|
|
776
|
-
if (!isRecord(option)) return [];
|
|
777
|
-
return [{
|
|
778
|
-
modifier: typeof option.modifier === "string" ? option.modifier : `_${optionName}`,
|
|
779
|
-
mode: modeName,
|
|
780
|
-
option: optionName,
|
|
781
|
-
label: typeof option.label === "string" ? option.label : void 0,
|
|
782
|
-
modeOrder,
|
|
783
|
-
optionOrder
|
|
784
|
-
}];
|
|
785
|
-
});
|
|
786
|
-
}));
|
|
787
|
-
}
|
|
788
|
-
function validateModifierOwnership(config, diagnostics) {
|
|
789
|
-
const owners = /* @__PURE__ */ new Map();
|
|
790
|
-
if (isRecord(config.modes)) for (const [modeName, options] of Object.entries(config.modes)) {
|
|
791
|
-
if (!isRecord(options)) continue;
|
|
792
|
-
for (const [optionName, option] of Object.entries(options)) {
|
|
793
|
-
if (!isRecord(option)) continue;
|
|
794
|
-
const modifier = typeof option.modifier === "string" ? option.modifier : `_${optionName}`;
|
|
795
|
-
if (!owners.has(modifier)) owners.set(modifier, modeName);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
if (!isRecord(config.tokenGroups)) return;
|
|
799
|
-
for (const [groupName, group] of Object.entries(config.tokenGroups)) {
|
|
800
|
-
if (!isRecord(group) || !isRecord(group.tokens)) continue;
|
|
801
|
-
for (const [tokenName, definition] of Object.entries(group.tokens)) {
|
|
802
|
-
if (!isRecord(definition)) continue;
|
|
803
|
-
validateDefinitionModifiers(definition, [
|
|
804
|
-
"tokenGroups",
|
|
805
|
-
groupName,
|
|
806
|
-
"tokens",
|
|
807
|
-
tokenName
|
|
808
|
-
], {
|
|
809
|
-
kind: "token",
|
|
810
|
-
name: `${groupName}/${tokenName}`
|
|
811
|
-
}, owners, /* @__PURE__ */ new Set(), diagnostics);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
function validateDefinitionModifiers(definition, path, tokenDefinition, owners, activeModeGroups, diagnostics) {
|
|
816
|
-
for (const [modifier, value] of Object.entries(definition)) {
|
|
817
|
-
if (!modifier.startsWith("_")) continue;
|
|
818
|
-
const modifierPath = [...path, modifier];
|
|
819
|
-
const owner = owners.get(modifier);
|
|
820
|
-
if (owner === void 0) {
|
|
821
|
-
push(diagnostics, "UNOWNED_MODIFIER", modifierPath, tokenDefinition, `Modifier "${modifier}" is not owned by a registered mode option.`);
|
|
822
|
-
continue;
|
|
823
|
-
}
|
|
824
|
-
if (activeModeGroups.has(owner)) push(diagnostics, "INVALID_MODE_COMBINATION", modifierPath, tokenDefinition, `Compound native token overrides cannot select more than one option from mode "${owner}".`);
|
|
825
|
-
if (looksLikeTokenDefinition(value)) validateDefinitionModifiers(value, modifierPath, tokenDefinition, owners, new Set([...activeModeGroups, owner]), diagnostics);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
function walkValues(value, path, visit) {
|
|
829
|
-
if (!isRecord(value)) return;
|
|
830
|
-
if (isTokenRef(value) || isAssetRef(value)) {
|
|
831
|
-
visit(value, path);
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
if (isOperatingSystemValue(value)) {
|
|
835
|
-
for (const key of [
|
|
836
|
-
"default",
|
|
837
|
-
"ios",
|
|
838
|
-
"android"
|
|
839
|
-
]) if (value[key] !== void 0) walkValues(value[key], [...path, key], visit);
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
if (isMixExpr(value)) {
|
|
843
|
-
walkValues(value.from, [...path, "from"], visit);
|
|
844
|
-
walkValues(value.to, [...path, "to"], visit);
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
if (looksLikeTokenDefinition(value)) {
|
|
848
|
-
walkValues(value.value, [...path, "value"], visit);
|
|
849
|
-
for (const [key, nested] of Object.entries(value)) if (key.startsWith("_")) walkValues(nested, [...path, key], visit);
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
-
for (const [key, nested] of Object.entries(value)) if (key.startsWith("_")) walkValues(nested, [...path, key], visit);
|
|
853
|
-
}
|
|
854
|
-
function looksLikeTokenDefinition(value) {
|
|
855
|
-
return isRecord(value) && "value" in value && !("__kind" in value);
|
|
856
|
-
}
|
|
857
|
-
function reportUnknownKeys(value, allowed, path, definition, diagnostics) {
|
|
858
|
-
for (const key of Object.keys(value)) {
|
|
859
|
-
if (allowed.has(key)) continue;
|
|
860
|
-
push(diagnostics, "INVALID_SCHEMA", [...path, key], definition, `Unknown native config field "${key}".`);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
function isRecord(value) {
|
|
864
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
865
|
-
}
|
|
866
|
-
function push(diagnostics, code, path, definition, reason) {
|
|
867
|
-
diagnostics.push({
|
|
868
|
-
code,
|
|
869
|
-
severity: "error",
|
|
870
|
-
path,
|
|
871
|
-
definition,
|
|
872
|
-
reason
|
|
873
|
-
});
|
|
874
|
-
}
|
|
875
|
-
function dedupe(diagnostics) {
|
|
876
|
-
const seen = /* @__PURE__ */ new Set();
|
|
877
|
-
return diagnostics.filter((diagnostic) => {
|
|
878
|
-
const key = `${diagnostic.code}:${diagnostic.path.join(".")}:${diagnostic.reason}`;
|
|
879
|
-
if (seen.has(key)) return false;
|
|
880
|
-
seen.add(key);
|
|
881
|
-
return true;
|
|
882
|
-
});
|
|
883
|
-
}
|
|
884
|
-
//#endregion
|
|
885
|
-
export { validateSerializedNativeConfig };
|