@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,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composition Rule Engine
|
|
3
|
+
*
|
|
4
|
+
* CP7: Validation engine for block compositions
|
|
5
|
+
* Block metadata accessor is now an injectable provider so
|
|
6
|
+
* web-side editor flows can supply install-aware data without depending on
|
|
7
|
+
* the populated runtime singleton.
|
|
8
|
+
*
|
|
9
|
+
* @module @pwfabric/core/blocks/rule-engine
|
|
10
|
+
*/
|
|
11
|
+
import { MAX_NESTING_DEPTH } from '@pwfabric/core';
|
|
12
|
+
import { blockRegistry } from './registry.js';
|
|
13
|
+
import { compositionRules } from './composition-rules.js';
|
|
14
|
+
function definitionToSnapshot(def) {
|
|
15
|
+
return {
|
|
16
|
+
type: def.type,
|
|
17
|
+
name: def.name,
|
|
18
|
+
canHaveChildren: def.canHaveChildren,
|
|
19
|
+
...(def.allowedChildren !== undefined ? { allowedChildren: def.allowedChildren } : {}),
|
|
20
|
+
...(def.allowedParents !== undefined ? { allowedParents: def.allowedParents } : {}),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Default provider — reads from the runtime `blockRegistry` singleton.
|
|
25
|
+
* Returns `undefined` for types absent from the singleton (post-
|
|
26
|
+
* the singleton is empty by default).
|
|
27
|
+
*/
|
|
28
|
+
export const defaultBlockMetaProvider = {
|
|
29
|
+
get(type) {
|
|
30
|
+
const def = blockRegistry.get(type);
|
|
31
|
+
return def ? definitionToSnapshot(def) : undefined;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
// ============================================================
|
|
35
|
+
// ERROR CODES
|
|
36
|
+
// ============================================================
|
|
37
|
+
export const CompositionErrorCode = {
|
|
38
|
+
MAX_DEPTH_EXCEEDED: 'MAX_DEPTH_EXCEEDED',
|
|
39
|
+
INVALID_CHILD: 'INVALID_CHILD',
|
|
40
|
+
INVALID_PARENT: 'INVALID_PARENT',
|
|
41
|
+
NO_CHILDREN_ALLOWED: 'NO_CHILDREN_ALLOWED',
|
|
42
|
+
SELF_NESTING: 'SELF_NESTING',
|
|
43
|
+
UNKNOWN_BLOCK_TYPE: 'UNKNOWN_BLOCK_TYPE',
|
|
44
|
+
ORPHANED_BLOCK: 'ORPHANED_BLOCK',
|
|
45
|
+
};
|
|
46
|
+
// ============================================================
|
|
47
|
+
// RULE ENGINE CLASS
|
|
48
|
+
// ============================================================
|
|
49
|
+
/**
|
|
50
|
+
* Composition Rule Engine
|
|
51
|
+
*
|
|
52
|
+
* Validates block compositions against defined rules.
|
|
53
|
+
*/
|
|
54
|
+
export class CompositionRuleEngine {
|
|
55
|
+
/** Rules for this engine instance (reserved for future custom rule support) */
|
|
56
|
+
rules;
|
|
57
|
+
/** Block metadata accessor */
|
|
58
|
+
meta;
|
|
59
|
+
constructor(rules = compositionRules, meta = defaultBlockMetaProvider) {
|
|
60
|
+
this.rules = rules;
|
|
61
|
+
this.meta = meta;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if a child can be inserted into a parent
|
|
65
|
+
*
|
|
66
|
+
* @param parent - Parent block (null for root level)
|
|
67
|
+
* @param childType - Type of child block to insert
|
|
68
|
+
* @param currentDepth - Current nesting depth
|
|
69
|
+
* @returns Validation result
|
|
70
|
+
*/
|
|
71
|
+
canInsert(parent, childType, currentDepth = 0) {
|
|
72
|
+
const errors = [];
|
|
73
|
+
// Check if child type is registered
|
|
74
|
+
const childDef = this.meta.get(childType);
|
|
75
|
+
if (!childDef) {
|
|
76
|
+
errors.push({
|
|
77
|
+
code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,
|
|
78
|
+
message: `Unknown block type: ${childType}`,
|
|
79
|
+
suggestion: 'Use a registered block type',
|
|
80
|
+
});
|
|
81
|
+
return { valid: false, errors };
|
|
82
|
+
}
|
|
83
|
+
// Root level insertion
|
|
84
|
+
if (parent === null) {
|
|
85
|
+
return { valid: true, errors: [] };
|
|
86
|
+
}
|
|
87
|
+
// Get parent definition
|
|
88
|
+
const parentDef = this.meta.get(parent.type);
|
|
89
|
+
if (!parentDef) {
|
|
90
|
+
errors.push({
|
|
91
|
+
code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,
|
|
92
|
+
message: `Unknown parent block type: ${parent.type}`,
|
|
93
|
+
blockId: parent.id,
|
|
94
|
+
});
|
|
95
|
+
return { valid: false, errors };
|
|
96
|
+
}
|
|
97
|
+
// Check if parent can have children
|
|
98
|
+
if (!parentDef.canHaveChildren) {
|
|
99
|
+
errors.push({
|
|
100
|
+
code: CompositionErrorCode.NO_CHILDREN_ALLOWED,
|
|
101
|
+
message: `${parentDef.name} blocks cannot have children`,
|
|
102
|
+
blockId: parent.id,
|
|
103
|
+
suggestion: `Place the ${childDef.name} block outside of ${parentDef.name}`,
|
|
104
|
+
});
|
|
105
|
+
return { valid: false, errors };
|
|
106
|
+
}
|
|
107
|
+
// Check depth limit
|
|
108
|
+
if (currentDepth >= MAX_NESTING_DEPTH) {
|
|
109
|
+
errors.push({
|
|
110
|
+
code: CompositionErrorCode.MAX_DEPTH_EXCEEDED,
|
|
111
|
+
message: `Maximum nesting depth (${MAX_NESTING_DEPTH}) exceeded`,
|
|
112
|
+
blockId: parent.id,
|
|
113
|
+
suggestion: 'Reduce nesting or restructure your layout',
|
|
114
|
+
});
|
|
115
|
+
return { valid: false, errors };
|
|
116
|
+
}
|
|
117
|
+
// Check allowed children
|
|
118
|
+
if (parentDef.allowedChildren && !parentDef.allowedChildren.includes(childType)) {
|
|
119
|
+
errors.push({
|
|
120
|
+
code: CompositionErrorCode.INVALID_CHILD,
|
|
121
|
+
message: `${childDef.name} is not allowed inside ${parentDef.name}`,
|
|
122
|
+
blockId: parent.id,
|
|
123
|
+
suggestion: `Allowed children: ${parentDef.allowedChildren.join(', ')}`,
|
|
124
|
+
});
|
|
125
|
+
return { valid: false, errors };
|
|
126
|
+
}
|
|
127
|
+
// Check allowed parents
|
|
128
|
+
if (childDef.allowedParents && !childDef.allowedParents.includes(parent.type)) {
|
|
129
|
+
errors.push({
|
|
130
|
+
code: CompositionErrorCode.INVALID_PARENT,
|
|
131
|
+
message: `${childDef.name} should be placed inside ${childDef.allowedParents.join(' or ')}`,
|
|
132
|
+
blockId: parent.id,
|
|
133
|
+
suggestion: `Move the ${childDef.name} into a ${childDef.allowedParents[0]}`,
|
|
134
|
+
});
|
|
135
|
+
// This is a warning, not a hard error
|
|
136
|
+
return { valid: true, errors };
|
|
137
|
+
}
|
|
138
|
+
// Check grid-specific rules (no nested grids)
|
|
139
|
+
if (parent.type === 'grid' && childType === 'grid') {
|
|
140
|
+
errors.push({
|
|
141
|
+
code: CompositionErrorCode.INVALID_CHILD,
|
|
142
|
+
message: 'Grids cannot contain other grids as direct children',
|
|
143
|
+
blockId: parent.id,
|
|
144
|
+
suggestion: 'Wrap the inner grid in a container first',
|
|
145
|
+
});
|
|
146
|
+
return { valid: false, errors };
|
|
147
|
+
}
|
|
148
|
+
return { valid: true, errors: [] };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if a block can be moved to a new parent
|
|
152
|
+
*
|
|
153
|
+
* @param block - Block to move
|
|
154
|
+
* @param newParent - New parent block (null for root level)
|
|
155
|
+
* @param currentDepth - Current nesting depth
|
|
156
|
+
* @returns Validation result
|
|
157
|
+
*/
|
|
158
|
+
canMove(block, newParent, currentDepth = 0) {
|
|
159
|
+
const errors = [];
|
|
160
|
+
// Check for self-nesting
|
|
161
|
+
if (newParent && this.isDescendantOf(newParent, block)) {
|
|
162
|
+
errors.push({
|
|
163
|
+
code: CompositionErrorCode.SELF_NESTING,
|
|
164
|
+
message: 'Cannot move a block into itself or its descendants',
|
|
165
|
+
blockId: block.id,
|
|
166
|
+
suggestion: 'Choose a different location',
|
|
167
|
+
});
|
|
168
|
+
return { valid: false, errors };
|
|
169
|
+
}
|
|
170
|
+
// Use canInsert for other validations
|
|
171
|
+
return this.canInsert(newParent, block.type, currentDepth);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Validate an entire block tree
|
|
175
|
+
*
|
|
176
|
+
* @param blocks - Root level blocks to validate
|
|
177
|
+
* @returns Array of validation errors
|
|
178
|
+
*/
|
|
179
|
+
validateTree(blocks) {
|
|
180
|
+
const errors = [];
|
|
181
|
+
const validateBlock = (block, parent, depth) => {
|
|
182
|
+
// Check block type
|
|
183
|
+
const def = this.meta.get(block.type);
|
|
184
|
+
if (!def) {
|
|
185
|
+
errors.push({
|
|
186
|
+
code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,
|
|
187
|
+
message: `Unknown block type: ${block.type}`,
|
|
188
|
+
blockId: block.id,
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
// Validate insertion
|
|
193
|
+
if (parent !== null) {
|
|
194
|
+
if (depth >= MAX_NESTING_DEPTH) {
|
|
195
|
+
errors.push({
|
|
196
|
+
code: CompositionErrorCode.MAX_DEPTH_EXCEEDED,
|
|
197
|
+
message: `Block at depth ${depth} exceeds maximum nesting depth (${MAX_NESTING_DEPTH})`,
|
|
198
|
+
blockId: block.id,
|
|
199
|
+
suggestion: 'Reduce nesting or restructure your layout',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const insertResult = this.canInsert(parent, block.type, depth);
|
|
204
|
+
errors.push(...insertResult.errors);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Recursively validate children
|
|
208
|
+
if (block.children) {
|
|
209
|
+
// Check if block can have children
|
|
210
|
+
if (!def.canHaveChildren && block.children.length > 0) {
|
|
211
|
+
errors.push({
|
|
212
|
+
code: CompositionErrorCode.NO_CHILDREN_ALLOWED,
|
|
213
|
+
message: `${def.name} blocks cannot have children`,
|
|
214
|
+
blockId: block.id,
|
|
215
|
+
suggestion: 'Remove children from this block',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
for (const child of block.children) {
|
|
219
|
+
validateBlock(child, block, depth + 1);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
for (const block of blocks) {
|
|
224
|
+
validateBlock(block, null, 0);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
valid: errors.length === 0,
|
|
228
|
+
errors,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get the depth of a block in a tree
|
|
233
|
+
*
|
|
234
|
+
* @param blocks - Root level blocks
|
|
235
|
+
* @param targetId - ID of block to find
|
|
236
|
+
* @returns Depth of block or -1 if not found
|
|
237
|
+
*/
|
|
238
|
+
getBlockDepth(blocks, targetId) {
|
|
239
|
+
const findDepth = (blockList, currentDepth) => {
|
|
240
|
+
for (const block of blockList) {
|
|
241
|
+
if (block.id === targetId) {
|
|
242
|
+
return currentDepth;
|
|
243
|
+
}
|
|
244
|
+
if (block.children) {
|
|
245
|
+
const found = findDepth(block.children, currentDepth + 1);
|
|
246
|
+
if (found >= 0)
|
|
247
|
+
return found;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return -1;
|
|
251
|
+
};
|
|
252
|
+
return findDepth(blocks, 0);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Check if a block is a descendant of another block
|
|
256
|
+
*
|
|
257
|
+
* @param block - Block to check descendants of
|
|
258
|
+
* @param potentialAncestor - Potential ancestor block
|
|
259
|
+
* @returns True if block is a descendant
|
|
260
|
+
*/
|
|
261
|
+
isDescendantOf(block, potentialAncestor) {
|
|
262
|
+
if (block.id === potentialAncestor.id) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
if (potentialAncestor.children) {
|
|
266
|
+
for (const child of potentialAncestor.children) {
|
|
267
|
+
if (this.isDescendantOf(block, child)) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// ============================================================
|
|
276
|
+
// SINGLETON INSTANCE
|
|
277
|
+
// ============================================================
|
|
278
|
+
/**
|
|
279
|
+
* Default composition rule engine singleton
|
|
280
|
+
*/
|
|
281
|
+
export const compositionRuleEngine = new CompositionRuleEngine();
|
|
282
|
+
/**
|
|
283
|
+
* Get the default composition rule engine
|
|
284
|
+
*
|
|
285
|
+
* @returns The default rule engine instance
|
|
286
|
+
*/
|
|
287
|
+
export function getCompositionRuleEngine() {
|
|
288
|
+
return compositionRuleEngine;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Create a new composition rule engine
|
|
292
|
+
*
|
|
293
|
+
* @param rules - Optional custom rules
|
|
294
|
+
* @param meta - Optional block metadata provider
|
|
295
|
+
* @returns New rule engine instance
|
|
296
|
+
*/
|
|
297
|
+
export function createCompositionRuleEngine(rules, meta) {
|
|
298
|
+
return new CompositionRuleEngine(rules, meta);
|
|
299
|
+
}
|
|
300
|
+
// ============================================================
|
|
301
|
+
// CONVENIENCE FUNCTIONS
|
|
302
|
+
// ============================================================
|
|
303
|
+
/**
|
|
304
|
+
* Check if a block can be inserted (convenience function)
|
|
305
|
+
*/
|
|
306
|
+
export function canInsertBlock(parent, childType, currentDepth = 0) {
|
|
307
|
+
return compositionRuleEngine.canInsert(parent, childType, currentDepth);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Check if a block can be moved (convenience function)
|
|
311
|
+
*/
|
|
312
|
+
export function canMoveBlock(block, newParent, currentDepth = 0) {
|
|
313
|
+
return compositionRuleEngine.canMove(block, newParent, currentDepth);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Validate a block tree (convenience function)
|
|
317
|
+
*/
|
|
318
|
+
export function validateBlockTree(blocks) {
|
|
319
|
+
return compositionRuleEngine.validateTree(blocks);
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=rule-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-engine.js","sourceRoot":"","sources":["../../src/blocks/rule-engine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Composition Rule Engine\n *\n * CP7: Validation engine for block compositions\n * Block metadata accessor is now an injectable provider so\n * web-side editor flows can supply install-aware data without depending on\n * the populated runtime singleton.\n *\n * @module @pwfabric/core/blocks/rule-engine\n */\n\nimport type {\n Block,\n BlockValidationResult as ValidationResult,\n BlockValidationError as ValidationError,\n CompositionRule,\n BlockDefinition,\n} from '@pwfabric/core'\nimport { MAX_NESTING_DEPTH } from '@pwfabric/core'\nimport { blockRegistry } from './registry.js'\nimport { compositionRules } from './composition-rules.js'\n\n// ============================================================\n// BLOCK META PROVIDER\n// ============================================================\n\n/**\n * Snapshot of the block metadata the rule engine consults during\n * validation. A subset of `BlockDefinition` — only the fields that\n * affect composition decisions (name + child/parent rules).\n */\nexport interface BlockMetaSnapshot {\n readonly type: string\n readonly name: string\n readonly canHaveChildren: boolean\n readonly allowedChildren?: readonly string[]\n readonly allowedParents?: readonly string[]\n}\n\n/**\n * Pluggable block metadata accessor. The default implementation is a\n * thin adapter over the legacy `blockRegistry` singleton; install-aware\n * editor flows construct their own provider that wraps\n * `useInstalledAtoms` data.\n */\nexport interface BlockMetaProvider {\n get(type: string): BlockMetaSnapshot | undefined\n}\n\nfunction definitionToSnapshot(def: BlockDefinition): BlockMetaSnapshot {\n return {\n type: def.type,\n name: def.name,\n canHaveChildren: def.canHaveChildren,\n ...(def.allowedChildren !== undefined ? { allowedChildren: def.allowedChildren } : {}),\n ...(def.allowedParents !== undefined ? { allowedParents: def.allowedParents } : {}),\n }\n}\n\n/**\n * Default provider — reads from the runtime `blockRegistry` singleton.\n * Returns `undefined` for types absent from the singleton (post-\n * the singleton is empty by default).\n */\nexport const defaultBlockMetaProvider: BlockMetaProvider = {\n get(type: string): BlockMetaSnapshot | undefined {\n const def = blockRegistry.get(type)\n return def ? definitionToSnapshot(def) : undefined\n },\n}\n\n// ============================================================\n// ERROR CODES\n// ============================================================\n\nexport const CompositionErrorCode = {\n MAX_DEPTH_EXCEEDED: 'MAX_DEPTH_EXCEEDED',\n INVALID_CHILD: 'INVALID_CHILD',\n INVALID_PARENT: 'INVALID_PARENT',\n NO_CHILDREN_ALLOWED: 'NO_CHILDREN_ALLOWED',\n SELF_NESTING: 'SELF_NESTING',\n UNKNOWN_BLOCK_TYPE: 'UNKNOWN_BLOCK_TYPE',\n ORPHANED_BLOCK: 'ORPHANED_BLOCK',\n} as const\n\nexport type CompositionErrorCodeType =\n (typeof CompositionErrorCode)[keyof typeof CompositionErrorCode]\n\n// ============================================================\n// RULE ENGINE CLASS\n// ============================================================\n\n/**\n * Composition Rule Engine\n *\n * Validates block compositions against defined rules.\n */\nexport class CompositionRuleEngine {\n /** Rules for this engine instance (reserved for future custom rule support) */\n readonly rules: readonly CompositionRule[]\n /** Block metadata accessor */\n readonly meta: BlockMetaProvider\n\n constructor(\n rules: readonly CompositionRule[] = compositionRules,\n meta: BlockMetaProvider = defaultBlockMetaProvider\n ) {\n this.rules = rules\n this.meta = meta\n }\n\n /**\n * Check if a child can be inserted into a parent\n *\n * @param parent - Parent block (null for root level)\n * @param childType - Type of child block to insert\n * @param currentDepth - Current nesting depth\n * @returns Validation result\n */\n canInsert(parent: Block | null, childType: string, currentDepth = 0): ValidationResult {\n const errors: ValidationError[] = []\n\n // Check if child type is registered\n const childDef = this.meta.get(childType)\n if (!childDef) {\n errors.push({\n code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,\n message: `Unknown block type: ${childType}`,\n suggestion: 'Use a registered block type',\n })\n return { valid: false, errors }\n }\n\n // Root level insertion\n if (parent === null) {\n return { valid: true, errors: [] }\n }\n\n // Get parent definition\n const parentDef = this.meta.get(parent.type)\n if (!parentDef) {\n errors.push({\n code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,\n message: `Unknown parent block type: ${parent.type}`,\n blockId: parent.id,\n })\n return { valid: false, errors }\n }\n\n // Check if parent can have children\n if (!parentDef.canHaveChildren) {\n errors.push({\n code: CompositionErrorCode.NO_CHILDREN_ALLOWED,\n message: `${parentDef.name} blocks cannot have children`,\n blockId: parent.id,\n suggestion: `Place the ${childDef.name} block outside of ${parentDef.name}`,\n })\n return { valid: false, errors }\n }\n\n // Check depth limit\n if (currentDepth >= MAX_NESTING_DEPTH) {\n errors.push({\n code: CompositionErrorCode.MAX_DEPTH_EXCEEDED,\n message: `Maximum nesting depth (${MAX_NESTING_DEPTH}) exceeded`,\n blockId: parent.id,\n suggestion: 'Reduce nesting or restructure your layout',\n })\n return { valid: false, errors }\n }\n\n // Check allowed children\n if (parentDef.allowedChildren && !parentDef.allowedChildren.includes(childType)) {\n errors.push({\n code: CompositionErrorCode.INVALID_CHILD,\n message: `${childDef.name} is not allowed inside ${parentDef.name}`,\n blockId: parent.id,\n suggestion: `Allowed children: ${parentDef.allowedChildren.join(', ')}`,\n })\n return { valid: false, errors }\n }\n\n // Check allowed parents\n if (childDef.allowedParents && !childDef.allowedParents.includes(parent.type)) {\n errors.push({\n code: CompositionErrorCode.INVALID_PARENT,\n message: `${childDef.name} should be placed inside ${childDef.allowedParents.join(' or ')}`,\n blockId: parent.id,\n suggestion: `Move the ${childDef.name} into a ${childDef.allowedParents[0]}`,\n })\n // This is a warning, not a hard error\n return { valid: true, errors }\n }\n\n // Check grid-specific rules (no nested grids)\n if (parent.type === 'grid' && childType === 'grid') {\n errors.push({\n code: CompositionErrorCode.INVALID_CHILD,\n message: 'Grids cannot contain other grids as direct children',\n blockId: parent.id,\n suggestion: 'Wrap the inner grid in a container first',\n })\n return { valid: false, errors }\n }\n\n return { valid: true, errors: [] }\n }\n\n /**\n * Check if a block can be moved to a new parent\n *\n * @param block - Block to move\n * @param newParent - New parent block (null for root level)\n * @param currentDepth - Current nesting depth\n * @returns Validation result\n */\n canMove(block: Block, newParent: Block | null, currentDepth = 0): ValidationResult {\n const errors: ValidationError[] = []\n\n // Check for self-nesting\n if (newParent && this.isDescendantOf(newParent, block)) {\n errors.push({\n code: CompositionErrorCode.SELF_NESTING,\n message: 'Cannot move a block into itself or its descendants',\n blockId: block.id,\n suggestion: 'Choose a different location',\n })\n return { valid: false, errors }\n }\n\n // Use canInsert for other validations\n return this.canInsert(newParent, block.type, currentDepth)\n }\n\n /**\n * Validate an entire block tree\n *\n * @param blocks - Root level blocks to validate\n * @returns Array of validation errors\n */\n validateTree(blocks: readonly Block[]): ValidationResult {\n const errors: ValidationError[] = []\n\n const validateBlock = (block: Block, parent: Block | null, depth: number): void => {\n // Check block type\n const def = this.meta.get(block.type)\n if (!def) {\n errors.push({\n code: CompositionErrorCode.UNKNOWN_BLOCK_TYPE,\n message: `Unknown block type: ${block.type}`,\n blockId: block.id,\n })\n return\n }\n\n // Validate insertion\n if (parent !== null) {\n if (depth >= MAX_NESTING_DEPTH) {\n errors.push({\n code: CompositionErrorCode.MAX_DEPTH_EXCEEDED,\n message: `Block at depth ${depth} exceeds maximum nesting depth (${MAX_NESTING_DEPTH})`,\n blockId: block.id,\n suggestion: 'Reduce nesting or restructure your layout',\n })\n } else {\n const insertResult = this.canInsert(parent, block.type, depth)\n errors.push(...insertResult.errors)\n }\n }\n\n // Recursively validate children\n if (block.children) {\n // Check if block can have children\n if (!def.canHaveChildren && block.children.length > 0) {\n errors.push({\n code: CompositionErrorCode.NO_CHILDREN_ALLOWED,\n message: `${def.name} blocks cannot have children`,\n blockId: block.id,\n suggestion: 'Remove children from this block',\n })\n }\n\n for (const child of block.children) {\n validateBlock(child, block, depth + 1)\n }\n }\n }\n\n for (const block of blocks) {\n validateBlock(block, null, 0)\n }\n\n return {\n valid: errors.length === 0,\n errors,\n }\n }\n\n /**\n * Get the depth of a block in a tree\n *\n * @param blocks - Root level blocks\n * @param targetId - ID of block to find\n * @returns Depth of block or -1 if not found\n */\n getBlockDepth(blocks: readonly Block[], targetId: string): number {\n const findDepth = (blockList: readonly Block[], currentDepth: number): number => {\n for (const block of blockList) {\n if (block.id === targetId) {\n return currentDepth\n }\n if (block.children) {\n const found = findDepth(block.children, currentDepth + 1)\n if (found >= 0) return found\n }\n }\n return -1\n }\n\n return findDepth(blocks, 0)\n }\n\n /**\n * Check if a block is a descendant of another block\n *\n * @param block - Block to check descendants of\n * @param potentialAncestor - Potential ancestor block\n * @returns True if block is a descendant\n */\n private isDescendantOf(block: Block, potentialAncestor: Block): boolean {\n if (block.id === potentialAncestor.id) {\n return true\n }\n\n if (potentialAncestor.children) {\n for (const child of potentialAncestor.children) {\n if (this.isDescendantOf(block, child)) {\n return true\n }\n }\n }\n\n return false\n }\n}\n\n// ============================================================\n// SINGLETON INSTANCE\n// ============================================================\n\n/**\n * Default composition rule engine singleton\n */\nexport const compositionRuleEngine = new CompositionRuleEngine()\n\n/**\n * Get the default composition rule engine\n *\n * @returns The default rule engine instance\n */\nexport function getCompositionRuleEngine(): CompositionRuleEngine {\n return compositionRuleEngine\n}\n\n/**\n * Create a new composition rule engine\n *\n * @param rules - Optional custom rules\n * @param meta - Optional block metadata provider\n * @returns New rule engine instance\n */\nexport function createCompositionRuleEngine(\n rules?: readonly CompositionRule[],\n meta?: BlockMetaProvider\n): CompositionRuleEngine {\n return new CompositionRuleEngine(rules, meta)\n}\n\n// ============================================================\n// CONVENIENCE FUNCTIONS\n// ============================================================\n\n/**\n * Check if a block can be inserted (convenience function)\n */\nexport function canInsertBlock(\n parent: Block | null,\n childType: string,\n currentDepth = 0\n): ValidationResult {\n return compositionRuleEngine.canInsert(parent, childType, currentDepth)\n}\n\n/**\n * Check if a block can be moved (convenience function)\n */\nexport function canMoveBlock(\n block: Block,\n newParent: Block | null,\n currentDepth = 0\n): ValidationResult {\n return compositionRuleEngine.canMove(block, newParent, currentDepth)\n}\n\n/**\n * Validate a block tree (convenience function)\n */\nexport function validateBlockTree(blocks: readonly Block[]): ValidationResult {\n return compositionRuleEngine.validateTree(blocks)\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface Event Context
|
|
3
|
+
*
|
|
4
|
+
* React context that carries the SurfaceEventBus down the render tree
|
|
5
|
+
* so block components can emit events without prop-drilling.
|
|
6
|
+
*
|
|
7
|
+
* The default value is `null`; block components that call `useSurfaceEvents()`
|
|
8
|
+
* when no bus is provided simply no-op rather than throwing.
|
|
9
|
+
*
|
|
10
|
+
* @module @pwfabric/runtime/blocks/surface-event-context
|
|
11
|
+
*/
|
|
12
|
+
import type { SurfaceEventBus } from '@pwfabric/contracts';
|
|
13
|
+
export declare const SurfaceEventContext: import("react").Context<SurfaceEventBus | null>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface Event Context
|
|
3
|
+
*
|
|
4
|
+
* React context that carries the SurfaceEventBus down the render tree
|
|
5
|
+
* so block components can emit events without prop-drilling.
|
|
6
|
+
*
|
|
7
|
+
* The default value is `null`; block components that call `useSurfaceEvents()`
|
|
8
|
+
* when no bus is provided simply no-op rather than throwing.
|
|
9
|
+
*
|
|
10
|
+
* @module @pwfabric/runtime/blocks/surface-event-context
|
|
11
|
+
*/
|
|
12
|
+
import { createContext } from 'react';
|
|
13
|
+
export const SurfaceEventContext = createContext(null);
|
|
14
|
+
//# sourceMappingURL=surface-event-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-event-context.js","sourceRoot":"","sources":["../../src/blocks/surface-event-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAGrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAyB,IAAI,CAAC,CAAA","sourcesContent":["/**\n * Surface Event Context\n *\n * React context that carries the SurfaceEventBus down the render tree\n * so block components can emit events without prop-drilling.\n *\n * The default value is `null`; block components that call `useSurfaceEvents()`\n * when no bus is provided simply no-op rather than throwing.\n *\n * @module @pwfabric/runtime/blocks/surface-event-context\n */\n\nimport { createContext } from 'react'\nimport type { SurfaceEventBus } from '@pwfabric/contracts'\n\nexport const SurfaceEventContext = createContext<SurfaceEventBus | null>(null)\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface ID Context
|
|
3
|
+
*
|
|
4
|
+
* React context that carries the current surface ID down the render tree
|
|
5
|
+
* so block components can include it in emitted events without prop-drilling.
|
|
6
|
+
*
|
|
7
|
+
* The default value is an empty string; blocks that read this context when
|
|
8
|
+
* no `BehaviorSurfaceProvider` is present will emit events with an empty
|
|
9
|
+
* surfaceId rather than throwing.
|
|
10
|
+
*
|
|
11
|
+
* @module @pwfabric/runtime/blocks/surface-id-context
|
|
12
|
+
*/
|
|
13
|
+
export declare const SurfaceIdContext: import("react").Context<string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Surface ID Context
|
|
3
|
+
*
|
|
4
|
+
* React context that carries the current surface ID down the render tree
|
|
5
|
+
* so block components can include it in emitted events without prop-drilling.
|
|
6
|
+
*
|
|
7
|
+
* The default value is an empty string; blocks that read this context when
|
|
8
|
+
* no `BehaviorSurfaceProvider` is present will emit events with an empty
|
|
9
|
+
* surfaceId rather than throwing.
|
|
10
|
+
*
|
|
11
|
+
* @module @pwfabric/runtime/blocks/surface-id-context
|
|
12
|
+
*/
|
|
13
|
+
import { createContext } from 'react';
|
|
14
|
+
export const SurfaceIdContext = createContext('');
|
|
15
|
+
//# sourceMappingURL=surface-id-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-id-context.js","sourceRoot":"","sources":["../../src/blocks/surface-id-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAErC,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAS,EAAE,CAAC,CAAA","sourcesContent":["/**\n * Surface ID Context\n *\n * React context that carries the current surface ID down the render tree\n * so block components can include it in emitted events without prop-drilling.\n *\n * The default value is an empty string; blocks that read this context when\n * no `BehaviorSurfaceProvider` is present will emit events with an empty\n * surfaceId rather than throwing.\n *\n * @module @pwfabric/runtime/blocks/surface-id-context\n */\n\nimport { createContext } from 'react'\n\nexport const SurfaceIdContext = createContext<string>('')\n"]}
|
package/dist/bus.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Bus
|
|
3
|
+
*
|
|
4
|
+
* Event bus for fabric communication
|
|
5
|
+
*
|
|
6
|
+
* @module @pwfabric/runtime/bus
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseEvent, EventBus, EventHandler, EventSubscription, EventFilter, FabricEvent } from '@pwfabric/contracts';
|
|
9
|
+
/**
|
|
10
|
+
* In-memory event bus implementation
|
|
11
|
+
*/
|
|
12
|
+
export declare class InMemoryEventBus implements EventBus {
|
|
13
|
+
private subscriptions;
|
|
14
|
+
private typeSubscriptions;
|
|
15
|
+
emit<E extends BaseEvent>(event: E): void;
|
|
16
|
+
subscribe<E extends BaseEvent>(handler: EventHandler<E>, filter?: EventFilter): EventSubscription;
|
|
17
|
+
on<E extends BaseEvent>(type: E['type'], handler: EventHandler<E>): EventSubscription;
|
|
18
|
+
once<E extends BaseEvent>(type: E['type'], handler: EventHandler<E>): EventSubscription;
|
|
19
|
+
/**
|
|
20
|
+
* Clear all subscriptions
|
|
21
|
+
*/
|
|
22
|
+
clear(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Get subscription count
|
|
25
|
+
*/
|
|
26
|
+
subscriptionCount(): number;
|
|
27
|
+
private matchesFilter;
|
|
28
|
+
private invokeHandler;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a new event bus
|
|
32
|
+
*/
|
|
33
|
+
export declare function createEventBus(): EventBus;
|
|
34
|
+
/**
|
|
35
|
+
* Helper to create a typed event
|
|
36
|
+
*/
|
|
37
|
+
export declare function createFabricEvent<T extends FabricEvent['type']>(type: T, data: Omit<Extract<FabricEvent, {
|
|
38
|
+
type: T;
|
|
39
|
+
}>, 'id' | 'type' | 'timestamp'>): Extract<FabricEvent, {
|
|
40
|
+
type: T;
|
|
41
|
+
}>;
|
package/dist/bus.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Bus
|
|
3
|
+
*
|
|
4
|
+
* Event bus for fabric communication
|
|
5
|
+
*
|
|
6
|
+
* @module @pwfabric/runtime/bus
|
|
7
|
+
*/
|
|
8
|
+
import { generateEventId } from '@pwfabric/contracts';
|
|
9
|
+
/**
|
|
10
|
+
* In-memory event bus implementation
|
|
11
|
+
*/
|
|
12
|
+
export class InMemoryEventBus {
|
|
13
|
+
subscriptions = [];
|
|
14
|
+
typeSubscriptions = new Map();
|
|
15
|
+
emit(event) {
|
|
16
|
+
// Emit to type-specific subscribers
|
|
17
|
+
const typeHandlers = this.typeSubscriptions.get(event.type);
|
|
18
|
+
if (typeHandlers) {
|
|
19
|
+
for (const entry of typeHandlers) {
|
|
20
|
+
this.invokeHandler(entry.handler, event);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Emit to general subscribers
|
|
24
|
+
for (const entry of this.subscriptions) {
|
|
25
|
+
if (this.matchesFilter(event, entry.filter)) {
|
|
26
|
+
this.invokeHandler(entry.handler, event);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
subscribe(handler, filter) {
|
|
31
|
+
const entry = {
|
|
32
|
+
id: generateEventId(),
|
|
33
|
+
handler: handler,
|
|
34
|
+
filter,
|
|
35
|
+
};
|
|
36
|
+
this.subscriptions.push(entry);
|
|
37
|
+
return {
|
|
38
|
+
unsubscribe: () => {
|
|
39
|
+
const index = this.subscriptions.indexOf(entry);
|
|
40
|
+
if (index !== -1) {
|
|
41
|
+
this.subscriptions.splice(index, 1);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
on(type, handler) {
|
|
47
|
+
const entry = {
|
|
48
|
+
id: generateEventId(),
|
|
49
|
+
handler: handler,
|
|
50
|
+
filter: undefined,
|
|
51
|
+
};
|
|
52
|
+
let typeSet = this.typeSubscriptions.get(type);
|
|
53
|
+
if (!typeSet) {
|
|
54
|
+
typeSet = new Set();
|
|
55
|
+
this.typeSubscriptions.set(type, typeSet);
|
|
56
|
+
}
|
|
57
|
+
typeSet.add(entry);
|
|
58
|
+
return {
|
|
59
|
+
unsubscribe: () => {
|
|
60
|
+
const set = this.typeSubscriptions.get(type);
|
|
61
|
+
if (set) {
|
|
62
|
+
set.delete(entry);
|
|
63
|
+
if (set.size === 0) {
|
|
64
|
+
this.typeSubscriptions.delete(type);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
once(type, handler) {
|
|
71
|
+
const subscription = this.on(type, (event) => {
|
|
72
|
+
subscription.unsubscribe();
|
|
73
|
+
handler(event);
|
|
74
|
+
});
|
|
75
|
+
return subscription;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clear all subscriptions
|
|
79
|
+
*/
|
|
80
|
+
clear() {
|
|
81
|
+
this.subscriptions = [];
|
|
82
|
+
this.typeSubscriptions.clear();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get subscription count
|
|
86
|
+
*/
|
|
87
|
+
subscriptionCount() {
|
|
88
|
+
let count = this.subscriptions.length;
|
|
89
|
+
for (const set of this.typeSubscriptions.values()) {
|
|
90
|
+
count += set.size;
|
|
91
|
+
}
|
|
92
|
+
return count;
|
|
93
|
+
}
|
|
94
|
+
matchesFilter(event, filter) {
|
|
95
|
+
if (!filter)
|
|
96
|
+
return true;
|
|
97
|
+
// Check type filter
|
|
98
|
+
if (filter.types && filter.types.length > 0) {
|
|
99
|
+
if (!filter.types.includes(event.type)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Check source filter
|
|
104
|
+
if (filter.sources && filter.sources.length > 0) {
|
|
105
|
+
const eventSource = event.source;
|
|
106
|
+
const matches = filter.sources.some((source) => {
|
|
107
|
+
if (source.fabricId && source.fabricId !== eventSource.fabricId) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if (source.capabilityId && source.capabilityId !== eventSource.capabilityId) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (source.domainId && source.domainId !== eventSource.domainId) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return true;
|
|
117
|
+
});
|
|
118
|
+
if (!matches)
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
invokeHandler(handler, event) {
|
|
124
|
+
try {
|
|
125
|
+
const result = handler(event);
|
|
126
|
+
// Handle async handlers - errors are swallowed but could be logged
|
|
127
|
+
if (result instanceof Promise) {
|
|
128
|
+
result.catch(() => {
|
|
129
|
+
// Handler error - could log here
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Handler threw synchronously - could log here
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Create a new event bus
|
|
140
|
+
*/
|
|
141
|
+
export function createEventBus() {
|
|
142
|
+
return new InMemoryEventBus();
|
|
143
|
+
}
|
|
144
|
+
// ============================================================
|
|
145
|
+
// TYPED EVENT EMITTERS
|
|
146
|
+
// ============================================================
|
|
147
|
+
/**
|
|
148
|
+
* Helper to create a typed event
|
|
149
|
+
*/
|
|
150
|
+
export function createFabricEvent(type, data) {
|
|
151
|
+
return {
|
|
152
|
+
id: generateEventId(),
|
|
153
|
+
type,
|
|
154
|
+
timestamp: Date.now(),
|
|
155
|
+
...data,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=bus.js.map
|
package/dist/bus.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.js","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Event Bus\n *\n * Event bus for fabric communication\n *\n * @module @pwfabric/runtime/bus\n */\n\nimport type {\n BaseEvent,\n EventBus,\n EventHandler,\n EventSubscription,\n EventFilter,\n FabricEvent,\n} from '@pwfabric/contracts'\nimport { generateEventId } from '@pwfabric/contracts'\n\n// ============================================================\n// IN-MEMORY EVENT BUS IMPLEMENTATION\n// ============================================================\n\n/**\n * Subscription entry\n */\ninterface SubscriptionEntry {\n readonly id: string\n readonly handler: EventHandler<BaseEvent>\n readonly filter: EventFilter | undefined\n}\n\n/**\n * In-memory event bus implementation\n */\nexport class InMemoryEventBus implements EventBus {\n private subscriptions: SubscriptionEntry[] = []\n private typeSubscriptions = new Map<string, Set<SubscriptionEntry>>()\n\n emit<E extends BaseEvent>(event: E): void {\n // Emit to type-specific subscribers\n const typeHandlers = this.typeSubscriptions.get(event.type)\n if (typeHandlers) {\n for (const entry of typeHandlers) {\n this.invokeHandler(entry.handler, event)\n }\n }\n\n // Emit to general subscribers\n for (const entry of this.subscriptions) {\n if (this.matchesFilter(event, entry.filter)) {\n this.invokeHandler(entry.handler, event)\n }\n }\n }\n\n subscribe<E extends BaseEvent>(\n handler: EventHandler<E>,\n filter?: EventFilter\n ): EventSubscription {\n const entry: SubscriptionEntry = {\n id: generateEventId(),\n handler: handler as EventHandler<BaseEvent>,\n filter,\n }\n\n this.subscriptions.push(entry)\n\n return {\n unsubscribe: () => {\n const index = this.subscriptions.indexOf(entry)\n if (index !== -1) {\n this.subscriptions.splice(index, 1)\n }\n },\n }\n }\n\n on<E extends BaseEvent>(type: E['type'], handler: EventHandler<E>): EventSubscription {\n const entry: SubscriptionEntry = {\n id: generateEventId(),\n handler: handler as EventHandler<BaseEvent>,\n filter: undefined,\n }\n\n let typeSet = this.typeSubscriptions.get(type)\n if (!typeSet) {\n typeSet = new Set()\n this.typeSubscriptions.set(type, typeSet)\n }\n typeSet.add(entry)\n\n return {\n unsubscribe: () => {\n const set = this.typeSubscriptions.get(type)\n if (set) {\n set.delete(entry)\n if (set.size === 0) {\n this.typeSubscriptions.delete(type)\n }\n }\n },\n }\n }\n\n once<E extends BaseEvent>(type: E['type'], handler: EventHandler<E>): EventSubscription {\n const subscription = this.on(type, (event) => {\n subscription.unsubscribe()\n handler(event as E)\n })\n return subscription\n }\n\n /**\n * Clear all subscriptions\n */\n clear(): void {\n this.subscriptions = []\n this.typeSubscriptions.clear()\n }\n\n /**\n * Get subscription count\n */\n subscriptionCount(): number {\n let count = this.subscriptions.length\n for (const set of this.typeSubscriptions.values()) {\n count += set.size\n }\n return count\n }\n\n private matchesFilter(event: BaseEvent, filter?: EventFilter): boolean {\n if (!filter) return true\n\n // Check type filter\n if (filter.types && filter.types.length > 0) {\n if (!filter.types.includes(event.type)) {\n return false\n }\n }\n\n // Check source filter\n if (filter.sources && filter.sources.length > 0) {\n const eventSource = event.source\n const matches = filter.sources.some((source) => {\n if (source.fabricId && source.fabricId !== eventSource.fabricId) {\n return false\n }\n if (source.capabilityId && source.capabilityId !== eventSource.capabilityId) {\n return false\n }\n if (source.domainId && source.domainId !== eventSource.domainId) {\n return false\n }\n return true\n })\n if (!matches) return false\n }\n\n return true\n }\n\n private invokeHandler(handler: EventHandler<BaseEvent>, event: BaseEvent): void {\n try {\n const result = handler(event)\n // Handle async handlers - errors are swallowed but could be logged\n if (result instanceof Promise) {\n result.catch(() => {\n // Handler error - could log here\n })\n }\n } catch {\n // Handler threw synchronously - could log here\n }\n }\n}\n\n/**\n * Create a new event bus\n */\nexport function createEventBus(): EventBus {\n return new InMemoryEventBus()\n}\n\n// ============================================================\n// TYPED EVENT EMITTERS\n// ============================================================\n\n/**\n * Helper to create a typed event\n */\nexport function createFabricEvent<T extends FabricEvent['type']>(\n type: T,\n data: Omit<Extract<FabricEvent, { type: T }>, 'id' | 'type' | 'timestamp'>\n): Extract<FabricEvent, { type: T }> {\n return {\n id: generateEventId(),\n type,\n timestamp: Date.now(),\n ...data,\n } as Extract<FabricEvent, { type: T }>\n}\n"]}
|