@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,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector Module Loader
|
|
3
|
+
*
|
|
4
|
+
* Mirror of `BlockModuleLoader` (render/dynamic-block-loader.ts) for
|
|
5
|
+
* kind='connector' / kind='provider' atom bundles: fetches the ESM bundle
|
|
6
|
+
* from `bundleUrl`, SHA-256 verifies the bytes against
|
|
7
|
+
* `descriptor.integrity` BEFORE evaluation (same security boundary as block
|
|
8
|
+
* bundles — a CDN-side compromise must not execute under our origin), then
|
|
9
|
+
* imports it via a Blob URL and resolves the engine FACTORY under the
|
|
10
|
+
* stable export convention (`createConnector`, `default` fallback).
|
|
11
|
+
*
|
|
12
|
+
* Error isolation: a failed load never throws out of `tryLoad` — the
|
|
13
|
+
* failure reason is recorded per atom id (`getFailure`) so the registry can
|
|
14
|
+
* mark its entry failed and consumers degrade honestly. `load` (the raw
|
|
15
|
+
* form) rejects for callers that want the exception.
|
|
16
|
+
*
|
|
17
|
+
* @module @pwfabric/runtime/connectors/module-loader
|
|
18
|
+
*/
|
|
19
|
+
import type { ConnectorEngineDescriptor, ConnectorEngineFactory, ConnectorEngineModule } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates verified bundle bytes into a module namespace. Injectable so
|
|
22
|
+
* tests (and non-browser hosts) can substitute the Blob-URL `import()`
|
|
23
|
+
* step, which only exists in browsers.
|
|
24
|
+
*/
|
|
25
|
+
export type ConnectorModuleEvaluator = (bytes: ArrayBuffer, descriptor: ConnectorEngineDescriptor) => Promise<ConnectorEngineModule>;
|
|
26
|
+
/**
|
|
27
|
+
* Loader for connector-engine ESM bundles.
|
|
28
|
+
*
|
|
29
|
+
* - Caches loaded factories by atom id
|
|
30
|
+
* - Deduplicates concurrent requests for the same atom
|
|
31
|
+
* - Records the last failure reason per atom id (does NOT poison the cache
|
|
32
|
+
* — a later retry is allowed and clears the failure on success)
|
|
33
|
+
*/
|
|
34
|
+
export declare class ConnectorModuleLoaderImpl {
|
|
35
|
+
private readonly cache;
|
|
36
|
+
private readonly pending;
|
|
37
|
+
private readonly failures;
|
|
38
|
+
private readonly evaluate;
|
|
39
|
+
constructor(options?: {
|
|
40
|
+
readonly evaluate?: ConnectorModuleEvaluator;
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Load a connector engine bundle and return its factory. Rejects on
|
|
44
|
+
* failure (fetch / integrity / export shape / timeout) after recording
|
|
45
|
+
* the reason — see `tryLoad` for the non-throwing form.
|
|
46
|
+
*/
|
|
47
|
+
load(descriptor: ConnectorEngineDescriptor): Promise<ConnectorEngineFactory>;
|
|
48
|
+
/**
|
|
49
|
+
* Non-throwing load: `null` on failure, with the reason retrievable via
|
|
50
|
+
* `getFailure(descriptor.id)`.
|
|
51
|
+
*/
|
|
52
|
+
tryLoad(descriptor: ConnectorEngineDescriptor): Promise<ConnectorEngineFactory | null>;
|
|
53
|
+
/** Whether the factory for an atom id is already cached. */
|
|
54
|
+
isLoaded(atomId: string): boolean;
|
|
55
|
+
/** Last recorded failure reason for an atom id, or null. */
|
|
56
|
+
getFailure(atomId: string): string | null;
|
|
57
|
+
/** Invalidate cache (and failure record) for one atom id or all. */
|
|
58
|
+
invalidate(atomId?: string): void;
|
|
59
|
+
private doLoad;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a loader with injectable evaluation (tests / non-browser hosts).
|
|
63
|
+
*/
|
|
64
|
+
export declare function createConnectorModuleLoader(options?: {
|
|
65
|
+
readonly evaluate?: ConnectorModuleEvaluator;
|
|
66
|
+
}): ConnectorModuleLoaderImpl;
|
|
67
|
+
/**
|
|
68
|
+
* Singleton instance — mirrors `BlockModuleLoader`.
|
|
69
|
+
*/
|
|
70
|
+
export declare const ConnectorModuleLoader: ConnectorModuleLoaderImpl;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector Module Loader
|
|
3
|
+
*
|
|
4
|
+
* Mirror of `BlockModuleLoader` (render/dynamic-block-loader.ts) for
|
|
5
|
+
* kind='connector' / kind='provider' atom bundles: fetches the ESM bundle
|
|
6
|
+
* from `bundleUrl`, SHA-256 verifies the bytes against
|
|
7
|
+
* `descriptor.integrity` BEFORE evaluation (same security boundary as block
|
|
8
|
+
* bundles — a CDN-side compromise must not execute under our origin), then
|
|
9
|
+
* imports it via a Blob URL and resolves the engine FACTORY under the
|
|
10
|
+
* stable export convention (`createConnector`, `default` fallback).
|
|
11
|
+
*
|
|
12
|
+
* Error isolation: a failed load never throws out of `tryLoad` — the
|
|
13
|
+
* failure reason is recorded per atom id (`getFailure`) so the registry can
|
|
14
|
+
* mark its entry failed and consumers degrade honestly. `load` (the raw
|
|
15
|
+
* form) rejects for callers that want the exception.
|
|
16
|
+
*
|
|
17
|
+
* @module @pwfabric/runtime/connectors/module-loader
|
|
18
|
+
*/
|
|
19
|
+
import { verifyIntegrity } from '../render/dynamic-block-loader.js';
|
|
20
|
+
const LOAD_TIMEOUT_MS = 10_000;
|
|
21
|
+
// ============================================================
|
|
22
|
+
// DEFAULT EVALUATOR (browser Blob-URL import)
|
|
23
|
+
// ============================================================
|
|
24
|
+
async function blobImportEvaluator(bytes, _descriptor) {
|
|
25
|
+
const blob = new Blob([bytes], { type: 'text/javascript' });
|
|
26
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
27
|
+
try {
|
|
28
|
+
return (await import(/* webpackIgnore: true */ blobUrl));
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
URL.revokeObjectURL(blobUrl);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ============================================================
|
|
35
|
+
// MODULE LOADER
|
|
36
|
+
// ============================================================
|
|
37
|
+
/**
|
|
38
|
+
* Loader for connector-engine ESM bundles.
|
|
39
|
+
*
|
|
40
|
+
* - Caches loaded factories by atom id
|
|
41
|
+
* - Deduplicates concurrent requests for the same atom
|
|
42
|
+
* - Records the last failure reason per atom id (does NOT poison the cache
|
|
43
|
+
* — a later retry is allowed and clears the failure on success)
|
|
44
|
+
*/
|
|
45
|
+
export class ConnectorModuleLoaderImpl {
|
|
46
|
+
cache = new Map();
|
|
47
|
+
pending = new Map();
|
|
48
|
+
failures = new Map();
|
|
49
|
+
evaluate;
|
|
50
|
+
constructor(options) {
|
|
51
|
+
this.evaluate = options?.evaluate ?? blobImportEvaluator;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Load a connector engine bundle and return its factory. Rejects on
|
|
55
|
+
* failure (fetch / integrity / export shape / timeout) after recording
|
|
56
|
+
* the reason — see `tryLoad` for the non-throwing form.
|
|
57
|
+
*/
|
|
58
|
+
async load(descriptor) {
|
|
59
|
+
const cached = this.cache.get(descriptor.id);
|
|
60
|
+
if (cached)
|
|
61
|
+
return cached.factory;
|
|
62
|
+
const inflight = this.pending.get(descriptor.id);
|
|
63
|
+
if (inflight)
|
|
64
|
+
return inflight;
|
|
65
|
+
const promise = this.doLoad(descriptor);
|
|
66
|
+
this.pending.set(descriptor.id, promise);
|
|
67
|
+
try {
|
|
68
|
+
const factory = await promise;
|
|
69
|
+
this.cache.set(descriptor.id, { factory, loadedAt: Date.now() });
|
|
70
|
+
this.failures.delete(descriptor.id);
|
|
71
|
+
return factory;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
this.failures.set(descriptor.id, err instanceof Error ? err.message : String(err));
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
this.pending.delete(descriptor.id);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Non-throwing load: `null` on failure, with the reason retrievable via
|
|
83
|
+
* `getFailure(descriptor.id)`.
|
|
84
|
+
*/
|
|
85
|
+
async tryLoad(descriptor) {
|
|
86
|
+
try {
|
|
87
|
+
return await this.load(descriptor);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** Whether the factory for an atom id is already cached. */
|
|
94
|
+
isLoaded(atomId) {
|
|
95
|
+
return this.cache.has(atomId);
|
|
96
|
+
}
|
|
97
|
+
/** Last recorded failure reason for an atom id, or null. */
|
|
98
|
+
getFailure(atomId) {
|
|
99
|
+
return this.failures.get(atomId) ?? null;
|
|
100
|
+
}
|
|
101
|
+
/** Invalidate cache (and failure record) for one atom id or all. */
|
|
102
|
+
invalidate(atomId) {
|
|
103
|
+
if (atomId) {
|
|
104
|
+
this.cache.delete(atomId);
|
|
105
|
+
this.failures.delete(atomId);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.cache.clear();
|
|
109
|
+
this.failures.clear();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async doLoad(descriptor) {
|
|
113
|
+
const fetchAndEvaluate = async () => {
|
|
114
|
+
const res = await fetch(descriptor.bundleUrl, { credentials: 'omit' });
|
|
115
|
+
if (!res.ok) {
|
|
116
|
+
throw new Error(`Bundle fetch failed for ${descriptor.id}: ${res.status}`);
|
|
117
|
+
}
|
|
118
|
+
const bytes = await res.arrayBuffer();
|
|
119
|
+
// Same law as block bundles: integrity is verified BEFORE evaluation.
|
|
120
|
+
await verifyIntegrity(bytes, descriptor.integrity, descriptor.id);
|
|
121
|
+
return this.evaluate(bytes, descriptor);
|
|
122
|
+
};
|
|
123
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Module load timed out after ${LOAD_TIMEOUT_MS / 1000}s`)), LOAD_TIMEOUT_MS));
|
|
124
|
+
const mod = await Promise.race([fetchAndEvaluate(), timeoutPromise]);
|
|
125
|
+
const factory = mod.createConnector ?? mod.default;
|
|
126
|
+
if (typeof factory !== 'function') {
|
|
127
|
+
throw new Error(`Module at ${descriptor.bundleUrl} does not export a connector factory ` +
|
|
128
|
+
`(expected 'createConnector' or a default function export)`);
|
|
129
|
+
}
|
|
130
|
+
return factory;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Create a loader with injectable evaluation (tests / non-browser hosts).
|
|
135
|
+
*/
|
|
136
|
+
export function createConnectorModuleLoader(options) {
|
|
137
|
+
return new ConnectorModuleLoaderImpl(options);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Singleton instance — mirrors `BlockModuleLoader`.
|
|
141
|
+
*/
|
|
142
|
+
export const ConnectorModuleLoader = new ConnectorModuleLoaderImpl();
|
|
143
|
+
//# sourceMappingURL=module-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-loader.js","sourceRoot":"","sources":["../../src/connectors/module-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Connector Module Loader\n *\n * Mirror of `BlockModuleLoader` (render/dynamic-block-loader.ts) for\n * kind='connector' / kind='provider' atom bundles: fetches the ESM bundle\n * from `bundleUrl`, SHA-256 verifies the bytes against\n * `descriptor.integrity` BEFORE evaluation (same security boundary as block\n * bundles — a CDN-side compromise must not execute under our origin), then\n * imports it via a Blob URL and resolves the engine FACTORY under the\n * stable export convention (`createConnector`, `default` fallback).\n *\n * Error isolation: a failed load never throws out of `tryLoad` — the\n * failure reason is recorded per atom id (`getFailure`) so the registry can\n * mark its entry failed and consumers degrade honestly. `load` (the raw\n * form) rejects for callers that want the exception.\n *\n * @module @pwfabric/runtime/connectors/module-loader\n */\n\nimport { verifyIntegrity } from '../render/dynamic-block-loader.js'\nimport type {\n ConnectorEngineDescriptor,\n ConnectorEngineFactory,\n ConnectorEngineModule,\n} from './types.js'\n\n// ============================================================\n// TYPES\n// ============================================================\n\n/**\n * Evaluates verified bundle bytes into a module namespace. Injectable so\n * tests (and non-browser hosts) can substitute the Blob-URL `import()`\n * step, which only exists in browsers.\n */\nexport type ConnectorModuleEvaluator = (\n bytes: ArrayBuffer,\n descriptor: ConnectorEngineDescriptor\n) => Promise<ConnectorEngineModule>\n\ninterface CachedEngineModule {\n readonly factory: ConnectorEngineFactory\n readonly loadedAt: number\n}\n\nconst LOAD_TIMEOUT_MS = 10_000\n\n// ============================================================\n// DEFAULT EVALUATOR (browser Blob-URL import)\n// ============================================================\n\nasync function blobImportEvaluator(\n bytes: ArrayBuffer,\n _descriptor: ConnectorEngineDescriptor\n): Promise<ConnectorEngineModule> {\n const blob = new Blob([bytes], { type: 'text/javascript' })\n const blobUrl = URL.createObjectURL(blob)\n try {\n return (await import(/* webpackIgnore: true */ blobUrl)) as ConnectorEngineModule\n } finally {\n URL.revokeObjectURL(blobUrl)\n }\n}\n\n// ============================================================\n// MODULE LOADER\n// ============================================================\n\n/**\n * Loader for connector-engine ESM bundles.\n *\n * - Caches loaded factories by atom id\n * - Deduplicates concurrent requests for the same atom\n * - Records the last failure reason per atom id (does NOT poison the cache\n * — a later retry is allowed and clears the failure on success)\n */\nexport class ConnectorModuleLoaderImpl {\n private readonly cache = new Map<string, CachedEngineModule>()\n private readonly pending = new Map<string, Promise<ConnectorEngineFactory>>()\n private readonly failures = new Map<string, string>()\n private readonly evaluate: ConnectorModuleEvaluator\n\n constructor(options?: { readonly evaluate?: ConnectorModuleEvaluator }) {\n this.evaluate = options?.evaluate ?? blobImportEvaluator\n }\n\n /**\n * Load a connector engine bundle and return its factory. Rejects on\n * failure (fetch / integrity / export shape / timeout) after recording\n * the reason — see `tryLoad` for the non-throwing form.\n */\n async load(descriptor: ConnectorEngineDescriptor): Promise<ConnectorEngineFactory> {\n const cached = this.cache.get(descriptor.id)\n if (cached) return cached.factory\n\n const inflight = this.pending.get(descriptor.id)\n if (inflight) return inflight\n\n const promise = this.doLoad(descriptor)\n this.pending.set(descriptor.id, promise)\n\n try {\n const factory = await promise\n this.cache.set(descriptor.id, { factory, loadedAt: Date.now() })\n this.failures.delete(descriptor.id)\n return factory\n } catch (err) {\n this.failures.set(descriptor.id, err instanceof Error ? err.message : String(err))\n throw err\n } finally {\n this.pending.delete(descriptor.id)\n }\n }\n\n /**\n * Non-throwing load: `null` on failure, with the reason retrievable via\n * `getFailure(descriptor.id)`.\n */\n async tryLoad(descriptor: ConnectorEngineDescriptor): Promise<ConnectorEngineFactory | null> {\n try {\n return await this.load(descriptor)\n } catch {\n return null\n }\n }\n\n /** Whether the factory for an atom id is already cached. */\n isLoaded(atomId: string): boolean {\n return this.cache.has(atomId)\n }\n\n /** Last recorded failure reason for an atom id, or null. */\n getFailure(atomId: string): string | null {\n return this.failures.get(atomId) ?? null\n }\n\n /** Invalidate cache (and failure record) for one atom id or all. */\n invalidate(atomId?: string): void {\n if (atomId) {\n this.cache.delete(atomId)\n this.failures.delete(atomId)\n } else {\n this.cache.clear()\n this.failures.clear()\n }\n }\n\n private async doLoad(descriptor: ConnectorEngineDescriptor): Promise<ConnectorEngineFactory> {\n const fetchAndEvaluate = async (): Promise<ConnectorEngineModule> => {\n const res = await fetch(descriptor.bundleUrl, { credentials: 'omit' })\n if (!res.ok) {\n throw new Error(`Bundle fetch failed for ${descriptor.id}: ${res.status}`)\n }\n const bytes = await res.arrayBuffer()\n // Same law as block bundles: integrity is verified BEFORE evaluation.\n await verifyIntegrity(bytes, descriptor.integrity, descriptor.id)\n return this.evaluate(bytes, descriptor)\n }\n\n const timeoutPromise = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Module load timed out after ${LOAD_TIMEOUT_MS / 1000}s`)),\n LOAD_TIMEOUT_MS\n )\n )\n\n const mod = await Promise.race([fetchAndEvaluate(), timeoutPromise])\n\n const factory = mod.createConnector ?? mod.default\n if (typeof factory !== 'function') {\n throw new Error(\n `Module at ${descriptor.bundleUrl} does not export a connector factory ` +\n `(expected 'createConnector' or a default function export)`\n )\n }\n return factory\n }\n}\n\n/**\n * Create a loader with injectable evaluation (tests / non-browser hosts).\n */\nexport function createConnectorModuleLoader(options?: {\n readonly evaluate?: ConnectorModuleEvaluator\n}): ConnectorModuleLoaderImpl {\n return new ConnectorModuleLoaderImpl(options)\n}\n\n/**\n * Singleton instance — mirrors `BlockModuleLoader`.\n */\nexport const ConnectorModuleLoader = new ConnectorModuleLoaderImpl()\n"]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector Engine Types
|
|
3
|
+
*
|
|
4
|
+
* Platform-side vocabulary for CONNECTOR/PROVIDER atom engines. Two
|
|
5
|
+
* consumption paths, ONE engine source:
|
|
6
|
+
*
|
|
7
|
+
* 1. dataSource path — a surface dataSource `{kind:'entity', entityType,
|
|
8
|
+
* connector:'graph-lists'}` routes through a `ConnectorEngineRegistry`:
|
|
9
|
+
* when a loaded engine is registered under that connection name the read
|
|
10
|
+
* goes through it (constructed with the world connection's config);
|
|
11
|
+
* absent engine/config keeps today's behavior (default facade or honest
|
|
12
|
+
* empty + `__errors` context), never a crash.
|
|
13
|
+
* 2. engine-bridge path — pack blocks get their connections/config from the
|
|
14
|
+
* runtime-provided connections context (`SurfaceConnectionsContext`).
|
|
15
|
+
* On the platform the value comes from the project's connections doc +
|
|
16
|
+
* world connector rows; in the runner the existing `connections.json`
|
|
17
|
+
* path is unchanged. Single dialect — the source differs, the shape
|
|
18
|
+
* doesn't (mirrors the runner's `PwappConnection`).
|
|
19
|
+
*
|
|
20
|
+
* @module @pwfabric/runtime/connectors/types
|
|
21
|
+
*/
|
|
22
|
+
import type { EntityAggregate, EntityTypeId, EntityQuery } from '../entity/types.js';
|
|
23
|
+
import type { ConnectorAggregateResult, ConnectorQueryResult } from '../entity/connector.js';
|
|
24
|
+
/**
|
|
25
|
+
* Atom kinds that ship a connector engine bundle. `connector` = dynamic
|
|
26
|
+
* data engine (e.g. graph-lists); `provider` = fixed-enum provider motor
|
|
27
|
+
* facet (e.g. the single Graph motor behind graph-mail/graph-users/…).
|
|
28
|
+
*/
|
|
29
|
+
export type ConnectorEngineKind = 'connector' | 'provider';
|
|
30
|
+
/**
|
|
31
|
+
* Descriptor for a loadable connector-engine atom bundle. Mirrors
|
|
32
|
+
* `DynamicBlockDescriptor` with the AtomRef `bundleUrl`
|
|
33
|
+
* vocabulary: the publish pipeline uploads the ESM bundle and stamps its
|
|
34
|
+
* SHA-256 — integrity is verified BEFORE evaluation (security boundary,
|
|
35
|
+
* same law as block bundles).
|
|
36
|
+
*/
|
|
37
|
+
export interface ConnectorEngineDescriptor {
|
|
38
|
+
/** Atom id of the engine (e.g. 'graph-lists', 'microsoft-graph-motor'). */
|
|
39
|
+
readonly id: string;
|
|
40
|
+
readonly kind: ConnectorEngineKind;
|
|
41
|
+
/** CDN URL of the ESM bundle produced by the publish pipeline. */
|
|
42
|
+
readonly bundleUrl: string;
|
|
43
|
+
/** SHA-256 of the bundle bytes (bare hex or SRI `sha256-<base64>`). */
|
|
44
|
+
readonly integrity: string;
|
|
45
|
+
readonly version?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Per-call access-token supplier handed to an engine at construction —
|
|
49
|
+
* exactly the signature the existing engines already take
|
|
50
|
+
* (GraphListConnector / createGraphConnector). Re-invoked on every request
|
|
51
|
+
* so token rotation is transparent. Resolving to `null` means
|
|
52
|
+
* unauthenticated — engines degrade honestly (anon/empty), they do not
|
|
53
|
+
* throw at construction time.
|
|
54
|
+
*/
|
|
55
|
+
export type ConnectorAccessTokenHook = () => Promise<string | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Factory a connector-engine bundle must export. The wrapper convention
|
|
58
|
+
* (mirror of the block bundle's `Component` + `definition`) is a stable
|
|
59
|
+
* `createConnector` named export; `default` is accepted as fallback.
|
|
60
|
+
*/
|
|
61
|
+
export type ConnectorEngineFactory = (getAccessToken: ConnectorAccessTokenHook, config: Readonly<Record<string, unknown>>) => unknown;
|
|
62
|
+
/** Module shape of an evaluated connector-engine bundle. */
|
|
63
|
+
export interface ConnectorEngineModule {
|
|
64
|
+
readonly createConnector?: ConnectorEngineFactory;
|
|
65
|
+
readonly default?: ConnectorEngineFactory;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Minimal read contract every constructed engine must satisfy — the surface
|
|
69
|
+
* dataSource path only lists records. Engines that additionally implement
|
|
70
|
+
* the full `EntityConnector` interface can be registered into an
|
|
71
|
+
* `EntityFacade` (`facade.connectors.register(engine)`) for the write path.
|
|
72
|
+
*/
|
|
73
|
+
export interface ConnectorEngine {
|
|
74
|
+
readonly name?: string;
|
|
75
|
+
query(entityType: EntityTypeId, query: EntityQuery): Promise<ConnectorQueryResult>;
|
|
76
|
+
/** Optional: an engine that can count server-side; absent = list and reduce. */
|
|
77
|
+
aggregate?(entityType: EntityTypeId, aggregate: EntityAggregate): Promise<ConnectorAggregateResult>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* One configured connection: a connector engine bound to this world with
|
|
81
|
+
* per-connection config. `connection` is the connection NAME the surface
|
|
82
|
+
* dialect references (`dataSources[].connector`); `descriptor` says which
|
|
83
|
+
* engine bundle serves it; `config` is the world connection's config
|
|
84
|
+
* (never credential values — auth law).
|
|
85
|
+
*/
|
|
86
|
+
export interface ConnectorConnectionBinding {
|
|
87
|
+
readonly connection: string;
|
|
88
|
+
readonly descriptor: ConnectorEngineDescriptor;
|
|
89
|
+
readonly config?: Readonly<Record<string, unknown>>;
|
|
90
|
+
/** Auth binding BY NAME — resolved by the token resolver. */
|
|
91
|
+
readonly authProviderRef?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Injectable token resolver — the registry derives each engine's
|
|
95
|
+
* `ConnectorAccessTokenHook` from this. By default the
|
|
96
|
+
* resolver answers `null` (engines behave as unauthenticated); a host plugs
|
|
97
|
+
* the AuthRegistry in through `setAccessTokenResolver` without another
|
|
98
|
+
* core change.
|
|
99
|
+
*/
|
|
100
|
+
export type ConnectorAccessTokenResolver = (binding: ConnectorConnectionBinding) => Promise<string | null>;
|
|
101
|
+
/** Lifecycle state of a connection's engine inside the registry. */
|
|
102
|
+
export type ConnectorEngineStatus = {
|
|
103
|
+
readonly state: 'unregistered';
|
|
104
|
+
} | {
|
|
105
|
+
readonly state: 'pending';
|
|
106
|
+
} | {
|
|
107
|
+
readonly state: 'ready';
|
|
108
|
+
} | {
|
|
109
|
+
readonly state: 'failed';
|
|
110
|
+
readonly reason: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Registry of connection name → constructed engine instance. Distinct from
|
|
114
|
+
* the entity system's `ConnectorRegistry`, which manages
|
|
115
|
+
* `EntityConnector` instances INSIDE one facade — this registry owns
|
|
116
|
+
* loading + constructing engines from atom bundles, world-wide.
|
|
117
|
+
*/
|
|
118
|
+
export interface ConnectorEngineRegistry {
|
|
119
|
+
/** Declare the world's connections (replaces the current set). */
|
|
120
|
+
configure(bindings: readonly ConnectorConnectionBinding[]): void;
|
|
121
|
+
/** Register an already-constructed engine directly (host/in-process). */
|
|
122
|
+
register(connection: string, engine: ConnectorEngine): void;
|
|
123
|
+
/**
|
|
124
|
+
* Resolve the engine for a connection name — loads the bundle and
|
|
125
|
+
* constructs the engine on first use, then answers from cache. NEVER
|
|
126
|
+
* throws: a failed load/construction marks the entry `failed` (with
|
|
127
|
+
* reason) and resolves `null` so consumers degrade honestly.
|
|
128
|
+
*/
|
|
129
|
+
resolve(connection: string): Promise<ConnectorEngine | null>;
|
|
130
|
+
/** Current lifecycle state of a connection (sync, for honest UI/errors). */
|
|
131
|
+
getStatus(connection: string): ConnectorEngineStatus;
|
|
132
|
+
/** Swap the token resolver (the auth-registry seam). Existing constructed
|
|
133
|
+
* engines keep their hook — it closes over the resolver reference, so a
|
|
134
|
+
* swap takes effect on the next token request, not the next construction. */
|
|
135
|
+
setAccessTokenResolver(resolver: ConnectorAccessTokenResolver): void;
|
|
136
|
+
/** Configured/registered connection names. */
|
|
137
|
+
list(): readonly string[];
|
|
138
|
+
/** Drop all bindings, instances, and failure states. */
|
|
139
|
+
clear(): void;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* One connection as blocks/the renderer see it. Shape-compatible with the
|
|
143
|
+
* runner's `PwappConnection` (`connections.json` entry) — single dialect,
|
|
144
|
+
* different source (platform: project connections doc + world connector
|
|
145
|
+
* rows; runner: connections.json).
|
|
146
|
+
*/
|
|
147
|
+
export interface SurfaceConnection {
|
|
148
|
+
readonly name: string;
|
|
149
|
+
/** Connector engine (atom) id serving this connection. */
|
|
150
|
+
readonly connector?: string;
|
|
151
|
+
readonly config?: Readonly<Record<string, unknown>>;
|
|
152
|
+
/** World row status when known (e.g. 'active' | 'pending'). */
|
|
153
|
+
readonly status?: string;
|
|
154
|
+
readonly authProviderRef?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Value carried by `SurfaceConnectionsContext` and the renderer's
|
|
158
|
+
* `connections` prop. `engines` may be null when the host provides the
|
|
159
|
+
* connections doc for bridge blocks but no loaded engines (yet).
|
|
160
|
+
*/
|
|
161
|
+
export interface SurfaceConnectionsValue {
|
|
162
|
+
readonly connections: readonly SurfaceConnection[];
|
|
163
|
+
readonly engines: ConnectorEngineRegistry | null;
|
|
164
|
+
/**
|
|
165
|
+
* the same live token the engine registry is constructed
|
|
166
|
+
* with, reachable by the data path.
|
|
167
|
+
*
|
|
168
|
+
* The registry already closes over a resolver, but it keeps it private, so a
|
|
169
|
+
* `rest` data source sitting beside an engine-backed one had no route to the
|
|
170
|
+
* identity the app was already signed in with. Exposed here, both paths draw
|
|
171
|
+
* on one bridge instead of the REST half having none.
|
|
172
|
+
*/
|
|
173
|
+
readonly getAccessToken?: ConnectorAccessTokenResolver;
|
|
174
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connector Engine Types
|
|
3
|
+
*
|
|
4
|
+
* Platform-side vocabulary for CONNECTOR/PROVIDER atom engines. Two
|
|
5
|
+
* consumption paths, ONE engine source:
|
|
6
|
+
*
|
|
7
|
+
* 1. dataSource path — a surface dataSource `{kind:'entity', entityType,
|
|
8
|
+
* connector:'graph-lists'}` routes through a `ConnectorEngineRegistry`:
|
|
9
|
+
* when a loaded engine is registered under that connection name the read
|
|
10
|
+
* goes through it (constructed with the world connection's config);
|
|
11
|
+
* absent engine/config keeps today's behavior (default facade or honest
|
|
12
|
+
* empty + `__errors` context), never a crash.
|
|
13
|
+
* 2. engine-bridge path — pack blocks get their connections/config from the
|
|
14
|
+
* runtime-provided connections context (`SurfaceConnectionsContext`).
|
|
15
|
+
* On the platform the value comes from the project's connections doc +
|
|
16
|
+
* world connector rows; in the runner the existing `connections.json`
|
|
17
|
+
* path is unchanged. Single dialect — the source differs, the shape
|
|
18
|
+
* doesn't (mirrors the runner's `PwappConnection`).
|
|
19
|
+
*
|
|
20
|
+
* @module @pwfabric/runtime/connectors/types
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/connectors/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG","sourcesContent":["/**\n * Connector Engine Types\n *\n * Platform-side vocabulary for CONNECTOR/PROVIDER atom engines. Two\n * consumption paths, ONE engine source:\n *\n * 1. dataSource path — a surface dataSource `{kind:'entity', entityType,\n * connector:'graph-lists'}` routes through a `ConnectorEngineRegistry`:\n * when a loaded engine is registered under that connection name the read\n * goes through it (constructed with the world connection's config);\n * absent engine/config keeps today's behavior (default facade or honest\n * empty + `__errors` context), never a crash.\n * 2. engine-bridge path — pack blocks get their connections/config from the\n * runtime-provided connections context (`SurfaceConnectionsContext`).\n * On the platform the value comes from the project's connections doc +\n * world connector rows; in the runner the existing `connections.json`\n * path is unchanged. Single dialect — the source differs, the shape\n * doesn't (mirrors the runner's `PwappConnection`).\n *\n * @module @pwfabric/runtime/connectors/types\n */\n\nimport type { EntityAggregate, EntityTypeId, EntityQuery } from '../entity/types.js'\nimport type { ConnectorAggregateResult, ConnectorQueryResult } from '../entity/connector.js'\n\n// ============================================================\n// ENGINE DESCRIPTOR (what the loader consumes)\n// ============================================================\n\n/**\n * Atom kinds that ship a connector engine bundle. `connector` = dynamic\n * data engine (e.g. graph-lists); `provider` = fixed-enum provider motor\n * facet (e.g. the single Graph motor behind graph-mail/graph-users/…).\n */\nexport type ConnectorEngineKind = 'connector' | 'provider'\n\n/**\n * Descriptor for a loadable connector-engine atom bundle. Mirrors\n * `DynamicBlockDescriptor` with the AtomRef `bundleUrl`\n * vocabulary: the publish pipeline uploads the ESM bundle and stamps its\n * SHA-256 — integrity is verified BEFORE evaluation (security boundary,\n * same law as block bundles).\n */\nexport interface ConnectorEngineDescriptor {\n /** Atom id of the engine (e.g. 'graph-lists', 'microsoft-graph-motor'). */\n readonly id: string\n readonly kind: ConnectorEngineKind\n /** CDN URL of the ESM bundle produced by the publish pipeline. */\n readonly bundleUrl: string\n /** SHA-256 of the bundle bytes (bare hex or SRI `sha256-<base64>`). */\n readonly integrity: string\n readonly version?: string\n}\n\n// ============================================================\n// ENGINE MODULE CONVENTION (what a bundle exports)\n// ============================================================\n\n/**\n * Per-call access-token supplier handed to an engine at construction —\n * exactly the signature the existing engines already take\n * (GraphListConnector / createGraphConnector). Re-invoked on every request\n * so token rotation is transparent. Resolving to `null` means\n * unauthenticated — engines degrade honestly (anon/empty), they do not\n * throw at construction time.\n */\nexport type ConnectorAccessTokenHook = () => Promise<string | null>\n\n/**\n * Factory a connector-engine bundle must export. The wrapper convention\n * (mirror of the block bundle's `Component` + `definition`) is a stable\n * `createConnector` named export; `default` is accepted as fallback.\n */\nexport type ConnectorEngineFactory = (\n getAccessToken: ConnectorAccessTokenHook,\n config: Readonly<Record<string, unknown>>\n) => unknown\n\n/** Module shape of an evaluated connector-engine bundle. */\nexport interface ConnectorEngineModule {\n readonly createConnector?: ConnectorEngineFactory\n readonly default?: ConnectorEngineFactory\n}\n\n/**\n * Minimal read contract every constructed engine must satisfy — the surface\n * dataSource path only lists records. Engines that additionally implement\n * the full `EntityConnector` interface can be registered into an\n * `EntityFacade` (`facade.connectors.register(engine)`) for the write path.\n */\nexport interface ConnectorEngine {\n readonly name?: string\n query(entityType: EntityTypeId, query: EntityQuery): Promise<ConnectorQueryResult>\n /** Optional: an engine that can count server-side; absent = list and reduce. */\n aggregate?(entityType: EntityTypeId, aggregate: EntityAggregate): Promise<ConnectorAggregateResult>\n}\n\n// ============================================================\n// CONNECTION BINDING (registry configuration unit)\n// ============================================================\n\n/**\n * One configured connection: a connector engine bound to this world with\n * per-connection config. `connection` is the connection NAME the surface\n * dialect references (`dataSources[].connector`); `descriptor` says which\n * engine bundle serves it; `config` is the world connection's config\n * (never credential values — auth law).\n */\nexport interface ConnectorConnectionBinding {\n readonly connection: string\n readonly descriptor: ConnectorEngineDescriptor\n readonly config?: Readonly<Record<string, unknown>>\n /** Auth binding BY NAME — resolved by the token resolver. */\n readonly authProviderRef?: string\n}\n\n/**\n * Injectable token resolver — the registry derives each engine's\n * `ConnectorAccessTokenHook` from this. By default the\n * resolver answers `null` (engines behave as unauthenticated); a host plugs\n * the AuthRegistry in through `setAccessTokenResolver` without another\n * core change.\n */\nexport type ConnectorAccessTokenResolver = (\n binding: ConnectorConnectionBinding\n) => Promise<string | null>\n\n// ============================================================\n// REGISTRY (name → engine instance)\n// ============================================================\n\n/** Lifecycle state of a connection's engine inside the registry. */\nexport type ConnectorEngineStatus =\n | { readonly state: 'unregistered' }\n | { readonly state: 'pending' }\n | { readonly state: 'ready' }\n | { readonly state: 'failed'; readonly reason: string }\n\n/**\n * Registry of connection name → constructed engine instance. Distinct from\n * the entity system's `ConnectorRegistry`, which manages\n * `EntityConnector` instances INSIDE one facade — this registry owns\n * loading + constructing engines from atom bundles, world-wide.\n */\nexport interface ConnectorEngineRegistry {\n /** Declare the world's connections (replaces the current set). */\n configure(bindings: readonly ConnectorConnectionBinding[]): void\n\n /** Register an already-constructed engine directly (host/in-process). */\n register(connection: string, engine: ConnectorEngine): void\n\n /**\n * Resolve the engine for a connection name — loads the bundle and\n * constructs the engine on first use, then answers from cache. NEVER\n * throws: a failed load/construction marks the entry `failed` (with\n * reason) and resolves `null` so consumers degrade honestly.\n */\n resolve(connection: string): Promise<ConnectorEngine | null>\n\n /** Current lifecycle state of a connection (sync, for honest UI/errors). */\n getStatus(connection: string): ConnectorEngineStatus\n\n /** Swap the token resolver (the auth-registry seam). Existing constructed\n * engines keep their hook — it closes over the resolver reference, so a\n * swap takes effect on the next token request, not the next construction. */\n setAccessTokenResolver(resolver: ConnectorAccessTokenResolver): void\n\n /** Configured/registered connection names. */\n list(): readonly string[]\n\n /** Drop all bindings, instances, and failure states. */\n clear(): void\n}\n\n// ============================================================\n// SURFACE CONNECTIONS CONTEXT VALUE (single dialect)\n// ============================================================\n\n/**\n * One connection as blocks/the renderer see it. Shape-compatible with the\n * runner's `PwappConnection` (`connections.json` entry) — single dialect,\n * different source (platform: project connections doc + world connector\n * rows; runner: connections.json).\n */\nexport interface SurfaceConnection {\n readonly name: string\n /** Connector engine (atom) id serving this connection. */\n readonly connector?: string\n readonly config?: Readonly<Record<string, unknown>>\n /** World row status when known (e.g. 'active' | 'pending'). */\n readonly status?: string\n readonly authProviderRef?: string\n}\n\n/**\n * Value carried by `SurfaceConnectionsContext` and the renderer's\n * `connections` prop. `engines` may be null when the host provides the\n * connections doc for bridge blocks but no loaded engines (yet).\n */\nexport interface SurfaceConnectionsValue {\n readonly connections: readonly SurfaceConnection[]\n readonly engines: ConnectorEngineRegistry | null\n /**\n * the same live token the engine registry is constructed\n * with, reachable by the data path.\n *\n * The registry already closes over a resolver, but it keeps it private, so a\n * `rest` data source sitting beside an engine-backed one had no route to the\n * identity the app was already signed in with. Exposed here, both paths draw\n * on one bridge instead of the REST half having none.\n */\n readonly getAccessToken?: ConnectorAccessTokenResolver\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution context for PWFabric runtime
|
|
3
|
+
*/
|
|
4
|
+
import { type Logger } from '@pwfabric/core';
|
|
5
|
+
/**
|
|
6
|
+
* Runtime context interface
|
|
7
|
+
*/
|
|
8
|
+
export interface RuntimeContext {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly logger: Logger;
|
|
11
|
+
readonly startTime: Date;
|
|
12
|
+
readonly metadata: Map<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a new runtime context
|
|
16
|
+
*/
|
|
17
|
+
export declare function createContext(name: string): RuntimeContext;
|
|
18
|
+
/**
|
|
19
|
+
* Context builder for fluent API
|
|
20
|
+
*/
|
|
21
|
+
export declare class ContextBuilder {
|
|
22
|
+
private name;
|
|
23
|
+
private meta;
|
|
24
|
+
withName(name: string): this;
|
|
25
|
+
withMetadata(key: string, value: unknown): this;
|
|
26
|
+
build(): RuntimeContext;
|
|
27
|
+
}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution context for PWFabric runtime
|
|
3
|
+
*/
|
|
4
|
+
import { createLogger } from '@pwfabric/core';
|
|
5
|
+
/**
|
|
6
|
+
* Create a new runtime context
|
|
7
|
+
*/
|
|
8
|
+
export function createContext(name) {
|
|
9
|
+
return {
|
|
10
|
+
id: crypto.randomUUID(),
|
|
11
|
+
logger: createLogger(`runtime:${name}`),
|
|
12
|
+
startTime: new Date(),
|
|
13
|
+
metadata: new Map(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Context builder for fluent API
|
|
18
|
+
*/
|
|
19
|
+
export class ContextBuilder {
|
|
20
|
+
name = 'default';
|
|
21
|
+
meta = new Map();
|
|
22
|
+
withName(name) {
|
|
23
|
+
this.name = name;
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
withMetadata(key, value) {
|
|
27
|
+
this.meta.set(key, value);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
build() {
|
|
31
|
+
const ctx = createContext(this.name);
|
|
32
|
+
for (const [key, value] of this.meta) {
|
|
33
|
+
ctx.metadata.set(key, value);
|
|
34
|
+
}
|
|
35
|
+
return ctx;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAe,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAY1D;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,MAAM,EAAE,YAAY,CAAC,WAAW,IAAI,EAAE,CAAC;QACvC,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,QAAQ,EAAE,IAAI,GAAG,EAAE;KACpB,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,cAAc;IACjB,IAAI,GAAG,SAAS,CAAA;IAChB,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAA;IAEzC,QAAQ,CAAC,IAAY;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,KAAc;QACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC9B,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF","sourcesContent":["/**\n * Execution context for PWFabric runtime\n */\n\nimport { type Logger, createLogger } from '@pwfabric/core'\n\n/**\n * Runtime context interface\n */\nexport interface RuntimeContext {\n readonly id: string\n readonly logger: Logger\n readonly startTime: Date\n readonly metadata: Map<string, unknown>\n}\n\n/**\n * Create a new runtime context\n */\nexport function createContext(name: string): RuntimeContext {\n return {\n id: crypto.randomUUID(),\n logger: createLogger(`runtime:${name}`),\n startTime: new Date(),\n metadata: new Map(),\n }\n}\n\n/**\n * Context builder for fluent API\n */\nexport class ContextBuilder {\n private name = 'default'\n private meta = new Map<string, unknown>()\n\n withName(name: string): this {\n this.name = name\n return this\n }\n\n withMetadata(key: string, value: unknown): this {\n this.meta.set(key, value)\n return this\n }\n\n build(): RuntimeContext {\n const ctx = createContext(this.name)\n for (const [key, value] of this.meta) {\n ctx.metadata.set(key, value)\n }\n return ctx\n }\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Capability Provider
|
|
3
|
+
*
|
|
4
|
+
* React context bridge between the capability registry and the render layer.
|
|
5
|
+
* Instantiates a DataService with config and exposes it via useDataService() hook.
|
|
6
|
+
*
|
|
7
|
+
* This is the canonical pattern for capability → React integration.
|
|
8
|
+
* Other capabilities (auth, routing, analytics, etc.) should follow the same structure.
|
|
9
|
+
*
|
|
10
|
+
* @module @pwfabric/runtime/data/DataCapabilityProvider
|
|
11
|
+
*/
|
|
12
|
+
import * as React from 'react';
|
|
13
|
+
import type { DataServiceInterface, DataServiceConfig } from './types.js';
|
|
14
|
+
export interface DataCapabilityProviderProps {
|
|
15
|
+
readonly config?: DataServiceConfig;
|
|
16
|
+
readonly service?: DataServiceInterface;
|
|
17
|
+
readonly children: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Provides a DataService instance to the component tree.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* - Pass `config` to let the provider create a DataService internally.
|
|
24
|
+
* - Pass `service` to inject an existing DataService (useful for testing or
|
|
25
|
+
* when the capability registry has already instantiated one).
|
|
26
|
+
* - If both are provided, `service` takes precedence.
|
|
27
|
+
*/
|
|
28
|
+
export declare function DataCapabilityProvider({ config, service, children, }: DataCapabilityProviderProps): React.ReactElement;
|
|
29
|
+
/**
|
|
30
|
+
* Access the DataService from the nearest DataCapabilityProvider.
|
|
31
|
+
*
|
|
32
|
+
* @throws Error if called outside of a DataCapabilityProvider.
|
|
33
|
+
*/
|
|
34
|
+
export declare function useDataService(): DataServiceInterface;
|
|
35
|
+
/**
|
|
36
|
+
* Optionally access the DataService — returns null if no provider is present.
|
|
37
|
+
* Useful for components that work with or without data binding.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useOptionalDataService(): DataServiceInterface | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Data Capability Provider
|
|
4
|
+
*
|
|
5
|
+
* React context bridge between the capability registry and the render layer.
|
|
6
|
+
* Instantiates a DataService with config and exposes it via useDataService() hook.
|
|
7
|
+
*
|
|
8
|
+
* This is the canonical pattern for capability → React integration.
|
|
9
|
+
* Other capabilities (auth, routing, analytics, etc.) should follow the same structure.
|
|
10
|
+
*
|
|
11
|
+
* @module @pwfabric/runtime/data/DataCapabilityProvider
|
|
12
|
+
*/
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import { DataService } from './manager.js';
|
|
15
|
+
// ============================================================
|
|
16
|
+
// CONTEXT
|
|
17
|
+
// ============================================================
|
|
18
|
+
const DataServiceContext = React.createContext(null);
|
|
19
|
+
/**
|
|
20
|
+
* Provides a DataService instance to the component tree.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* - Pass `config` to let the provider create a DataService internally.
|
|
24
|
+
* - Pass `service` to inject an existing DataService (useful for testing or
|
|
25
|
+
* when the capability registry has already instantiated one).
|
|
26
|
+
* - If both are provided, `service` takes precedence.
|
|
27
|
+
*/
|
|
28
|
+
export function DataCapabilityProvider({ config, service, children, }) {
|
|
29
|
+
const dataService = React.useMemo(() => {
|
|
30
|
+
if (service)
|
|
31
|
+
return service;
|
|
32
|
+
return new DataService(config);
|
|
33
|
+
}, [service, config]);
|
|
34
|
+
return _jsx(DataServiceContext.Provider, { value: dataService, children: children });
|
|
35
|
+
}
|
|
36
|
+
// ============================================================
|
|
37
|
+
// HOOK
|
|
38
|
+
// ============================================================
|
|
39
|
+
/**
|
|
40
|
+
* Access the DataService from the nearest DataCapabilityProvider.
|
|
41
|
+
*
|
|
42
|
+
* @throws Error if called outside of a DataCapabilityProvider.
|
|
43
|
+
*/
|
|
44
|
+
export function useDataService() {
|
|
45
|
+
const service = React.useContext(DataServiceContext);
|
|
46
|
+
if (!service) {
|
|
47
|
+
throw new Error('useDataService must be used within a DataCapabilityProvider');
|
|
48
|
+
}
|
|
49
|
+
return service;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Optionally access the DataService — returns null if no provider is present.
|
|
53
|
+
* Useful for components that work with or without data binding.
|
|
54
|
+
*/
|
|
55
|
+
export function useOptionalDataService() {
|
|
56
|
+
return React.useContext(DataServiceContext);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=DataCapabilityProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataCapabilityProvider.js","sourceRoot":"","sources":["../../src/data/DataCapabilityProvider.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,+DAA+D;AAC/D,UAAU;AACV,+DAA+D;AAE/D,MAAM,kBAAkB,GAAG,KAAK,CAAC,aAAa,CAA8B,IAAI,CAAC,CAAA;AAYjF;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,MAAM,EACN,OAAO,EACP,QAAQ,GACoB;IAC5B,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACrC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;QAC3B,OAAO,IAAI,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;IAErB,OAAO,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YAAG,QAAQ,GAA+B,CAAA;AAClG,CAAC;AAED,+DAA+D;AAC/D,OAAO;AACP,+DAA+D;AAE/D;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAA;IACpD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;IAChF,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["/**\n * Data Capability Provider\n *\n * React context bridge between the capability registry and the render layer.\n * Instantiates a DataService with config and exposes it via useDataService() hook.\n *\n * This is the canonical pattern for capability → React integration.\n * Other capabilities (auth, routing, analytics, etc.) should follow the same structure.\n *\n * @module @pwfabric/runtime/data/DataCapabilityProvider\n */\n\nimport * as React from 'react'\nimport { DataService } from './manager.js'\nimport type { DataServiceInterface, DataServiceConfig } from './types.js'\n\n// ============================================================\n// CONTEXT\n// ============================================================\n\nconst DataServiceContext = React.createContext<DataServiceInterface | null>(null)\n\n// ============================================================\n// PROVIDER\n// ============================================================\n\nexport interface DataCapabilityProviderProps {\n readonly config?: DataServiceConfig\n readonly service?: DataServiceInterface\n readonly children: React.ReactNode\n}\n\n/**\n * Provides a DataService instance to the component tree.\n *\n * Usage:\n * - Pass `config` to let the provider create a DataService internally.\n * - Pass `service` to inject an existing DataService (useful for testing or\n * when the capability registry has already instantiated one).\n * - If both are provided, `service` takes precedence.\n */\nexport function DataCapabilityProvider({\n config,\n service,\n children,\n}: DataCapabilityProviderProps): React.ReactElement {\n const dataService = React.useMemo(() => {\n if (service) return service\n return new DataService(config)\n }, [service, config])\n\n return <DataServiceContext.Provider value={dataService}>{children}</DataServiceContext.Provider>\n}\n\n// ============================================================\n// HOOK\n// ============================================================\n\n/**\n * Access the DataService from the nearest DataCapabilityProvider.\n *\n * @throws Error if called outside of a DataCapabilityProvider.\n */\nexport function useDataService(): DataServiceInterface {\n const service = React.useContext(DataServiceContext)\n if (!service) {\n throw new Error('useDataService must be used within a DataCapabilityProvider')\n }\n return service\n}\n\n/**\n * Optionally access the DataService — returns null if no provider is present.\n * Useful for components that work with or without data binding.\n */\nexport function useOptionalDataService(): DataServiceInterface | null {\n return React.useContext(DataServiceContext)\n}\n"]}
|