@pwfabric/runtime 0.0.0-stage → 1.0.0-rc.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/LICENSE +90 -0
- package/README.md +43 -2
- package/dist/a11y/announcer.d.ts +65 -0
- package/dist/a11y/announcer.js +140 -0
- package/dist/a11y/announcer.js.map +1 -0
- package/dist/a11y/contrast.d.ts +54 -0
- package/dist/a11y/contrast.js +93 -0
- package/dist/a11y/contrast.js.map +1 -0
- package/dist/a11y/focus.d.ts +123 -0
- package/dist/a11y/focus.js +282 -0
- package/dist/a11y/focus.js.map +1 -0
- package/dist/a11y/index.d.ts +21 -0
- package/dist/a11y/index.js +18 -0
- package/dist/a11y/index.js.map +1 -0
- package/dist/a11y/keyboard.d.ts +144 -0
- package/dist/a11y/keyboard.js +317 -0
- package/dist/a11y/keyboard.js.map +1 -0
- package/dist/adapters/default-image.d.ts +25 -0
- package/dist/adapters/default-image.js +37 -0
- package/dist/adapters/default-image.js.map +1 -0
- package/dist/adapters/index.d.ts +27 -0
- package/dist/adapters/index.js +28 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/next-image.d.ts +38 -0
- package/dist/adapters/next-image.js +124 -0
- package/dist/adapters/next-image.js.map +1 -0
- package/dist/adapters/types.d.ts +61 -0
- package/dist/adapters/types.js +11 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/analytics/index.d.ts +14 -0
- package/dist/analytics/index.js +15 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/tracker.d.ts +65 -0
- package/dist/analytics/tracker.js +251 -0
- package/dist/analytics/tracker.js.map +1 -0
- package/dist/analytics/types.d.ts +130 -0
- package/dist/analytics/types.js +11 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/provider.d.ts +132 -0
- package/dist/auth/provider.js +473 -0
- package/dist/auth/provider.js.map +1 -0
- package/dist/auth/types.d.ts +117 -0
- package/dist/auth/types.js +9 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/binding/collection.d.ts +190 -0
- package/dist/binding/collection.js +358 -0
- package/dist/binding/collection.js.map +1 -0
- package/dist/binding/datasource.d.ts +319 -0
- package/dist/binding/datasource.js +556 -0
- package/dist/binding/datasource.js.map +1 -0
- package/dist/binding/engine.d.ts +65 -0
- package/dist/binding/engine.js +268 -0
- package/dist/binding/engine.js.map +1 -0
- package/dist/binding/expression.d.ts +150 -0
- package/dist/binding/expression.js +787 -0
- package/dist/binding/expression.js.map +1 -0
- package/dist/binding/index.d.ts +19 -0
- package/dist/binding/index.js +14 -0
- package/dist/binding/index.js.map +1 -0
- package/dist/binding/two-way.d.ts +149 -0
- package/dist/binding/two-way.js +462 -0
- package/dist/binding/two-way.js.map +1 -0
- package/dist/binding/types.d.ts +119 -0
- package/dist/binding/types.js +9 -0
- package/dist/binding/types.js.map +1 -0
- package/dist/blocks/component-types.d.ts +81 -0
- package/dist/blocks/component-types.js +11 -0
- package/dist/blocks/component-types.js.map +1 -0
- package/dist/blocks/composition-rules.d.ts +168 -0
- package/dist/blocks/composition-rules.js +391 -0
- package/dist/blocks/composition-rules.js.map +1 -0
- package/dist/blocks/hooks.d.ts +31 -0
- package/dist/blocks/hooks.js +42 -0
- package/dist/blocks/hooks.js.map +1 -0
- package/dist/blocks/index.d.ts +14 -0
- package/dist/blocks/index.js +23 -0
- package/dist/blocks/index.js.map +1 -0
- package/dist/blocks/registry.d.ts +84 -0
- package/dist/blocks/registry.js +136 -0
- package/dist/blocks/registry.js.map +1 -0
- package/dist/blocks/rule-engine.d.ts +131 -0
- package/dist/blocks/rule-engine.js +321 -0
- package/dist/blocks/rule-engine.js.map +1 -0
- package/dist/blocks/surface-event-context.d.ts +13 -0
- package/dist/blocks/surface-event-context.js +14 -0
- package/dist/blocks/surface-event-context.js.map +1 -0
- package/dist/blocks/surface-id-context.d.ts +13 -0
- package/dist/blocks/surface-id-context.js +15 -0
- package/dist/blocks/surface-id-context.js.map +1 -0
- package/dist/bus.d.ts +41 -0
- package/dist/bus.js +158 -0
- package/dist/bus.js.map +1 -0
- package/dist/cache/index.d.ts +9 -0
- package/dist/cache/index.js +10 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory.d.ts +32 -0
- package/dist/cache/memory.js +138 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/types.d.ts +62 -0
- package/dist/cache/types.js +9 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/capability/index.d.ts +72 -0
- package/dist/capability/index.js +87 -0
- package/dist/capability/index.js.map +1 -0
- package/dist/capability/kernel-capabilities.d.ts +31 -0
- package/dist/capability/kernel-capabilities.js +36 -0
- package/dist/capability/kernel-capabilities.js.map +1 -0
- package/dist/capability/platform-capabilities.d.ts +71 -0
- package/dist/capability/platform-capabilities.js +267 -0
- package/dist/capability/platform-capabilities.js.map +1 -0
- package/dist/capability/type-mapping.d.ts +70 -0
- package/dist/capability/type-mapping.js +107 -0
- package/dist/capability/type-mapping.js.map +1 -0
- package/dist/capability/validation.d.ts +46 -0
- package/dist/capability/validation.js +54 -0
- package/dist/capability/validation.js.map +1 -0
- package/dist/connectors/declared-connector.d.ts +48 -0
- package/dist/connectors/declared-connector.js +333 -0
- package/dist/connectors/declared-connector.js.map +1 -0
- package/dist/connectors/engine-registry.d.ts +50 -0
- package/dist/connectors/engine-registry.js +135 -0
- package/dist/connectors/engine-registry.js.map +1 -0
- package/dist/connectors/index.d.ts +14 -0
- package/dist/connectors/index.js +14 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/module-loader.d.ts +70 -0
- package/dist/connectors/module-loader.js +143 -0
- package/dist/connectors/module-loader.js.map +1 -0
- package/dist/connectors/types.d.ts +174 -0
- package/dist/connectors/types.js +23 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.js +38 -0
- package/dist/context.js.map +1 -0
- package/dist/data/DataCapabilityProvider.d.ts +39 -0
- package/dist/data/DataCapabilityProvider.js +58 -0
- package/dist/data/DataCapabilityProvider.js.map +1 -0
- package/dist/data/index.d.ts +17 -0
- package/dist/data/index.js +18 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data/manager.d.ts +40 -0
- package/dist/data/manager.js +442 -0
- package/dist/data/manager.js.map +1 -0
- package/dist/data/types.d.ts +218 -0
- package/dist/data/types.js +2 -0
- package/dist/data/types.js.map +1 -0
- package/dist/entity/aggregate.d.ts +8 -0
- package/dist/entity/aggregate.js +24 -0
- package/dist/entity/aggregate.js.map +1 -0
- package/dist/entity/apply-query.d.ts +58 -0
- package/dist/entity/apply-query.js +264 -0
- package/dist/entity/apply-query.js.map +1 -0
- package/dist/entity/behavior.d.ts +94 -0
- package/dist/entity/behavior.js +78 -0
- package/dist/entity/behavior.js.map +1 -0
- package/dist/entity/connector.d.ts +141 -0
- package/dist/entity/connector.js +89 -0
- package/dist/entity/connector.js.map +1 -0
- package/dist/entity/connectors/index.d.ts +12 -0
- package/dist/entity/connectors/index.js +11 -0
- package/dist/entity/connectors/index.js.map +1 -0
- package/dist/entity/connectors/static.d.ts +51 -0
- package/dist/entity/connectors/static.js +245 -0
- package/dist/entity/connectors/static.js.map +1 -0
- package/dist/entity/entity-datasource.d.ts +50 -0
- package/dist/entity/entity-datasource.js +33 -0
- package/dist/entity/entity-datasource.js.map +1 -0
- package/dist/entity/facade.d.ts +70 -0
- package/dist/entity/facade.js +70 -0
- package/dist/entity/facade.js.map +1 -0
- package/dist/entity/http-connector.d.ts +123 -0
- package/dist/entity/http-connector.js +295 -0
- package/dist/entity/http-connector.js.map +1 -0
- package/dist/entity/index.d.ts +38 -0
- package/dist/entity/index.js +31 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/postgres-connector.d.ts +64 -0
- package/dist/entity/postgres-connector.js +239 -0
- package/dist/entity/postgres-connector.js.map +1 -0
- package/dist/entity/registry.d.ts +59 -0
- package/dist/entity/registry.js +90 -0
- package/dist/entity/registry.js.map +1 -0
- package/dist/entity/store.d.ts +66 -0
- package/dist/entity/store.js +349 -0
- package/dist/entity/store.js.map +1 -0
- package/dist/entity/types.d.ts +180 -0
- package/dist/entity/types.js +10 -0
- package/dist/entity/types.js.map +1 -0
- package/dist/execution-context.d.ts +88 -0
- package/dist/execution-context.js +146 -0
- package/dist/execution-context.js.map +1 -0
- package/dist/executor.d.ts +27 -0
- package/dist/executor.js +33 -0
- package/dist/executor.js.map +1 -0
- package/dist/forms/form-entity-bridge.d.ts +94 -0
- package/dist/forms/form-entity-bridge.js +96 -0
- package/dist/forms/form-entity-bridge.js.map +1 -0
- package/dist/forms/form-write-target.d.ts +34 -0
- package/dist/forms/form-write-target.js +81 -0
- package/dist/forms/form-write-target.js.map +1 -0
- package/dist/forms/index.d.ts +22 -0
- package/dist/forms/index.js +25 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/named-control-values.d.ts +27 -0
- package/dist/forms/named-control-values.js +42 -0
- package/dist/forms/named-control-values.js.map +1 -0
- package/dist/forms/processor.d.ts +55 -0
- package/dist/forms/processor.js +154 -0
- package/dist/forms/processor.js.map +1 -0
- package/dist/forms/types.d.ts +174 -0
- package/dist/forms/types.js +33 -0
- package/dist/forms/types.js.map +1 -0
- package/dist/forms/validator.d.ts +61 -0
- package/dist/forms/validator.js +218 -0
- package/dist/forms/validator.js.map +1 -0
- package/dist/graph/index.d.ts +10 -0
- package/dist/graph/index.js +9 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/resolver.d.ts +66 -0
- package/dist/graph/resolver.js +243 -0
- package/dist/graph/resolver.js.map +1 -0
- package/dist/graph/types.d.ts +125 -0
- package/dist/graph/types.js +9 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/hooks/useInstalledAtoms.d.ts +96 -0
- package/dist/hooks/useInstalledAtoms.js +92 -0
- package/dist/hooks/useInstalledAtoms.js.map +1 -0
- package/dist/i18n/index.d.ts +15 -0
- package/dist/i18n/index.js +14 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/translator.d.ts +76 -0
- package/dist/i18n/translator.js +357 -0
- package/dist/i18n/translator.js.map +1 -0
- package/dist/i18n/types.d.ts +93 -0
- package/dist/i18n/types.js +9 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.d.ts +47 -0
- package/dist/kernel.js +258 -0
- package/dist/kernel.js.map +1 -0
- package/dist/perf/budget.d.ts +92 -0
- package/dist/perf/budget.js +122 -0
- package/dist/perf/budget.js.map +1 -0
- package/dist/perf/index.d.ts +16 -0
- package/dist/perf/index.js +13 -0
- package/dist/perf/index.js.map +1 -0
- package/dist/perf/render-timer.d.ts +90 -0
- package/dist/perf/render-timer.js +136 -0
- package/dist/perf/render-timer.js.map +1 -0
- package/dist/perf/reporter.d.ts +126 -0
- package/dist/perf/reporter.js +241 -0
- package/dist/perf/reporter.js.map +1 -0
- package/dist/perf/web-vitals.d.ts +111 -0
- package/dist/perf/web-vitals.js +268 -0
- package/dist/perf/web-vitals.js.map +1 -0
- package/dist/registry.d.ts +63 -0
- package/dist/registry.js +126 -0
- package/dist/registry.js.map +1 -0
- package/dist/render/BehaviorSurfaceProvider.d.ts +65 -0
- package/dist/render/BehaviorSurfaceProvider.js +185 -0
- package/dist/render/BehaviorSurfaceProvider.js.map +1 -0
- package/dist/render/BlockErrorBoundary.d.ts +26 -0
- package/dist/render/BlockErrorBoundary.js +41 -0
- package/dist/render/BlockErrorBoundary.js.map +1 -0
- package/dist/render/DataBoundSurfaceRenderer.d.ts +78 -0
- package/dist/render/DataBoundSurfaceRenderer.js +998 -0
- package/dist/render/DataBoundSurfaceRenderer.js.map +1 -0
- package/dist/render/DynamicBlockWrapper.d.ts +23 -0
- package/dist/render/DynamicBlockWrapper.js +117 -0
- package/dist/render/DynamicBlockWrapper.js.map +1 -0
- package/dist/render/appearance-resolver.d.ts +50 -0
- package/dist/render/appearance-resolver.js +78 -0
- package/dist/render/appearance-resolver.js.map +1 -0
- package/dist/render/capability-gate.d.ts +69 -0
- package/dist/render/capability-gate.js +94 -0
- package/dist/render/capability-gate.js.map +1 -0
- package/dist/render/conditional-states-css.d.ts +41 -0
- package/dist/render/conditional-states-css.js +82 -0
- package/dist/render/conditional-states-css.js.map +1 -0
- package/dist/render/connections-context.d.ts +31 -0
- package/dist/render/connections-context.js +34 -0
- package/dist/render/connections-context.js.map +1 -0
- package/dist/render/dark-theme-css.d.ts +36 -0
- package/dist/render/dark-theme-css.js +67 -0
- package/dist/render/dark-theme-css.js.map +1 -0
- package/dist/render/data-binding-types.d.ts +191 -0
- package/dist/render/data-binding-types.js +11 -0
- package/dist/render/data-binding-types.js.map +1 -0
- package/dist/render/data-cache.d.ts +30 -0
- package/dist/render/data-cache.js +37 -0
- package/dist/render/data-cache.js.map +1 -0
- package/dist/render/derive-dark-theme.d.ts +17 -0
- package/dist/render/derive-dark-theme.js +18 -0
- package/dist/render/derive-dark-theme.js.map +1 -0
- package/dist/render/dynamic-artifact-context.d.ts +77 -0
- package/dist/render/dynamic-artifact-context.js +89 -0
- package/dist/render/dynamic-artifact-context.js.map +1 -0
- package/dist/render/dynamic-block-loader.d.ts +80 -0
- package/dist/render/dynamic-block-loader.js +197 -0
- package/dist/render/dynamic-block-loader.js.map +1 -0
- package/dist/render/endpoint.d.ts +18 -0
- package/dist/render/endpoint.js +109 -0
- package/dist/render/endpoint.js.map +1 -0
- package/dist/render/entity-facade-context.d.ts +34 -0
- package/dist/render/entity-facade-context.js +37 -0
- package/dist/render/entity-facade-context.js.map +1 -0
- package/dist/render/group-states-css.d.ts +41 -0
- package/dist/render/group-states-css.js +73 -0
- package/dist/render/group-states-css.js.map +1 -0
- package/dist/render/hooks/useSurfaceEvents.d.ts +8 -0
- package/dist/render/hooks/useSurfaceEvents.js +9 -0
- package/dist/render/hooks/useSurfaceEvents.js.map +1 -0
- package/dist/render/hooks/useSurfaceId.d.ts +8 -0
- package/dist/render/hooks/useSurfaceId.js +9 -0
- package/dist/render/hooks/useSurfaceId.js.map +1 -0
- package/dist/render/index.d.ts +48 -0
- package/dist/render/index.js +61 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/interaction-rule-engine.d.ts +12 -0
- package/dist/render/interaction-rule-engine.js +47 -0
- package/dist/render/interaction-rule-engine.js.map +1 -0
- package/dist/render/keyframes-css.d.ts +31 -0
- package/dist/render/keyframes-css.js +44 -0
- package/dist/render/keyframes-css.js.map +1 -0
- package/dist/render/query-state.d.ts +3 -0
- package/dist/render/query-state.js +70 -0
- package/dist/render/query-state.js.map +1 -0
- package/dist/render/renderer.d.ts +44 -0
- package/dist/render/renderer.js +937 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/resolve-expressions.d.ts +37 -0
- package/dist/render/resolve-expressions.js +309 -0
- package/dist/render/resolve-expressions.js.map +1 -0
- package/dist/render/responsive-style-css.d.ts +42 -0
- package/dist/render/responsive-style-css.js +123 -0
- package/dist/render/responsive-style-css.js.map +1 -0
- package/dist/render/responsive.d.ts +49 -0
- package/dist/render/responsive.js +99 -0
- package/dist/render/responsive.js.map +1 -0
- package/dist/render/scoped-css.d.ts +71 -0
- package/dist/render/scoped-css.js +102 -0
- package/dist/render/scoped-css.js.map +1 -0
- package/dist/render/shell-selection.d.ts +69 -0
- package/dist/render/shell-selection.js +117 -0
- package/dist/render/shell-selection.js.map +1 -0
- package/dist/render/states-css.d.ts +32 -0
- package/dist/render/states-css.js +63 -0
- package/dist/render/states-css.js.map +1 -0
- package/dist/render/surface-data-context.d.ts +18 -0
- package/dist/render/surface-data-context.js +21 -0
- package/dist/render/surface-data-context.js.map +1 -0
- package/dist/render/surface-event-bus.d.ts +19 -0
- package/dist/render/surface-event-bus.js +68 -0
- package/dist/render/surface-event-bus.js.map +1 -0
- package/dist/render/surface-event-context.d.ts +11 -0
- package/dist/render/surface-event-context.js +12 -0
- package/dist/render/surface-event-context.js.map +1 -0
- package/dist/render/surface-id-context.d.ts +8 -0
- package/dist/render/surface-id-context.js +9 -0
- package/dist/render/surface-id-context.js.map +1 -0
- package/dist/render/theme-utils.d.ts +14 -0
- package/dist/render/theme-utils.js +15 -0
- package/dist/render/theme-utils.js.map +1 -0
- package/dist/render/types.d.ts +282 -0
- package/dist/render/types.js +9 -0
- package/dist/render/types.js.map +1 -0
- package/dist/render/visibility-css.d.ts +42 -0
- package/dist/render/visibility-css.js +119 -0
- package/dist/render/visibility-css.js.map +1 -0
- package/dist/render/width-scope.d.ts +34 -0
- package/dist/render/width-scope.js +44 -0
- package/dist/render/width-scope.js.map +1 -0
- package/dist/render/write-only-sources.d.ts +33 -0
- package/dist/render/write-only-sources.js +99 -0
- package/dist/render/write-only-sources.js.map +1 -0
- package/dist/routing/index.d.ts +14 -0
- package/dist/routing/index.js +15 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/router.d.ts +42 -0
- package/dist/routing/router.js +218 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/routing/types.d.ts +124 -0
- package/dist/routing/types.js +9 -0
- package/dist/routing/types.js.map +1 -0
- package/dist/seo/generator.d.ts +39 -0
- package/dist/seo/generator.js +236 -0
- package/dist/seo/generator.js.map +1 -0
- package/dist/seo/index.d.ts +14 -0
- package/dist/seo/index.js +15 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/types.d.ts +181 -0
- package/dist/seo/types.js +9 -0
- package/dist/seo/types.js.map +1 -0
- package/dist/state/index.d.ts +15 -0
- package/dist/state/index.js +16 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/manager.d.ts +33 -0
- package/dist/state/manager.js +81 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/store.d.ts +40 -0
- package/dist/state/store.js +145 -0
- package/dist/state/store.js.map +1 -0
- package/dist/state/types.d.ts +107 -0
- package/dist/state/types.js +9 -0
- package/dist/state/types.js.map +1 -0
- package/dist/surface/expression.d.ts +65 -0
- package/dist/surface/expression.js +179 -0
- package/dist/surface/expression.js.map +1 -0
- package/dist/surface/index.d.ts +32 -0
- package/dist/surface/index.js +25 -0
- package/dist/surface/index.js.map +1 -0
- package/dist/surface/interpreter.d.ts +96 -0
- package/dist/surface/interpreter.js +231 -0
- package/dist/surface/interpreter.js.map +1 -0
- package/dist/surface/layout.d.ts +54 -0
- package/dist/surface/layout.js +288 -0
- package/dist/surface/layout.js.map +1 -0
- package/dist/surface/output.d.ts +90 -0
- package/dist/surface/output.js +104 -0
- package/dist/surface/output.js.map +1 -0
- package/dist/surface/primitives.d.ts +180 -0
- package/dist/surface/primitives.js +339 -0
- package/dist/surface/primitives.js.map +1 -0
- package/dist/surface/renderer.d.ts +96 -0
- package/dist/surface/renderer.js +190 -0
- package/dist/surface/renderer.js.map +1 -0
- package/dist/surface/schemas.d.ts +181 -0
- package/dist/surface/schemas.js +142 -0
- package/dist/surface/schemas.js.map +1 -0
- package/dist/surface/transforms.d.ts +144 -0
- package/dist/surface/transforms.js +120 -0
- package/dist/surface/transforms.js.map +1 -0
- package/dist/surface/types.d.ts +160 -0
- package/dist/surface/types.js +51 -0
- package/dist/surface/types.js.map +1 -0
- package/dist/surface/validation.d.ts +123 -0
- package/dist/surface/validation.js +147 -0
- package/dist/surface/validation.js.map +1 -0
- package/dist/validator.d.ts +55 -0
- package/dist/validator.js +100 -0
- package/dist/validator.js.map +1 -0
- package/package.json +106 -3
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout System
|
|
3
|
+
*
|
|
4
|
+
* Slot and layout resolution for surfaces
|
|
5
|
+
*
|
|
6
|
+
* The layout system handles:
|
|
7
|
+
* - Slot resolution (named slots with fallback content)
|
|
8
|
+
* - Layout composition (nesting surfaces)
|
|
9
|
+
* - Conditional rendering
|
|
10
|
+
* - Loop expansion
|
|
11
|
+
*
|
|
12
|
+
* @module @pwfabric/runtime/surface/layout
|
|
13
|
+
*/
|
|
14
|
+
import { createNode, createChildContext } from './types.js';
|
|
15
|
+
import { evaluate, createExpressionContext, } from './expression.js';
|
|
16
|
+
import { isPrimitive } from './primitives.js';
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a layout definition into render nodes
|
|
19
|
+
*/
|
|
20
|
+
export function resolveLayout(layout, context) {
|
|
21
|
+
const exprContext = createExpressionContext(context.data);
|
|
22
|
+
return resolveLayoutNode(layout, context, exprContext);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a single layout node
|
|
26
|
+
*/
|
|
27
|
+
function resolveLayoutNode(layout, context, exprContext) {
|
|
28
|
+
// Handle conditional rendering
|
|
29
|
+
if (layout.if) {
|
|
30
|
+
const condResult = evaluate(layout.if, exprContext);
|
|
31
|
+
if (!condResult.success) {
|
|
32
|
+
return { success: false, error: `Condition error: ${condResult.error}` };
|
|
33
|
+
}
|
|
34
|
+
if (!condResult.value) {
|
|
35
|
+
// Condition is false, render nothing
|
|
36
|
+
return { success: true, nodes: [] };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Handle loop expansion
|
|
40
|
+
if (layout.each) {
|
|
41
|
+
return resolveLoop(layout, context, exprContext);
|
|
42
|
+
}
|
|
43
|
+
// Handle slot
|
|
44
|
+
if (layout.slot) {
|
|
45
|
+
return resolveSlot(layout, context, exprContext);
|
|
46
|
+
}
|
|
47
|
+
// Handle primitive or custom component
|
|
48
|
+
return resolvePrimitive(layout, context, exprContext);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a loop layout into multiple nodes
|
|
52
|
+
*/
|
|
53
|
+
function resolveLoop(layout, context, exprContext) {
|
|
54
|
+
const { each } = layout;
|
|
55
|
+
if (!each) {
|
|
56
|
+
return { success: false, error: 'Loop layout missing each config' };
|
|
57
|
+
}
|
|
58
|
+
const itemsResult = evaluate(each.items, exprContext);
|
|
59
|
+
if (!itemsResult.success) {
|
|
60
|
+
return { success: false, error: `Loop items error: ${itemsResult.error}` };
|
|
61
|
+
}
|
|
62
|
+
const items = itemsResult.value;
|
|
63
|
+
if (!Array.isArray(items)) {
|
|
64
|
+
return { success: false, error: `Loop items must be an array, got ${typeof items}` };
|
|
65
|
+
}
|
|
66
|
+
const nodes = [];
|
|
67
|
+
for (let index = 0; index < items.length; index++) {
|
|
68
|
+
const item = items[index];
|
|
69
|
+
// Create child context with loop variables
|
|
70
|
+
const loopData = {
|
|
71
|
+
[each.as]: item,
|
|
72
|
+
[`${each.as}Index`]: index,
|
|
73
|
+
[`${each.as}First`]: index === 0,
|
|
74
|
+
[`${each.as}Last`]: index === items.length - 1,
|
|
75
|
+
};
|
|
76
|
+
const childContext = createChildContext(context, loopData);
|
|
77
|
+
const childExprContext = createExpressionContext({ ...exprContext.data, ...loopData });
|
|
78
|
+
// Generate key
|
|
79
|
+
let key;
|
|
80
|
+
if (each.key) {
|
|
81
|
+
const keyResult = evaluate(each.key, childExprContext);
|
|
82
|
+
key = keyResult.success ? String(keyResult.value) : `loop-${index}`;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
key = `loop-${index}`;
|
|
86
|
+
}
|
|
87
|
+
// Resolve children for this iteration
|
|
88
|
+
if (layout.children) {
|
|
89
|
+
for (const child of layout.children) {
|
|
90
|
+
const childResult = resolveLayoutNode(child, childContext, childExprContext);
|
|
91
|
+
if (!childResult.success) {
|
|
92
|
+
return childResult;
|
|
93
|
+
}
|
|
94
|
+
// Add key to each child
|
|
95
|
+
for (const node of childResult.nodes) {
|
|
96
|
+
nodes.push(createNode(node.type, { ...node.props, key }, node.children));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { success: true, nodes };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolve a slot layout
|
|
105
|
+
*/
|
|
106
|
+
function resolveSlot(layout, context, exprContext) {
|
|
107
|
+
const slotName = layout.slot;
|
|
108
|
+
if (!slotName) {
|
|
109
|
+
return { success: false, error: 'Slot layout missing slot name' };
|
|
110
|
+
}
|
|
111
|
+
const slotContent = context.slots.get(slotName);
|
|
112
|
+
if (slotContent && slotContent.length > 0) {
|
|
113
|
+
// Slot has content, use it
|
|
114
|
+
return { success: true, nodes: slotContent };
|
|
115
|
+
}
|
|
116
|
+
// No slot content, use fallback (children)
|
|
117
|
+
if (layout.children) {
|
|
118
|
+
const nodes = [];
|
|
119
|
+
for (const child of layout.children) {
|
|
120
|
+
const childResult = resolveLayoutNode(child, context, exprContext);
|
|
121
|
+
if (!childResult.success) {
|
|
122
|
+
return childResult;
|
|
123
|
+
}
|
|
124
|
+
nodes.push(...childResult.nodes);
|
|
125
|
+
}
|
|
126
|
+
return { success: true, nodes };
|
|
127
|
+
}
|
|
128
|
+
// No fallback either
|
|
129
|
+
return { success: true, nodes: [] };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Resolve a primitive or custom component
|
|
133
|
+
*/
|
|
134
|
+
function resolvePrimitive(layout, context, exprContext) {
|
|
135
|
+
const { type, props = {}, children = [] } = layout;
|
|
136
|
+
// Resolve props (evaluate expressions in prop values)
|
|
137
|
+
const resolvedProps = {};
|
|
138
|
+
for (const [key, value] of Object.entries(props)) {
|
|
139
|
+
if (typeof value === 'string' && value.startsWith('{{') && value.endsWith('}}')) {
|
|
140
|
+
// Expression prop
|
|
141
|
+
const expr = value.slice(2, -2).trim();
|
|
142
|
+
const result = evaluate(expr, exprContext);
|
|
143
|
+
if (!result.success) {
|
|
144
|
+
return { success: false, error: `Prop ${key} expression error: ${result.error}` };
|
|
145
|
+
}
|
|
146
|
+
resolvedProps[key] = result.value;
|
|
147
|
+
}
|
|
148
|
+
else if (typeof value === 'string' && value.includes('{{')) {
|
|
149
|
+
// Template string with interpolation
|
|
150
|
+
const result = interpolateString(value, exprContext);
|
|
151
|
+
if (!result.success) {
|
|
152
|
+
return { success: false, error: `Prop ${key} interpolation error: ${result.error}` };
|
|
153
|
+
}
|
|
154
|
+
resolvedProps[key] = result.value;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
resolvedProps[key] = value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Resolve children recursively
|
|
161
|
+
const resolvedChildren = [];
|
|
162
|
+
for (const child of children) {
|
|
163
|
+
const childResult = resolveLayoutNode(child, context, exprContext);
|
|
164
|
+
if (!childResult.success) {
|
|
165
|
+
return childResult;
|
|
166
|
+
}
|
|
167
|
+
resolvedChildren.push(...childResult.nodes);
|
|
168
|
+
}
|
|
169
|
+
// Validate primitive type
|
|
170
|
+
if (!isPrimitive(type) && !type.includes(':')) {
|
|
171
|
+
// Unknown type - could be a custom component, let it pass
|
|
172
|
+
}
|
|
173
|
+
const node = createNode(type, resolvedProps, resolvedChildren);
|
|
174
|
+
return { success: true, nodes: [node] };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Interpolate a string with expressions
|
|
178
|
+
*/
|
|
179
|
+
function interpolateString(template, exprContext) {
|
|
180
|
+
const pattern = /\{\{(.+?)\}\}/g;
|
|
181
|
+
let result = template;
|
|
182
|
+
let match;
|
|
183
|
+
// Need to reset lastIndex since we're using the regex multiple times
|
|
184
|
+
pattern.lastIndex = 0;
|
|
185
|
+
const replacements = [];
|
|
186
|
+
while ((match = pattern.exec(template)) !== null) {
|
|
187
|
+
const placeholder = match[0];
|
|
188
|
+
const expression = match[1];
|
|
189
|
+
if (!expression)
|
|
190
|
+
continue;
|
|
191
|
+
const evalResult = evaluate(expression.trim(), exprContext);
|
|
192
|
+
if (!evalResult.success) {
|
|
193
|
+
return { success: false, error: evalResult.error };
|
|
194
|
+
}
|
|
195
|
+
replacements.push({ from: placeholder, to: String(evalResult.value ?? '') });
|
|
196
|
+
}
|
|
197
|
+
for (const { from, to } of replacements) {
|
|
198
|
+
result = result.replace(from, to);
|
|
199
|
+
}
|
|
200
|
+
return { success: true, value: result };
|
|
201
|
+
}
|
|
202
|
+
// ============================================================
|
|
203
|
+
// SLOT MANAGEMENT
|
|
204
|
+
// ============================================================
|
|
205
|
+
/**
|
|
206
|
+
* Create a slot map from slot content
|
|
207
|
+
*/
|
|
208
|
+
export function createSlotMap(slots) {
|
|
209
|
+
return new Map(Object.entries(slots));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Extract slots from children based on slot attribute
|
|
213
|
+
*/
|
|
214
|
+
export function extractSlots(children) {
|
|
215
|
+
const defaultSlot = [];
|
|
216
|
+
const namedSlots = new Map();
|
|
217
|
+
for (const child of children) {
|
|
218
|
+
const slotName = child.props.slot;
|
|
219
|
+
if (slotName) {
|
|
220
|
+
const existing = namedSlots.get(slotName) ?? [];
|
|
221
|
+
existing.push(child);
|
|
222
|
+
namedSlots.set(slotName, existing);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
defaultSlot.push(child);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return { default: defaultSlot, named: namedSlots };
|
|
229
|
+
}
|
|
230
|
+
// ============================================================
|
|
231
|
+
// LAYOUT COMPOSITION
|
|
232
|
+
// ============================================================
|
|
233
|
+
/**
|
|
234
|
+
* Compose multiple layouts into one
|
|
235
|
+
*/
|
|
236
|
+
export function composeLayouts(layouts, context) {
|
|
237
|
+
const nodes = [];
|
|
238
|
+
for (const layout of layouts) {
|
|
239
|
+
const result = resolveLayout(layout, context);
|
|
240
|
+
if (!result.success) {
|
|
241
|
+
return result;
|
|
242
|
+
}
|
|
243
|
+
nodes.push(...result.nodes);
|
|
244
|
+
}
|
|
245
|
+
return { success: true, nodes };
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Wrap nodes in a container
|
|
249
|
+
*/
|
|
250
|
+
export function wrapInContainer(nodes, props) {
|
|
251
|
+
return createNode('container', props ?? {}, nodes);
|
|
252
|
+
}
|
|
253
|
+
// ============================================================
|
|
254
|
+
// LAYOUT VALIDATION
|
|
255
|
+
// ============================================================
|
|
256
|
+
/**
|
|
257
|
+
* Validate a layout definition
|
|
258
|
+
*/
|
|
259
|
+
export function validateLayout(layout) {
|
|
260
|
+
const errors = [];
|
|
261
|
+
// Must have a type
|
|
262
|
+
if (!layout.type) {
|
|
263
|
+
errors.push('Layout must have a type');
|
|
264
|
+
}
|
|
265
|
+
// Validate each config
|
|
266
|
+
if (layout.each) {
|
|
267
|
+
if (!layout.each.items) {
|
|
268
|
+
errors.push('Loop layout must have items expression');
|
|
269
|
+
}
|
|
270
|
+
if (!layout.each.as) {
|
|
271
|
+
errors.push('Loop layout must have as variable name');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Validate children recursively
|
|
275
|
+
if (layout.children) {
|
|
276
|
+
for (let i = 0; i < layout.children.length; i++) {
|
|
277
|
+
const child = layout.children[i];
|
|
278
|
+
if (!child)
|
|
279
|
+
continue;
|
|
280
|
+
const childResult = validateLayout(child);
|
|
281
|
+
if (!childResult.valid) {
|
|
282
|
+
errors.push(...childResult.errors.map((e) => `children[${i}]: ${e}`));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return { valid: errors.length === 0, errors };
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/surface/layout.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Layout System\n *\n * Slot and layout resolution for surfaces\n *\n * The layout system handles:\n * - Slot resolution (named slots with fallback content)\n * - Layout composition (nesting surfaces)\n * - Conditional rendering\n * - Loop expansion\n *\n * @module @pwfabric/runtime/surface/layout\n */\n\nimport type { RenderNode, RenderContext, LayoutJSON } from './types.js'\nimport { createNode, createChildContext } from './types.js'\nimport {\n evaluate,\n createExpressionContext,\n type ExpressionContext,\n type ExpressionResult,\n} from './expression.js'\nimport { isPrimitive } from './primitives.js'\n\n// ============================================================\n// LAYOUT RESOLUTION\n// ============================================================\n\n/**\n * Layout resolution result\n */\nexport type LayoutResult =\n | { readonly success: true; readonly nodes: readonly RenderNode[] }\n | { readonly success: false; readonly error: string }\n\n/**\n * Resolve a layout definition into render nodes\n */\nexport function resolveLayout(layout: LayoutJSON, context: RenderContext): LayoutResult {\n const exprContext = createExpressionContext(context.data)\n\n return resolveLayoutNode(layout, context, exprContext)\n}\n\n/**\n * Resolve a single layout node\n */\nfunction resolveLayoutNode(\n layout: LayoutJSON,\n context: RenderContext,\n exprContext: ExpressionContext\n): LayoutResult {\n // Handle conditional rendering\n if (layout.if) {\n const condResult = evaluate(layout.if, exprContext)\n if (!condResult.success) {\n return { success: false, error: `Condition error: ${condResult.error}` }\n }\n if (!condResult.value) {\n // Condition is false, render nothing\n return { success: true, nodes: [] }\n }\n }\n\n // Handle loop expansion\n if (layout.each) {\n return resolveLoop(layout, context, exprContext)\n }\n\n // Handle slot\n if (layout.slot) {\n return resolveSlot(layout, context, exprContext)\n }\n\n // Handle primitive or custom component\n return resolvePrimitive(layout, context, exprContext)\n}\n\n/**\n * Resolve a loop layout into multiple nodes\n */\nfunction resolveLoop(\n layout: LayoutJSON,\n context: RenderContext,\n exprContext: ExpressionContext\n): LayoutResult {\n const { each } = layout\n if (!each) {\n return { success: false, error: 'Loop layout missing each config' }\n }\n\n const itemsResult = evaluate(each.items, exprContext)\n if (!itemsResult.success) {\n return { success: false, error: `Loop items error: ${itemsResult.error}` }\n }\n\n const items = itemsResult.value\n if (!Array.isArray(items)) {\n return { success: false, error: `Loop items must be an array, got ${typeof items}` }\n }\n\n const nodes: RenderNode[] = []\n\n for (let index = 0; index < items.length; index++) {\n const item = items[index]\n\n // Create child context with loop variables\n const loopData: Record<string, unknown> = {\n [each.as]: item,\n [`${each.as}Index`]: index,\n [`${each.as}First`]: index === 0,\n [`${each.as}Last`]: index === items.length - 1,\n }\n\n const childContext = createChildContext(context, loopData)\n const childExprContext = createExpressionContext({ ...exprContext.data, ...loopData })\n\n // Generate key\n let key: string\n if (each.key) {\n const keyResult = evaluate(each.key, childExprContext)\n key = keyResult.success ? String(keyResult.value) : `loop-${index}`\n } else {\n key = `loop-${index}`\n }\n\n // Resolve children for this iteration\n if (layout.children) {\n for (const child of layout.children) {\n const childResult = resolveLayoutNode(child, childContext, childExprContext)\n if (!childResult.success) {\n return childResult\n }\n // Add key to each child\n for (const node of childResult.nodes) {\n nodes.push(createNode(node.type, { ...node.props, key }, node.children))\n }\n }\n }\n }\n\n return { success: true, nodes }\n}\n\n/**\n * Resolve a slot layout\n */\nfunction resolveSlot(\n layout: LayoutJSON,\n context: RenderContext,\n exprContext: ExpressionContext\n): LayoutResult {\n const slotName = layout.slot\n if (!slotName) {\n return { success: false, error: 'Slot layout missing slot name' }\n }\n const slotContent = context.slots.get(slotName)\n\n if (slotContent && slotContent.length > 0) {\n // Slot has content, use it\n return { success: true, nodes: slotContent }\n }\n\n // No slot content, use fallback (children)\n if (layout.children) {\n const nodes: RenderNode[] = []\n for (const child of layout.children) {\n const childResult = resolveLayoutNode(child, context, exprContext)\n if (!childResult.success) {\n return childResult\n }\n nodes.push(...childResult.nodes)\n }\n return { success: true, nodes }\n }\n\n // No fallback either\n return { success: true, nodes: [] }\n}\n\n/**\n * Resolve a primitive or custom component\n */\nfunction resolvePrimitive(\n layout: LayoutJSON,\n context: RenderContext,\n exprContext: ExpressionContext\n): LayoutResult {\n const { type, props = {}, children = [] } = layout\n\n // Resolve props (evaluate expressions in prop values)\n const resolvedProps: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(props)) {\n if (typeof value === 'string' && value.startsWith('{{') && value.endsWith('}}')) {\n // Expression prop\n const expr = value.slice(2, -2).trim()\n const result = evaluate(expr, exprContext)\n if (!result.success) {\n return { success: false, error: `Prop ${key} expression error: ${result.error}` }\n }\n resolvedProps[key] = result.value\n } else if (typeof value === 'string' && value.includes('{{')) {\n // Template string with interpolation\n const result = interpolateString(value, exprContext)\n if (!result.success) {\n return { success: false, error: `Prop ${key} interpolation error: ${result.error}` }\n }\n resolvedProps[key] = result.value\n } else {\n resolvedProps[key] = value\n }\n }\n\n // Resolve children recursively\n const resolvedChildren: RenderNode[] = []\n for (const child of children) {\n const childResult = resolveLayoutNode(child, context, exprContext)\n if (!childResult.success) {\n return childResult\n }\n resolvedChildren.push(...childResult.nodes)\n }\n\n // Validate primitive type\n if (!isPrimitive(type) && !type.includes(':')) {\n // Unknown type - could be a custom component, let it pass\n }\n\n const node = createNode(type, resolvedProps, resolvedChildren)\n return { success: true, nodes: [node] }\n}\n\n/**\n * Interpolate a string with expressions\n */\nfunction interpolateString(\n template: string,\n exprContext: ExpressionContext\n): ExpressionResult<string> {\n const pattern = /\\{\\{(.+?)\\}\\}/g\n let result = template\n let match: RegExpExecArray | null\n\n // Need to reset lastIndex since we're using the regex multiple times\n pattern.lastIndex = 0\n\n const replacements: { from: string; to: string }[] = []\n\n while ((match = pattern.exec(template)) !== null) {\n const placeholder = match[0]\n const expression = match[1]\n if (!expression) continue\n const evalResult = evaluate(expression.trim(), exprContext)\n if (!evalResult.success) {\n return { success: false, error: evalResult.error }\n }\n replacements.push({ from: placeholder, to: String(evalResult.value ?? '') })\n }\n\n for (const { from, to } of replacements) {\n result = result.replace(from, to)\n }\n\n return { success: true, value: result }\n}\n\n// ============================================================\n// SLOT MANAGEMENT\n// ============================================================\n\n/**\n * Create a slot map from slot content\n */\nexport function createSlotMap(\n slots: Record<string, readonly RenderNode[]>\n): Map<string, readonly RenderNode[]> {\n return new Map(Object.entries(slots))\n}\n\n/**\n * Extract slots from children based on slot attribute\n */\nexport function extractSlots(children: readonly RenderNode[]): {\n default: readonly RenderNode[]\n named: Map<string, readonly RenderNode[]>\n} {\n const defaultSlot: RenderNode[] = []\n const namedSlots = new Map<string, RenderNode[]>()\n\n for (const child of children) {\n const slotName = child.props.slot as string | undefined\n if (slotName) {\n const existing = namedSlots.get(slotName) ?? []\n existing.push(child)\n namedSlots.set(slotName, existing)\n } else {\n defaultSlot.push(child)\n }\n }\n\n return { default: defaultSlot, named: namedSlots }\n}\n\n// ============================================================\n// LAYOUT COMPOSITION\n// ============================================================\n\n/**\n * Compose multiple layouts into one\n */\nexport function composeLayouts(\n layouts: readonly LayoutJSON[],\n context: RenderContext\n): LayoutResult {\n const nodes: RenderNode[] = []\n\n for (const layout of layouts) {\n const result = resolveLayout(layout, context)\n if (!result.success) {\n return result\n }\n nodes.push(...result.nodes)\n }\n\n return { success: true, nodes }\n}\n\n/**\n * Wrap nodes in a container\n */\nexport function wrapInContainer(\n nodes: readonly RenderNode[],\n props?: Record<string, unknown>\n): RenderNode {\n return createNode('container', props ?? {}, nodes)\n}\n\n// ============================================================\n// LAYOUT VALIDATION\n// ============================================================\n\n/**\n * Validate a layout definition\n */\nexport function validateLayout(layout: LayoutJSON): { valid: boolean; errors: string[] } {\n const errors: string[] = []\n\n // Must have a type\n if (!layout.type) {\n errors.push('Layout must have a type')\n }\n\n // Validate each config\n if (layout.each) {\n if (!layout.each.items) {\n errors.push('Loop layout must have items expression')\n }\n if (!layout.each.as) {\n errors.push('Loop layout must have as variable name')\n }\n }\n\n // Validate children recursively\n if (layout.children) {\n for (let i = 0; i < layout.children.length; i++) {\n const child = layout.children[i]\n if (!child) continue\n const childResult = validateLayout(child)\n if (!childResult.valid) {\n errors.push(...childResult.errors.map((e) => `children[${i}]: ${e}`))\n }\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n"]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed Output Factories
|
|
3
|
+
*
|
|
4
|
+
* Typed wrappers for BaseSurfaceOutput.data.
|
|
5
|
+
* These do NOT modify @pwfabric/contracts. They extend the contract types
|
|
6
|
+
* with narrowed data fields and provide factory functions that validate.
|
|
7
|
+
*
|
|
8
|
+
* @module @pwfabric/runtime/surface/output
|
|
9
|
+
*/
|
|
10
|
+
import type { WebSurfaceOutput, ApiSurfaceOutput, CliSurfaceOutput } from '@pwfabric/contracts';
|
|
11
|
+
/**
|
|
12
|
+
* Web output with narrowed data type
|
|
13
|
+
*/
|
|
14
|
+
export interface TypedWebOutput extends WebSurfaceOutput {
|
|
15
|
+
readonly data: {
|
|
16
|
+
readonly html: string;
|
|
17
|
+
readonly css?: string;
|
|
18
|
+
readonly head?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* API output with narrowed data type
|
|
23
|
+
*/
|
|
24
|
+
export interface TypedApiOutput extends ApiSurfaceOutput {
|
|
25
|
+
readonly data: {
|
|
26
|
+
readonly json: unknown;
|
|
27
|
+
readonly status: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* CLI output with narrowed data type
|
|
32
|
+
*/
|
|
33
|
+
export interface TypedCliOutput extends CliSurfaceOutput {
|
|
34
|
+
readonly data: {
|
|
35
|
+
readonly formatted: string;
|
|
36
|
+
readonly raw?: unknown;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Result of creating a typed output
|
|
41
|
+
*/
|
|
42
|
+
export type OutputFactoryResult<T> = {
|
|
43
|
+
readonly success: true;
|
|
44
|
+
readonly output: T;
|
|
45
|
+
} | {
|
|
46
|
+
readonly success: false;
|
|
47
|
+
readonly errors: readonly string[];
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Create a validated TypedWebOutput.
|
|
51
|
+
*
|
|
52
|
+
* Validates the data shape and returns a typed output or errors.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createWebOutput(options: {
|
|
55
|
+
readonly data: {
|
|
56
|
+
readonly html: string;
|
|
57
|
+
readonly css?: string;
|
|
58
|
+
readonly head?: string;
|
|
59
|
+
};
|
|
60
|
+
readonly component?: unknown;
|
|
61
|
+
readonly html?: string;
|
|
62
|
+
}): OutputFactoryResult<TypedWebOutput>;
|
|
63
|
+
/**
|
|
64
|
+
* Create a validated TypedApiOutput.
|
|
65
|
+
*
|
|
66
|
+
* Validates the data shape and returns a typed output or errors.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createApiOutput(options: {
|
|
69
|
+
readonly data: {
|
|
70
|
+
readonly json: unknown;
|
|
71
|
+
readonly status: number;
|
|
72
|
+
};
|
|
73
|
+
readonly status: number;
|
|
74
|
+
readonly headers?: Record<string, string>;
|
|
75
|
+
readonly body?: unknown;
|
|
76
|
+
}): OutputFactoryResult<TypedApiOutput>;
|
|
77
|
+
/**
|
|
78
|
+
* Create a validated TypedCliOutput.
|
|
79
|
+
*
|
|
80
|
+
* Validates the data shape and returns a typed output or errors.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createCliOutput(options: {
|
|
83
|
+
readonly data: {
|
|
84
|
+
readonly formatted: string;
|
|
85
|
+
readonly raw?: unknown;
|
|
86
|
+
};
|
|
87
|
+
readonly exitCode: number;
|
|
88
|
+
readonly stdout?: string;
|
|
89
|
+
readonly stderr?: string;
|
|
90
|
+
}): OutputFactoryResult<TypedCliOutput>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed Output Factories
|
|
3
|
+
*
|
|
4
|
+
* Typed wrappers for BaseSurfaceOutput.data.
|
|
5
|
+
* These do NOT modify @pwfabric/contracts. They extend the contract types
|
|
6
|
+
* with narrowed data fields and provide factory functions that validate.
|
|
7
|
+
*
|
|
8
|
+
* @module @pwfabric/runtime/surface/output
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
// ============================================================
|
|
12
|
+
// ZOD SCHEMAS
|
|
13
|
+
// ============================================================
|
|
14
|
+
const webOutputDataSchema = z.object({
|
|
15
|
+
html: z.string(),
|
|
16
|
+
css: z.string().optional(),
|
|
17
|
+
head: z.string().optional(),
|
|
18
|
+
});
|
|
19
|
+
const apiOutputDataSchema = z.object({
|
|
20
|
+
json: z.unknown(),
|
|
21
|
+
status: z.number().int().min(100).max(599),
|
|
22
|
+
});
|
|
23
|
+
const cliOutputDataSchema = z.object({
|
|
24
|
+
formatted: z.string(),
|
|
25
|
+
raw: z.unknown().optional(),
|
|
26
|
+
});
|
|
27
|
+
// ============================================================
|
|
28
|
+
// FACTORY FUNCTIONS
|
|
29
|
+
// ============================================================
|
|
30
|
+
/**
|
|
31
|
+
* Create a validated TypedWebOutput.
|
|
32
|
+
*
|
|
33
|
+
* Validates the data shape and returns a typed output or errors.
|
|
34
|
+
*/
|
|
35
|
+
export function createWebOutput(options) {
|
|
36
|
+
const dataResult = webOutputDataSchema.safeParse(options.data);
|
|
37
|
+
if (!dataResult.success) {
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const data = {
|
|
44
|
+
html: dataResult.data.html,
|
|
45
|
+
...(dataResult.data.css !== undefined ? { css: dataResult.data.css } : {}),
|
|
46
|
+
...(dataResult.data.head !== undefined ? { head: dataResult.data.head } : {}),
|
|
47
|
+
};
|
|
48
|
+
const output = {
|
|
49
|
+
type: 'web',
|
|
50
|
+
data,
|
|
51
|
+
...(options.component !== undefined ? { component: options.component } : {}),
|
|
52
|
+
...(options.html !== undefined ? { html: options.html } : {}),
|
|
53
|
+
};
|
|
54
|
+
return { success: true, output };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a validated TypedApiOutput.
|
|
58
|
+
*
|
|
59
|
+
* Validates the data shape and returns a typed output or errors.
|
|
60
|
+
*/
|
|
61
|
+
export function createApiOutput(options) {
|
|
62
|
+
const dataResult = apiOutputDataSchema.safeParse(options.data);
|
|
63
|
+
if (!dataResult.success) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const data = {
|
|
70
|
+
json: dataResult.data.json,
|
|
71
|
+
status: dataResult.data.status,
|
|
72
|
+
};
|
|
73
|
+
const output = {
|
|
74
|
+
type: 'api',
|
|
75
|
+
data,
|
|
76
|
+
status: options.status,
|
|
77
|
+
body: options.body ?? null,
|
|
78
|
+
...(options.headers ? { headers: options.headers } : {}),
|
|
79
|
+
};
|
|
80
|
+
return { success: true, output };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a validated TypedCliOutput.
|
|
84
|
+
*
|
|
85
|
+
* Validates the data shape and returns a typed output or errors.
|
|
86
|
+
*/
|
|
87
|
+
export function createCliOutput(options) {
|
|
88
|
+
const dataResult = cliOutputDataSchema.safeParse(options.data);
|
|
89
|
+
if (!dataResult.success) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const output = {
|
|
96
|
+
type: 'cli',
|
|
97
|
+
data: dataResult.data,
|
|
98
|
+
exitCode: options.exitCode,
|
|
99
|
+
...(options.stdout !== undefined && { stdout: options.stdout }),
|
|
100
|
+
...(options.stderr !== undefined && { stderr: options.stderr }),
|
|
101
|
+
};
|
|
102
|
+
return { success: true, output };
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/surface/output.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Typed Output Factories\n *\n * Typed wrappers for BaseSurfaceOutput.data.\n * These do NOT modify @pwfabric/contracts. They extend the contract types\n * with narrowed data fields and provide factory functions that validate.\n *\n * @module @pwfabric/runtime/surface/output\n */\n\nimport { z } from 'zod'\nimport type { WebSurfaceOutput, ApiSurfaceOutput, CliSurfaceOutput } from '@pwfabric/contracts'\n\n// ============================================================\n// TYPED OUTPUT INTERFACES\n// ============================================================\n\n/**\n * Web output with narrowed data type\n */\nexport interface TypedWebOutput extends WebSurfaceOutput {\n readonly data: {\n readonly html: string\n readonly css?: string\n readonly head?: string\n }\n}\n\n/**\n * API output with narrowed data type\n */\nexport interface TypedApiOutput extends ApiSurfaceOutput {\n readonly data: {\n readonly json: unknown\n readonly status: number\n }\n}\n\n/**\n * CLI output with narrowed data type\n */\nexport interface TypedCliOutput extends CliSurfaceOutput {\n readonly data: {\n readonly formatted: string\n readonly raw?: unknown\n }\n}\n\n// ============================================================\n// ZOD SCHEMAS\n// ============================================================\n\nconst webOutputDataSchema = z.object({\n html: z.string(),\n css: z.string().optional(),\n head: z.string().optional(),\n})\n\nconst apiOutputDataSchema = z.object({\n json: z.unknown(),\n status: z.number().int().min(100).max(599),\n})\n\nconst cliOutputDataSchema = z.object({\n formatted: z.string(),\n raw: z.unknown().optional(),\n})\n\n// ============================================================\n// VALIDATION RESULT\n// ============================================================\n\n/**\n * Result of creating a typed output\n */\nexport type OutputFactoryResult<T> =\n | { readonly success: true; readonly output: T }\n | { readonly success: false; readonly errors: readonly string[] }\n\n// ============================================================\n// FACTORY FUNCTIONS\n// ============================================================\n\n/**\n * Create a validated TypedWebOutput.\n *\n * Validates the data shape and returns a typed output or errors.\n */\nexport function createWebOutput(options: {\n readonly data: { readonly html: string; readonly css?: string; readonly head?: string }\n readonly component?: unknown\n readonly html?: string\n}): OutputFactoryResult<TypedWebOutput> {\n const dataResult = webOutputDataSchema.safeParse(options.data)\n\n if (!dataResult.success) {\n return {\n success: false,\n errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),\n }\n }\n\n const data: TypedWebOutput['data'] = {\n html: dataResult.data.html,\n ...(dataResult.data.css !== undefined ? { css: dataResult.data.css } : {}),\n ...(dataResult.data.head !== undefined ? { head: dataResult.data.head } : {}),\n }\n\n const output: TypedWebOutput = {\n type: 'web',\n data,\n ...(options.component !== undefined ? { component: options.component } : {}),\n ...(options.html !== undefined ? { html: options.html } : {}),\n }\n\n return { success: true, output }\n}\n\n/**\n * Create a validated TypedApiOutput.\n *\n * Validates the data shape and returns a typed output or errors.\n */\nexport function createApiOutput(options: {\n readonly data: { readonly json: unknown; readonly status: number }\n readonly status: number\n readonly headers?: Record<string, string>\n readonly body?: unknown\n}): OutputFactoryResult<TypedApiOutput> {\n const dataResult = apiOutputDataSchema.safeParse(options.data)\n\n if (!dataResult.success) {\n return {\n success: false,\n errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),\n }\n }\n\n const data: TypedApiOutput['data'] = {\n json: dataResult.data.json,\n status: dataResult.data.status,\n }\n\n const output: TypedApiOutput = {\n type: 'api',\n data,\n status: options.status,\n body: options.body ?? null,\n ...(options.headers ? { headers: options.headers } : {}),\n }\n\n return { success: true, output }\n}\n\n/**\n * Create a validated TypedCliOutput.\n *\n * Validates the data shape and returns a typed output or errors.\n */\nexport function createCliOutput(options: {\n readonly data: { readonly formatted: string; readonly raw?: unknown }\n readonly exitCode: number\n readonly stdout?: string\n readonly stderr?: string\n}): OutputFactoryResult<TypedCliOutput> {\n const dataResult = cliOutputDataSchema.safeParse(options.data)\n\n if (!dataResult.success) {\n return {\n success: false,\n errors: dataResult.error.issues.map((i) => `data.${i.path.join('.')}: ${i.message}`),\n }\n }\n\n const output: TypedCliOutput = {\n type: 'cli',\n data: dataResult.data,\n exitCode: options.exitCode,\n ...(options.stdout !== undefined && { stdout: options.stdout }),\n ...(options.stderr !== undefined && { stderr: options.stderr }),\n }\n\n return { success: true, output }\n}\n"]}
|