@flyingrobots/bijou 4.4.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -1
- package/dist/adapters/test/index.d.ts.map +1 -1
- package/dist/adapters/test/index.js +1 -3
- package/dist/adapters/test/index.js.map +1 -1
- package/dist/adapters/test/runtime.d.ts.map +1 -1
- package/dist/adapters/test/runtime.js +4 -3
- package/dist/adapters/test/runtime.js.map +1 -1
- package/dist/context-theme.d.ts +25 -0
- package/dist/context-theme.d.ts.map +1 -1
- package/dist/context-theme.js +19 -0
- package/dist/context-theme.js.map +1 -1
- package/dist/context.d.ts +13 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +24 -3
- package/dist/context.js.map +1 -1
- package/dist/core/active-binding-collection.d.ts +49 -0
- package/dist/core/active-binding-collection.d.ts.map +1 -0
- package/dist/core/active-binding-collection.js +264 -0
- package/dist/core/active-binding-collection.js.map +1 -0
- package/dist/core/app-shell-composition.d.ts +44 -0
- package/dist/core/app-shell-composition.d.ts.map +1 -0
- package/dist/core/app-shell-composition.js +123 -0
- package/dist/core/app-shell-composition.js.map +1 -0
- package/dist/core/binding-frame-update.d.ts +18 -0
- package/dist/core/binding-frame-update.d.ts.map +1 -0
- package/dist/core/binding-frame-update.js +133 -0
- package/dist/core/binding-frame-update.js.map +1 -0
- package/dist/core/binding-lifecycle.d.ts +65 -0
- package/dist/core/binding-lifecycle.d.ts.map +1 -0
- package/dist/core/binding-lifecycle.js +357 -0
- package/dist/core/binding-lifecycle.js.map +1 -0
- package/dist/core/binding.d.ts +192 -0
- package/dist/core/binding.d.ts.map +1 -0
- package/dist/core/binding.js +587 -0
- package/dist/core/binding.js.map +1 -0
- package/dist/core/block-metadata.d.ts +113 -0
- package/dist/core/block-metadata.d.ts.map +1 -0
- package/dist/core/block-metadata.js +376 -0
- package/dist/core/block-metadata.js.map +1 -0
- package/dist/core/block-tree-render.d.ts +17 -0
- package/dist/core/block-tree-render.d.ts.map +1 -0
- package/dist/core/block-tree-render.js +186 -0
- package/dist/core/block-tree-render.js.map +1 -0
- package/dist/core/component-metadata.d.ts +63 -0
- package/dist/core/component-metadata.d.ts.map +1 -0
- package/dist/core/component-metadata.js +158 -0
- package/dist/core/component-metadata.js.map +1 -0
- package/dist/core/components/alert-v3.d.ts.map +1 -1
- package/dist/core/components/alert-v3.js +5 -4
- package/dist/core/components/alert-v3.js.map +1 -1
- package/dist/core/components/alert.d.ts.map +1 -1
- package/dist/core/components/alert.js +7 -8
- package/dist/core/components/alert.js.map +1 -1
- package/dist/core/components/badge.d.ts.map +1 -1
- package/dist/core/components/badge.js +19 -18
- package/dist/core/components/badge.js.map +1 -1
- package/dist/core/components/box-v3.d.ts.map +1 -1
- package/dist/core/components/box-v3.js +29 -29
- package/dist/core/components/box-v3.js.map +1 -1
- package/dist/core/components/dag-edges.d.ts +28 -5
- package/dist/core/components/dag-edges.d.ts.map +1 -1
- package/dist/core/components/dag-edges.js +116 -22
- package/dist/core/components/dag-edges.js.map +1 -1
- package/dist/core/components/dag-layout.d.ts +3 -4
- package/dist/core/components/dag-layout.d.ts.map +1 -1
- package/dist/core/components/dag-layout.js +42 -9
- package/dist/core/components/dag-layout.js.map +1 -1
- package/dist/core/components/dag-render.d.ts +4 -3
- package/dist/core/components/dag-render.d.ts.map +1 -1
- package/dist/core/components/dag-render.js +209 -105
- package/dist/core/components/dag-render.js.map +1 -1
- package/dist/core/components/dag-source.d.ts +4 -0
- package/dist/core/components/dag-source.d.ts.map +1 -1
- package/dist/core/components/dag-source.js +10 -0
- package/dist/core/components/dag-source.js.map +1 -1
- package/dist/core/components/dag.d.ts +20 -4
- package/dist/core/components/dag.d.ts.map +1 -1
- package/dist/core/components/dag.js.map +1 -1
- package/dist/core/components/explainability.d.ts.map +1 -1
- package/dist/core/components/explainability.js +30 -87
- package/dist/core/components/explainability.js.map +1 -1
- package/dist/core/components/guided-flow.d.ts +32 -0
- package/dist/core/components/guided-flow.d.ts.map +1 -0
- package/dist/core/components/guided-flow.js +131 -0
- package/dist/core/components/guided-flow.js.map +1 -0
- package/dist/core/components/hyperlink.d.ts.map +1 -1
- package/dist/core/components/hyperlink.js +7 -4
- package/dist/core/components/hyperlink.js.map +1 -1
- package/dist/core/components/index.d.ts +5 -3
- package/dist/core/components/index.d.ts.map +1 -1
- package/dist/core/components/index.js +1 -0
- package/dist/core/components/index.js.map +1 -1
- package/dist/core/components/markdown-parse.d.ts +4 -0
- package/dist/core/components/markdown-parse.d.ts.map +1 -1
- package/dist/core/components/markdown-parse.js +66 -2
- package/dist/core/components/markdown-parse.js.map +1 -1
- package/dist/core/components/markdown-render.d.ts.map +1 -1
- package/dist/core/components/markdown-render.js +220 -14
- package/dist/core/components/markdown-render.js.map +1 -1
- package/dist/core/components/markdown.d.ts +4 -3
- package/dist/core/components/markdown.d.ts.map +1 -1
- package/dist/core/components/markdown.js +6 -5
- package/dist/core/components/markdown.js.map +1 -1
- package/dist/core/components/paginator.d.ts.map +1 -1
- package/dist/core/components/paginator.js +5 -3
- package/dist/core/components/paginator.js.map +1 -1
- package/dist/core/components/perf-overlay.d.ts.map +1 -1
- package/dist/core/components/perf-overlay.js +3 -2
- package/dist/core/components/perf-overlay.js.map +1 -1
- package/dist/core/components/preference-list.d.ts.map +1 -1
- package/dist/core/components/preference-list.js +75 -37
- package/dist/core/components/preference-list.js.map +1 -1
- package/dist/core/components/progress.d.ts.map +1 -1
- package/dist/core/components/progress.js +4 -3
- package/dist/core/components/progress.js.map +1 -1
- package/dist/core/components/separator-v3.d.ts.map +1 -1
- package/dist/core/components/separator-v3.js +11 -11
- package/dist/core/components/separator-v3.js.map +1 -1
- package/dist/core/components/separator.d.ts.map +1 -1
- package/dist/core/components/separator.js +4 -1
- package/dist/core/components/separator.js.map +1 -1
- package/dist/core/components/skeleton.d.ts.map +1 -1
- package/dist/core/components/skeleton.js +3 -2
- package/dist/core/components/skeleton.js.map +1 -1
- package/dist/core/components/surface-text.d.ts +7 -0
- package/dist/core/components/surface-text.d.ts.map +1 -1
- package/dist/core/components/surface-text.js +33 -25
- package/dist/core/components/surface-text.js.map +1 -1
- package/dist/core/components/table-v3.d.ts +5 -2
- package/dist/core/components/table-v3.d.ts.map +1 -1
- package/dist/core/components/table-v3.js +162 -37
- package/dist/core/components/table-v3.js.map +1 -1
- package/dist/core/components/table.d.ts +51 -7
- package/dist/core/components/table.d.ts.map +1 -1
- package/dist/core/components/table.js +655 -81
- package/dist/core/components/table.js.map +1 -1
- package/dist/core/fixture-promotion.d.ts +33 -0
- package/dist/core/fixture-promotion.d.ts.map +1 -0
- package/dist/core/fixture-promotion.js +62 -0
- package/dist/core/fixture-promotion.js.map +1 -0
- package/dist/core/forms/filter-interactive.d.ts.map +1 -1
- package/dist/core/forms/filter-interactive.js +2 -4
- package/dist/core/forms/filter-interactive.js.map +1 -1
- package/dist/core/forms/multiselect.d.ts.map +1 -1
- package/dist/core/forms/multiselect.js +2 -4
- package/dist/core/forms/multiselect.js.map +1 -1
- package/dist/core/forms/note.d.ts.map +1 -1
- package/dist/core/forms/note.js +2 -1
- package/dist/core/forms/note.js.map +1 -1
- package/dist/core/forms/select.d.ts.map +1 -1
- package/dist/core/forms/select.js +2 -4
- package/dist/core/forms/select.js.map +1 -1
- package/dist/core/forms/textarea-editor.d.ts.map +1 -1
- package/dist/core/forms/textarea-editor.js +7 -5
- package/dist/core/forms/textarea-editor.js.map +1 -1
- package/dist/core/layout/envelope.d.ts +174 -0
- package/dist/core/layout/envelope.d.ts.map +1 -0
- package/dist/core/layout/envelope.js +336 -0
- package/dist/core/layout/envelope.js.map +1 -0
- package/dist/core/layout/geometry.d.ts +39 -0
- package/dist/core/layout/geometry.d.ts.map +1 -0
- package/dist/core/layout/geometry.js +201 -0
- package/dist/core/layout/geometry.js.map +1 -0
- package/dist/core/mode-lowering.d.ts +48 -0
- package/dist/core/mode-lowering.d.ts.map +1 -0
- package/dist/core/mode-lowering.js +176 -0
- package/dist/core/mode-lowering.js.map +1 -0
- package/dist/core/numeric.d.ts +16 -0
- package/dist/core/numeric.d.ts.map +1 -0
- package/dist/core/numeric.js +37 -0
- package/dist/core/numeric.js.map +1 -0
- package/dist/core/render/differ.d.ts.map +1 -1
- package/dist/core/render/differ.js +15 -13
- package/dist/core/render/differ.js.map +1 -1
- package/dist/core/runtime-viewport.d.ts.map +1 -1
- package/dist/core/runtime-viewport.js +2 -3
- package/dist/core/runtime-viewport.js.map +1 -1
- package/dist/core/schema-block.d.ts +63 -0
- package/dist/core/schema-block.d.ts.map +1 -0
- package/dist/core/schema-block.js +361 -0
- package/dist/core/schema-block.js.map +1 -0
- package/dist/core/selection.d.ts +127 -0
- package/dist/core/selection.d.ts.map +1 -0
- package/dist/core/selection.js +350 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/standard-blocks.d.ts +264 -0
- package/dist/core/standard-blocks.d.ts.map +1 -0
- package/dist/core/standard-blocks.js +2518 -0
- package/dist/core/standard-blocks.js.map +1 -0
- package/dist/core/story-capture.d.ts +48 -0
- package/dist/core/story-capture.d.ts.map +1 -0
- package/dist/core/story-capture.js +64 -0
- package/dist/core/story-capture.js.map +1 -0
- package/dist/core/text/grapheme.d.ts +51 -0
- package/dist/core/text/grapheme.d.ts.map +1 -1
- package/dist/core/text/grapheme.js +68 -0
- package/dist/core/text/grapheme.js.map +1 -1
- package/dist/core/text/icon-presentation.d.ts +10 -0
- package/dist/core/text/icon-presentation.d.ts.map +1 -0
- package/dist/core/text/icon-presentation.js +12 -0
- package/dist/core/text/icon-presentation.js.map +1 -0
- package/dist/core/text/index.d.ts +2 -1
- package/dist/core/text/index.d.ts.map +1 -1
- package/dist/core/text/index.js +2 -1
- package/dist/core/text/index.js.map +1 -1
- package/dist/core/text/wrap.d.ts.map +1 -1
- package/dist/core/text/wrap.js +37 -20
- package/dist/core/text/wrap.js.map +1 -1
- package/dist/core/theme/color.d.ts +32 -0
- package/dist/core/theme/color.d.ts.map +1 -1
- package/dist/core/theme/color.js +68 -0
- package/dist/core/theme/color.js.map +1 -1
- package/dist/core/theme/doctor.d.ts +37 -0
- package/dist/core/theme/doctor.d.ts.map +1 -0
- package/dist/core/theme/doctor.js +175 -0
- package/dist/core/theme/doctor.js.map +1 -0
- package/dist/core/theme/dtcg.d.ts.map +1 -1
- package/dist/core/theme/dtcg.js +10 -1
- package/dist/core/theme/dtcg.js.map +1 -1
- package/dist/core/theme/graph-types.d.ts +5 -0
- package/dist/core/theme/graph-types.d.ts.map +1 -1
- package/dist/core/theme/graph.d.ts.map +1 -1
- package/dist/core/theme/graph.js +52 -5
- package/dist/core/theme/graph.js.map +1 -1
- package/dist/core/theme/index.d.ts +4 -1
- package/dist/core/theme/index.d.ts.map +1 -1
- package/dist/core/theme/index.js +3 -1
- package/dist/core/theme/index.js.map +1 -1
- package/dist/core/theme/presets.d.ts +3 -2
- package/dist/core/theme/presets.d.ts.map +1 -1
- package/dist/core/theme/presets.js +22 -29
- package/dist/core/theme/presets.js.map +1 -1
- package/dist/core/theme/tokens.d.ts +1 -1
- package/dist/core/theme/tokens.d.ts.map +1 -1
- package/dist/factory.d.ts +3 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +4 -6
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +23 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -6
- package/dist/index.js.map +1 -1
- package/dist/ports/context.d.ts +6 -1
- package/dist/ports/context.d.ts.map +1 -1
- package/dist/ports/surface.d.ts +6 -4
- package/dist/ports/surface.d.ts.map +1 -1
- package/dist/ports/surface.js +40 -23
- package/dist/ports/surface.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -45,10 +45,18 @@ const panel = boxSurface(
|
|
|
45
45
|
|
|
46
46
|
Select the family based on the interaction semantic, not just the visual shape.
|
|
47
47
|
|
|
48
|
+
Render-path naming follows one house rule: the base family name is the public
|
|
49
|
+
component, and a `*Surface()` companion means “the same family on the composable
|
|
50
|
+
surface path.” If there is no `*Surface()` companion, the family is either
|
|
51
|
+
already surface-native, intentionally string-first, or both paths would be
|
|
52
|
+
fake duplication rather than a real second API.
|
|
53
|
+
|
|
48
54
|
### Status and Feedback
|
|
49
55
|
- **`badge()`**: Compact, inline status.
|
|
50
56
|
- **`note()`**: Non-urgent explanation.
|
|
51
57
|
- **`alert()`**: Persistent, in-flow message.
|
|
58
|
+
- **`guidedFlow()`**: Calm multi-step assistance with one explicit next action.
|
|
59
|
+
- **`explainability()`**: AI- or machine-mediated recommendation with visible provenance and evidence.
|
|
52
60
|
- *Use `@flyingrobots/bijou-tui` notifications for stacking, history, or active routing.*
|
|
53
61
|
|
|
54
62
|
### Selection and Prompts
|
|
@@ -68,11 +76,73 @@ Select the family based on the interaction semantic, not just the visual shape.
|
|
|
68
76
|
- **`breadcrumb()`**: Path context.
|
|
69
77
|
- **`stepper()`**: Ordered stages in a linear process.
|
|
70
78
|
|
|
79
|
+
### Theme Authoring
|
|
80
|
+
- **`extendTheme()`**: Build a custom theme from a known-good preset.
|
|
81
|
+
- **`doctorTheme()`**: Structured checks for invalid colors, weak contrast,
|
|
82
|
+
and suspicious token reuse.
|
|
83
|
+
- **`themeContrastRatio()`**: Deterministic foreground/background contrast
|
|
84
|
+
calculation for token-pair tests.
|
|
85
|
+
|
|
86
|
+
### Mode-Aware Authoring
|
|
87
|
+
- **`renderByMode()`**: Dispatch a component to the current output contract.
|
|
88
|
+
- **`lintModeLowering()`**: Compare explicit semantic facts across output modes.
|
|
89
|
+
- **`modeLoweringReportText()`**: Render a compact lowering report for tests,
|
|
90
|
+
docs, and review comments.
|
|
91
|
+
- **`defineComponentMetadata()`**: Declare validated package, family, mode,
|
|
92
|
+
arg, variant, invariant, example, and source facts for tooling.
|
|
93
|
+
- **`componentMetadataSummary()`**: Render compact metadata for docs, MCP
|
|
94
|
+
payloads, and agent-facing reports.
|
|
95
|
+
- **`defineBlock()`**: Declare a validated reusable block with package, family,
|
|
96
|
+
scale, mode, slot, variant, config, component, story, semantic facts, optional
|
|
97
|
+
view data contracts, and command intents.
|
|
98
|
+
- **`standardBlocks` / standard block exports**: Import the first-party
|
|
99
|
+
standard block definitions for AppShell, ReaderSurface, InspectorPanel,
|
|
100
|
+
inline status, in-flow status, transient overlay feedback, activity stream,
|
|
101
|
+
shortcut cues, and progress. These expose contracts, stories, data
|
|
102
|
+
requirements, command intents, and schema-bound posture, with deterministic
|
|
103
|
+
first-proof render output across all output modes. Production AppShell
|
|
104
|
+
behavior remains a later runtime slice.
|
|
105
|
+
- **`defineBlockPackage()`**: Declare exported blocks, docs, tags, version, and
|
|
106
|
+
Bijou peer compatibility for ordinary NPM block packages.
|
|
107
|
+
- **`defineBlockSchemaAdapter()` / `defineSchemaBlock()`**: Validate unknown
|
|
108
|
+
boundary data before producing immutable block render input and binding facts,
|
|
109
|
+
without fetching, subscribing, dispatching, or rendering AppShell.
|
|
110
|
+
- **`blockMetadataSummary()`**: Render compact block metadata for docs, MCP
|
|
111
|
+
payloads, and agent-facing reports.
|
|
112
|
+
- **`defineAppShellComposition()`**: Compose runtime-backed blocks into logical
|
|
113
|
+
AppShell slots with an explicit provider scope, without rendering or
|
|
114
|
+
subscribing.
|
|
115
|
+
- **`blockRenderNode()` / `renderBlockTree()`**: Explicitly render nested block
|
|
116
|
+
declarations into parent slots when a preview or host intentionally wants a
|
|
117
|
+
block tree, while ordinary `block.render()` remains a local single-block
|
|
118
|
+
render contract.
|
|
119
|
+
- **`defineDataRequirement()` / `defineDataProvider()` / `providerScope()`**:
|
|
120
|
+
Declare data requirements and explicit local provider availability without
|
|
121
|
+
hidden global registration.
|
|
122
|
+
- **`defineViewData()`**: Group named data requirements for a view or block
|
|
123
|
+
without binding them to providers.
|
|
124
|
+
- **`resolveProviderRequirement()`**: Resolve a requirement against an explicit
|
|
125
|
+
local provider scope as frozen metadata, without subscribing or fetching.
|
|
126
|
+
- **`bindingFrameFromSnapshots()`**: Assemble read-only render frames from
|
|
127
|
+
resolved provider metadata and already-created immutable snapshots.
|
|
128
|
+
- **`bindingSnapshot()` / `bindingFrame()`**: Model provider-delivered plain
|
|
129
|
+
data as copied, versioned immutable snapshots and read-only render frames.
|
|
130
|
+
- **`commandIntent()`**: Declare user intent outputs as inspectable metadata,
|
|
131
|
+
without business-logic callbacks or provider mutation handles.
|
|
132
|
+
- **`captureStoryMatrix()`**: Capture every profile/variant pair from a story
|
|
133
|
+
renderer.
|
|
134
|
+
- **`storyCaptureMatrixText()`**: Render a deterministic multi-mode story
|
|
135
|
+
matrix for docs and tests.
|
|
136
|
+
- **`createFixturePromotionRecord()`**: Preserve provenance when a fixture,
|
|
137
|
+
docs page, story, example, or MCP payload is promoted into another surface.
|
|
138
|
+
- **`fixturePromotionText()`**: Render that promotion record for review and
|
|
139
|
+
agent output.
|
|
140
|
+
|
|
71
141
|
## Documentation
|
|
72
142
|
|
|
73
143
|
- **[GUIDE.md](./GUIDE.md)**: Productive-fast path.
|
|
74
144
|
- **[ADVANCED_GUIDE.md](./ADVANCED_GUIDE.md)**: Rendering doctrine, themes, and testing.
|
|
75
|
-
- **[Design System](../../docs/design-system/README.md)**:
|
|
145
|
+
- **[Design System](../../docs/design-system/README.md)**: Foundations, token vocabulary, and component families.
|
|
76
146
|
|
|
77
147
|
---
|
|
78
148
|
Built with 💎 by [FLYING ROBOTS](https://github.com/flyingrobots)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAU,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAa,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAU,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAa,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,wEAAwE;IACxE,EAAE,CAAC,EAAE,aAAa,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wDAAwD;IACxD,KAAK,CAAC,EAAE,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;IACjD,gDAAgD;IAChD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AASD;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,YAAY;IAC/C,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAwB/E"}
|
|
@@ -5,7 +5,6 @@ import { plainStyle } from './style.js';
|
|
|
5
5
|
import { createResolved } from '../../core/theme/resolve.js';
|
|
6
6
|
import { CYAN_MAGENTA } from '../../core/theme/presets.js';
|
|
7
7
|
import { createThemeAccessors } from '../../core/theme/accessors.js';
|
|
8
|
-
import { createTokenGraph } from '../../core/theme/graph.js';
|
|
9
8
|
import { systemClock } from '../../core/clock.js';
|
|
10
9
|
export { mockRuntime } from './runtime.js';
|
|
11
10
|
export { mockIO } from './io.js';
|
|
@@ -44,7 +43,6 @@ export function createTestContext(options = {}) {
|
|
|
44
43
|
: options.io);
|
|
45
44
|
const style = options.style ?? plainStyle();
|
|
46
45
|
const theme = createResolved(options.theme ?? CYAN_MAGENTA, options.noColor ?? false, options.colorScheme ?? 'dark');
|
|
47
|
-
const tokenGraph = createTokenGraph((options.theme ?? CYAN_MAGENTA));
|
|
48
46
|
const mode = options.mode ?? 'interactive';
|
|
49
47
|
return {
|
|
50
48
|
theme,
|
|
@@ -53,7 +51,7 @@ export function createTestContext(options = {}) {
|
|
|
53
51
|
io,
|
|
54
52
|
clock,
|
|
55
53
|
style,
|
|
56
|
-
tokenGraph,
|
|
54
|
+
tokenGraph: theme.tokenGraph,
|
|
57
55
|
resolveBCSS: () => ({}),
|
|
58
56
|
...createThemeAccessors(theme),
|
|
59
57
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAErE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAwC,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAwBlE,SAAS,WAAW,CAAC,KAA2D;IAC9E,OAAO,OAAO,KAAK,KAAK,QAAQ;WAC3B,KAAK,KAAK,IAAI;WACd,KAAK,IAAI,KAAK;WACd,OAAO,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC;AACvC,CAAC;AAWD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8B,EAAE;IAChE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC;IAC1D,MAAM,KAAK,GAAG,cAAc,KAAK,SAAS;QACxC,CAAC,CAAC,WAAW,EAAE;QACf,CAAC,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;QAC/C,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE;QAClC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC;IACrH,MAAM,IAAI,GAAe,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC;IAEvD,OAAO;QACL,KAAK;QACL,IAAI;QACJ,OAAO;QACP,EAAE;QACF,KAAK;QACL,KAAK;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QACvB,GAAG,oBAAoB,CAAC,KAAK,CAAC;KAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAiBzE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sanitizePositiveInt } from '../../core/numeric.js';
|
|
1
2
|
/**
|
|
2
3
|
* Create an in-memory {@link RuntimePort} for tests.
|
|
3
4
|
*
|
|
@@ -20,9 +21,9 @@ export function mockRuntime(options = {}) {
|
|
|
20
21
|
},
|
|
21
22
|
stdoutIsTTY: options.stdoutIsTTY ?? true,
|
|
22
23
|
stdinIsTTY: options.stdinIsTTY ?? true,
|
|
23
|
-
columns: options.columns
|
|
24
|
-
rows: options.rows
|
|
25
|
-
refreshRate: options.refreshRate
|
|
24
|
+
columns: sanitizePositiveInt(options.columns, 80),
|
|
25
|
+
rows: sanitizePositiveInt(options.rows, 24),
|
|
26
|
+
refreshRate: sanitizePositiveInt(options.refreshRate, 60),
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
29
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAoB5D;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,UAA8B,EAAE;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IACjC,OAAO;QACL;;;;WAIG;QACH,GAAG,CAAC,GAAW;YACb,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;QACtC,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,IAAI,EAAE,mBAAmB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,WAAW,EAAE,mBAAmB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC"}
|
package/dist/context-theme.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import type { BijouContext } from './ports/context.js';
|
|
2
2
|
import { type ResolvedTheme } from './core/theme/resolve.js';
|
|
3
3
|
import type { Theme } from './core/theme/tokens.js';
|
|
4
|
+
/** Notification emitted when the observed theme graph changes. */
|
|
5
|
+
export interface ThemeChange {
|
|
6
|
+
/** The context whose theme graph emitted the change. */
|
|
7
|
+
readonly ctx: BijouContext;
|
|
8
|
+
/** Token path that changed. `'*'` means broad invalidation after import. */
|
|
9
|
+
readonly path: string;
|
|
10
|
+
/** True when the underlying graph requested a full recompute. */
|
|
11
|
+
readonly fullReload: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Disposable subscription returned by {@link observeTheme}. */
|
|
14
|
+
export interface ThemeObservation {
|
|
15
|
+
/** Stop observing future theme changes. */
|
|
16
|
+
dispose(): void;
|
|
17
|
+
}
|
|
4
18
|
/**
|
|
5
19
|
* Clone a Bijou context with a different already-resolved theme.
|
|
6
20
|
*
|
|
@@ -12,4 +26,15 @@ export declare function cloneContextWithResolvedTheme(ctx: BijouContext, theme:
|
|
|
12
26
|
* Clone a Bijou context with a different theme definition.
|
|
13
27
|
*/
|
|
14
28
|
export declare function cloneContextWithTheme(ctx: BijouContext, theme: Theme): BijouContext;
|
|
29
|
+
/**
|
|
30
|
+
* Observe theme/token updates for a context.
|
|
31
|
+
*
|
|
32
|
+
* This is the supported third-party authoring seam for reacting to in-place
|
|
33
|
+
* token-graph updates. Handlers should invalidate any cached theme-derived
|
|
34
|
+
* work and re-read tokens through the accessor layer on the provided context.
|
|
35
|
+
*
|
|
36
|
+
* When a caller replaces the entire context object, dispose the old
|
|
37
|
+
* observation and subscribe to the new context instead.
|
|
38
|
+
*/
|
|
39
|
+
export declare function observeTheme(ctx: BijouContext, handler: (change: ThemeChange) => void): ThemeObservation;
|
|
15
40
|
//# sourceMappingURL=context-theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-theme.d.ts","sourceRoot":"","sources":["../src/context-theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,aAAa,GACnB,YAAY,CAOd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,KAAK,GACX,YAAY,CAKd"}
|
|
1
|
+
{"version":3,"file":"context-theme.d.ts","sourceRoot":"","sources":["../src/context-theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAEpD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,gEAAgE;AAChE,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,aAAa,GACnB,YAAY,CAOd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,KAAK,GACX,YAAY,CAKd;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACrC,gBAAgB,CAQlB"}
|
package/dist/context-theme.js
CHANGED
|
@@ -20,4 +20,23 @@ export function cloneContextWithResolvedTheme(ctx, theme) {
|
|
|
20
20
|
export function cloneContextWithTheme(ctx, theme) {
|
|
21
21
|
return cloneContextWithResolvedTheme(ctx, createResolved(theme, ctx.theme.noColor, ctx.theme.colorScheme));
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Observe theme/token updates for a context.
|
|
25
|
+
*
|
|
26
|
+
* This is the supported third-party authoring seam for reacting to in-place
|
|
27
|
+
* token-graph updates. Handlers should invalidate any cached theme-derived
|
|
28
|
+
* work and re-read tokens through the accessor layer on the provided context.
|
|
29
|
+
*
|
|
30
|
+
* When a caller replaces the entire context object, dispose the old
|
|
31
|
+
* observation and subscribe to the new context instead.
|
|
32
|
+
*/
|
|
33
|
+
export function observeTheme(ctx, handler) {
|
|
34
|
+
return ctx.tokenGraph.on((path) => {
|
|
35
|
+
handler({
|
|
36
|
+
ctx,
|
|
37
|
+
path,
|
|
38
|
+
fullReload: path === '*',
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
23
42
|
//# sourceMappingURL=context-theme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-theme.js","sourceRoot":"","sources":["../src/context-theme.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAsB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"context-theme.js","sourceRoot":"","sources":["../src/context-theme.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAsB,MAAM,yBAAyB,CAAC;AAmB7E;;;;;GAKG;AACH,MAAM,UAAU,6BAA6B,CAC3C,GAAiB,EACjB,KAAoB;IAEpB,OAAO;QACL,GAAG,GAAG;QACN,KAAK;QACL,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,GAAG,oBAAoB,CAAC,KAAK,CAAC;KAC/B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAiB,EACjB,KAAY;IAEZ,OAAO,6BAA6B,CAClC,GAAG,EACH,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAChE,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAiB,EACjB,OAAsC;IAEtC,OAAO,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,OAAO,CAAC;YACN,GAAG;YACH,IAAI;YACJ,UAAU,EAAE,IAAI,KAAK,GAAG;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/context.d.ts
CHANGED
|
@@ -18,7 +18,19 @@ export declare function getDefaultContext(): BijouContext;
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function setDefaultContext(ctx: BijouContext): void;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Register a lazy initializer for the global default {@link BijouContext}.
|
|
22
|
+
*
|
|
23
|
+
* Host adapters can use this to provide ambient context bootstrapping without
|
|
24
|
+
* forcing higher-level runtime packages to depend on host-specific modules.
|
|
25
|
+
*
|
|
26
|
+
* The initializer is invoked only when {@link getDefaultContext} is called and
|
|
27
|
+
* no explicit default has been set yet.
|
|
28
|
+
*
|
|
29
|
+
* @param initializer - Lazy factory for the default context, or `null` to clear it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function setDefaultContextInitializer(initializer: (() => BijouContext) | null): void;
|
|
32
|
+
/**
|
|
33
|
+
* Reset the default context and lazy initializer.
|
|
22
34
|
*
|
|
23
35
|
* **Test-only** — ensures isolation between test cases.
|
|
24
36
|
*/
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,YAAY,CAchD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,CAAC,MAAM,YAAY,CAAC,GAAG,IAAI,GACvC,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD"}
|
package/dist/context.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
let defaultContext = null;
|
|
2
|
+
let defaultContextInitializer = null;
|
|
2
3
|
/**
|
|
3
4
|
* Retrieve the global default {@link BijouContext}.
|
|
4
5
|
*
|
|
@@ -8,9 +9,14 @@ let defaultContext = null;
|
|
|
8
9
|
*/
|
|
9
10
|
export function getDefaultContext() {
|
|
10
11
|
if (defaultContext === null) {
|
|
12
|
+
if (defaultContextInitializer != null) {
|
|
13
|
+
defaultContext = defaultContextInitializer();
|
|
14
|
+
return defaultContext;
|
|
15
|
+
}
|
|
11
16
|
throw new Error('[bijou] No default context configured. ' +
|
|
12
|
-
'Import @flyingrobots/bijou-node to auto-
|
|
13
|
-
'or call setDefaultContext() explicitly.'
|
|
17
|
+
'Import @flyingrobots/bijou-node to register Node auto-init, ' +
|
|
18
|
+
'call startApp(app), or call setDefaultContext() explicitly. ' +
|
|
19
|
+
'Guide: https://github.com/flyingrobots/bijou/tree/main/packages/bijou-node/GUIDE.md#basic-setup');
|
|
14
20
|
}
|
|
15
21
|
return defaultContext;
|
|
16
22
|
}
|
|
@@ -27,11 +33,26 @@ export function setDefaultContext(ctx) {
|
|
|
27
33
|
defaultContext = ctx;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
|
-
*
|
|
36
|
+
* Register a lazy initializer for the global default {@link BijouContext}.
|
|
37
|
+
*
|
|
38
|
+
* Host adapters can use this to provide ambient context bootstrapping without
|
|
39
|
+
* forcing higher-level runtime packages to depend on host-specific modules.
|
|
40
|
+
*
|
|
41
|
+
* The initializer is invoked only when {@link getDefaultContext} is called and
|
|
42
|
+
* no explicit default has been set yet.
|
|
43
|
+
*
|
|
44
|
+
* @param initializer - Lazy factory for the default context, or `null` to clear it.
|
|
45
|
+
*/
|
|
46
|
+
export function setDefaultContextInitializer(initializer) {
|
|
47
|
+
defaultContextInitializer = initializer;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Reset the default context and lazy initializer.
|
|
31
51
|
*
|
|
32
52
|
* **Test-only** — ensures isolation between test cases.
|
|
33
53
|
*/
|
|
34
54
|
export function _resetDefaultContextForTesting() {
|
|
35
55
|
defaultContext = null;
|
|
56
|
+
defaultContextInitializer = null;
|
|
36
57
|
}
|
|
37
58
|
//# sourceMappingURL=context.js.map
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,IAAI,cAAc,GAAwB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,IAAI,cAAc,GAAwB,IAAI,CAAC;AAC/C,IAAI,yBAAyB,GAAgC,IAAI,CAAC;AAElE;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,IAAI,yBAAyB,IAAI,IAAI,EAAE,CAAC;YACtC,cAAc,GAAG,yBAAyB,EAAE,CAAC;YAC7C,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,MAAM,IAAI,KAAK,CACb,yCAAyC;YACzC,8DAA8D;YAC9D,8DAA8D;YAC9D,iGAAiG,CAClG,CAAC;IACJ,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAiB;IACjD,cAAc,GAAG,GAAG,CAAC;AACvB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC1C,WAAwC;IAExC,yBAAyB,GAAG,WAAW,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B;IAC5C,cAAc,GAAG,IAAI,CAAC;IACtB,yBAAyB,GAAG,IAAI,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type DataRequirement, type ProviderId, type ViewDataContract } from './binding.js';
|
|
2
|
+
import { type BindingLifecycleOwner, type BindingLifecycleRecord } from './binding-lifecycle.js';
|
|
3
|
+
declare const ACTIVE_BINDING_ENTRY_BRAND: unique symbol;
|
|
4
|
+
declare const ACTIVE_BINDING_COLLECTION_BRAND: unique symbol;
|
|
5
|
+
export interface ActiveBindingEntryInput {
|
|
6
|
+
readonly owner: BindingLifecycleOwner;
|
|
7
|
+
readonly requirement: DataRequirement;
|
|
8
|
+
readonly providerId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ActiveBindingEntry {
|
|
11
|
+
readonly [ACTIVE_BINDING_ENTRY_BRAND]: true;
|
|
12
|
+
readonly owner: BindingLifecycleOwner;
|
|
13
|
+
readonly requirement: DataRequirement;
|
|
14
|
+
readonly providerId?: ProviderId;
|
|
15
|
+
}
|
|
16
|
+
export interface ActiveBindingProviderAssignment {
|
|
17
|
+
readonly requirementId: string;
|
|
18
|
+
readonly providerId: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ActiveBindingContractInput {
|
|
21
|
+
readonly owner: BindingLifecycleOwner;
|
|
22
|
+
readonly contract: ViewDataContract;
|
|
23
|
+
readonly providerIds?: readonly ActiveBindingProviderAssignment[];
|
|
24
|
+
}
|
|
25
|
+
export interface CollectActiveBindingsInput {
|
|
26
|
+
readonly entries?: readonly ActiveBindingEntry[];
|
|
27
|
+
readonly contracts?: readonly ActiveBindingContractInput[];
|
|
28
|
+
}
|
|
29
|
+
export declare class ActiveBindingCollection {
|
|
30
|
+
#private;
|
|
31
|
+
readonly [ACTIVE_BINDING_COLLECTION_BRAND]: true;
|
|
32
|
+
constructor(entries: readonly ActiveBindingEntry[]);
|
|
33
|
+
entries(): readonly ActiveBindingEntry[];
|
|
34
|
+
requirements(): readonly DataRequirement[];
|
|
35
|
+
owners(): readonly BindingLifecycleOwner[];
|
|
36
|
+
lifecycleRecords(): readonly BindingLifecycleRecord[];
|
|
37
|
+
get(ownerId: string, requirementId: string): ActiveBindingEntry | undefined;
|
|
38
|
+
has(ownerId: string, requirementId: string): boolean;
|
|
39
|
+
byOwner(ownerId: string): readonly ActiveBindingEntry[];
|
|
40
|
+
byRequirement(requirementId: string): readonly ActiveBindingEntry[];
|
|
41
|
+
with(entry: ActiveBindingEntry): ActiveBindingCollection;
|
|
42
|
+
}
|
|
43
|
+
export declare function activeBindingEntry(input: ActiveBindingEntryInput): ActiveBindingEntry;
|
|
44
|
+
export declare function isActiveBindingEntry(value: unknown): value is ActiveBindingEntry;
|
|
45
|
+
export declare function activeBindingCollection(entries: readonly ActiveBindingEntry[]): ActiveBindingCollection;
|
|
46
|
+
export declare function isActiveBindingCollection(value: unknown): value is ActiveBindingCollection;
|
|
47
|
+
export declare function collectActiveBindings(input: CollectActiveBindingsInput): ActiveBindingCollection;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=active-binding-collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active-binding-collection.d.ts","sourceRoot":"","sources":["../../src/core/active-binding-collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,UAAU,EAEf,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,wBAAwB,CAAC;AAEhC,QAAA,MAAM,0BAA0B,EAAE,OAAO,MAAqC,CAAC;AAC/E,QAAA,MAAM,+BAA+B,EAAE,OAAO,MAA0C,CAAC;AAEzF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,CAAC,0BAA0B,CAAC,EAAE,IAAI,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,+BAA+B,EAAE,CAAC;CACnE;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAC5D;AAED,qBAAa,uBAAuB;;IAClC,QAAQ,CAAC,CAAC,+BAA+B,CAAC,EAAG,IAAI,CAAC;gBAItC,OAAO,EAAE,SAAS,kBAAkB,EAAE;IA6ClD,OAAO,IAAI,SAAS,kBAAkB,EAAE;IAIxC,YAAY,IAAI,SAAS,eAAe,EAAE;IAW1C,MAAM,IAAI,SAAS,qBAAqB,EAAE;IAW1C,gBAAgB,IAAI,SAAS,sBAAsB,EAAE;IAWrD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAe3E,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO;IAIpD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;IAYvD,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,kBAAkB,EAAE;IAYnE,IAAI,CAAC,KAAK,EAAE,kBAAkB,GAAG,uBAAuB;CAGzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,kBAAkB,CAwBrF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAOhF;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,uBAAuB,CAEzB;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,uBAAuB,CAO1F;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,0BAA0B,GAChC,uBAAuB,CAiBzB"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { isDataRequirement, isViewDataContract, } from './binding.js';
|
|
2
|
+
import { bindingLifecycleRecord, isBindingLifecycleOwner, } from './binding-lifecycle.js';
|
|
3
|
+
const ACTIVE_BINDING_ENTRY_BRAND = Symbol('ActiveBindingEntry');
|
|
4
|
+
const ACTIVE_BINDING_COLLECTION_BRAND = Symbol('ActiveBindingCollection');
|
|
5
|
+
export class ActiveBindingCollection {
|
|
6
|
+
[ACTIVE_BINDING_COLLECTION_BRAND];
|
|
7
|
+
#entries;
|
|
8
|
+
#entriesByKey;
|
|
9
|
+
constructor(entries) {
|
|
10
|
+
if (!Array.isArray(entries)) {
|
|
11
|
+
throw new Error('active binding collection: entries must be an array');
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(this, ACTIVE_BINDING_COLLECTION_BRAND, { value: true });
|
|
14
|
+
const entriesByKey = new Map();
|
|
15
|
+
const entryIndexesByKey = new Map();
|
|
16
|
+
const normalizedEntries = [];
|
|
17
|
+
entries.forEach((entry, index) => {
|
|
18
|
+
if (!isActiveBindingEntry(entry)) {
|
|
19
|
+
throw new Error(`active binding collection: entry at index ${index} was not created by activeBindingEntry()`);
|
|
20
|
+
}
|
|
21
|
+
const key = activeBindingKey(entry.owner.id, entry.requirement.id);
|
|
22
|
+
const existingEntry = entriesByKey.get(key);
|
|
23
|
+
if (existingEntry !== undefined) {
|
|
24
|
+
const mergedEntry = mergeDuplicateEntry(existingEntry, entry);
|
|
25
|
+
const existingIndex = entryIndexesByKey.get(key);
|
|
26
|
+
if (existingIndex === undefined) {
|
|
27
|
+
throw new Error(`active binding collection: missing index for owner ${entry.owner.id} `
|
|
28
|
+
+ `requirement ${entry.requirement.id}`);
|
|
29
|
+
}
|
|
30
|
+
entriesByKey.set(key, mergedEntry);
|
|
31
|
+
normalizedEntries[existingIndex] = mergedEntry;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
entriesByKey.set(key, entry);
|
|
35
|
+
entryIndexesByKey.set(key, normalizedEntries.length);
|
|
36
|
+
normalizedEntries.push(entry);
|
|
37
|
+
});
|
|
38
|
+
this.#entries = Object.freeze(normalizedEntries);
|
|
39
|
+
this.#entriesByKey = entriesByKey;
|
|
40
|
+
Object.freeze(this);
|
|
41
|
+
}
|
|
42
|
+
entries() {
|
|
43
|
+
return Object.freeze([...this.#entries]);
|
|
44
|
+
}
|
|
45
|
+
requirements() {
|
|
46
|
+
const requirementsById = new Map();
|
|
47
|
+
this.#entries.forEach((entry) => {
|
|
48
|
+
if (!requirementsById.has(entry.requirement.id)) {
|
|
49
|
+
requirementsById.set(entry.requirement.id, entry.requirement);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return Object.freeze([...requirementsById.values()]);
|
|
53
|
+
}
|
|
54
|
+
owners() {
|
|
55
|
+
const ownersById = new Map();
|
|
56
|
+
this.#entries.forEach((entry) => {
|
|
57
|
+
if (!ownersById.has(entry.owner.id)) {
|
|
58
|
+
ownersById.set(entry.owner.id, entry.owner);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return Object.freeze([...ownersById.values()]);
|
|
62
|
+
}
|
|
63
|
+
lifecycleRecords() {
|
|
64
|
+
return Object.freeze(this.#entries.map((entry) => bindingLifecycleRecord({
|
|
65
|
+
owner: entry.owner,
|
|
66
|
+
requirementId: entry.requirement.id,
|
|
67
|
+
providerId: entry.providerId,
|
|
68
|
+
facts: entry.requirement.facts,
|
|
69
|
+
})));
|
|
70
|
+
}
|
|
71
|
+
get(ownerId, requirementId) {
|
|
72
|
+
return this.#entriesByKey.get(activeBindingKey(normalizeRequiredText({
|
|
73
|
+
scope: 'active binding collection',
|
|
74
|
+
field: 'ownerId',
|
|
75
|
+
value: ownerId,
|
|
76
|
+
}), normalizeRequiredText({
|
|
77
|
+
scope: 'active binding collection',
|
|
78
|
+
field: 'requirementId',
|
|
79
|
+
value: requirementId,
|
|
80
|
+
})));
|
|
81
|
+
}
|
|
82
|
+
has(ownerId, requirementId) {
|
|
83
|
+
return this.get(ownerId, requirementId) !== undefined;
|
|
84
|
+
}
|
|
85
|
+
byOwner(ownerId) {
|
|
86
|
+
const normalizedOwnerId = normalizeRequiredText({
|
|
87
|
+
scope: 'active binding collection',
|
|
88
|
+
field: 'ownerId',
|
|
89
|
+
value: ownerId,
|
|
90
|
+
});
|
|
91
|
+
return Object.freeze(this.#entries.filter((entry) => entry.owner.id === normalizedOwnerId));
|
|
92
|
+
}
|
|
93
|
+
byRequirement(requirementId) {
|
|
94
|
+
const normalizedRequirementId = normalizeRequiredText({
|
|
95
|
+
scope: 'active binding collection',
|
|
96
|
+
field: 'requirementId',
|
|
97
|
+
value: requirementId,
|
|
98
|
+
});
|
|
99
|
+
return Object.freeze(this.#entries.filter((entry) => entry.requirement.id === normalizedRequirementId));
|
|
100
|
+
}
|
|
101
|
+
with(entry) {
|
|
102
|
+
return new ActiveBindingCollection([...this.#entries, entry]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function activeBindingEntry(input) {
|
|
106
|
+
if (!isBindingLifecycleOwner(input.owner)) {
|
|
107
|
+
throw new Error('active binding entry: owner was not created by defineBindingLifecycleOwner()');
|
|
108
|
+
}
|
|
109
|
+
if (!isDataRequirement(input.requirement)) {
|
|
110
|
+
throw new Error('active binding entry: requirement was not created by defineDataRequirement()');
|
|
111
|
+
}
|
|
112
|
+
const entry = {
|
|
113
|
+
owner: input.owner,
|
|
114
|
+
requirement: input.requirement,
|
|
115
|
+
providerId: optionalRequiredText({
|
|
116
|
+
scope: 'active binding entry',
|
|
117
|
+
field: 'providerId',
|
|
118
|
+
value: input.providerId,
|
|
119
|
+
}),
|
|
120
|
+
};
|
|
121
|
+
Object.defineProperty(entry, ACTIVE_BINDING_ENTRY_BRAND, { value: true });
|
|
122
|
+
return Object.freeze(entry);
|
|
123
|
+
}
|
|
124
|
+
export function isActiveBindingEntry(value) {
|
|
125
|
+
return Boolean(value
|
|
126
|
+
&& typeof value === 'object'
|
|
127
|
+
&& Object.prototype.hasOwnProperty.call(value, ACTIVE_BINDING_ENTRY_BRAND)
|
|
128
|
+
&& value[ACTIVE_BINDING_ENTRY_BRAND] === true);
|
|
129
|
+
}
|
|
130
|
+
export function activeBindingCollection(entries) {
|
|
131
|
+
return new ActiveBindingCollection(entries);
|
|
132
|
+
}
|
|
133
|
+
export function isActiveBindingCollection(value) {
|
|
134
|
+
return Boolean(value
|
|
135
|
+
&& typeof value === 'object'
|
|
136
|
+
&& Object.prototype.hasOwnProperty.call(value, ACTIVE_BINDING_COLLECTION_BRAND)
|
|
137
|
+
&& value[ACTIVE_BINDING_COLLECTION_BRAND] === true);
|
|
138
|
+
}
|
|
139
|
+
export function collectActiveBindings(input) {
|
|
140
|
+
if (input === undefined || input === null || typeof input !== 'object' || Array.isArray(input)) {
|
|
141
|
+
throw new Error('active binding collection: input must be an object');
|
|
142
|
+
}
|
|
143
|
+
if (input.entries !== undefined && !Array.isArray(input.entries)) {
|
|
144
|
+
throw new Error('active binding collection: entries must be an array');
|
|
145
|
+
}
|
|
146
|
+
if (input.contracts !== undefined && !Array.isArray(input.contracts)) {
|
|
147
|
+
throw new Error('active binding collection: contracts must be an array');
|
|
148
|
+
}
|
|
149
|
+
const entries = [...(input.entries ?? [])];
|
|
150
|
+
(input.contracts ?? []).forEach((source, index) => {
|
|
151
|
+
entries.push(...activeBindingEntriesFromContract(source, index));
|
|
152
|
+
});
|
|
153
|
+
return new ActiveBindingCollection(entries);
|
|
154
|
+
}
|
|
155
|
+
function activeBindingEntriesFromContract(source, index) {
|
|
156
|
+
if (!isObjectRecord(source)) {
|
|
157
|
+
throw new Error(`active binding collection: contract ${index} must be an object`);
|
|
158
|
+
}
|
|
159
|
+
if (!isBindingLifecycleOwner(source.owner)) {
|
|
160
|
+
throw new Error(`active binding collection: contract ${index} owner was not created by defineBindingLifecycleOwner()`);
|
|
161
|
+
}
|
|
162
|
+
if (!isViewDataContract(source.contract)) {
|
|
163
|
+
throw new Error(`active binding collection: contract ${index} was not created by defineViewData()`);
|
|
164
|
+
}
|
|
165
|
+
const providerIds = providerAssignmentsByRequirementId(source.providerIds);
|
|
166
|
+
const requirementIds = new Set(source.contract.requirementIds());
|
|
167
|
+
providerIds.forEach((_, requirementId) => {
|
|
168
|
+
if (!requirementIds.has(requirementId)) {
|
|
169
|
+
throw new Error(`active binding collection: provider assignment ${requirementId} `
|
|
170
|
+
+ `does not match contract ${index}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
const requirements = source.contract.requirements().map((requirement, requirementIndex) => {
|
|
174
|
+
if (!isDataRequirement(requirement)) {
|
|
175
|
+
throw new Error(`active binding collection: contract ${index} requirement ${requirementIndex} `
|
|
176
|
+
+ 'was not created by defineDataRequirement()');
|
|
177
|
+
}
|
|
178
|
+
return requirement;
|
|
179
|
+
});
|
|
180
|
+
return Object.freeze(requirements.map((requirement) => activeBindingEntry({
|
|
181
|
+
owner: source.owner,
|
|
182
|
+
requirement,
|
|
183
|
+
providerId: providerIds.get(requirement.id),
|
|
184
|
+
})));
|
|
185
|
+
}
|
|
186
|
+
function providerAssignmentsByRequirementId(assignments) {
|
|
187
|
+
if (assignments === undefined) {
|
|
188
|
+
return new Map();
|
|
189
|
+
}
|
|
190
|
+
if (!Array.isArray(assignments)) {
|
|
191
|
+
throw new Error('active binding collection: providerIds must be an array');
|
|
192
|
+
}
|
|
193
|
+
if (assignments.length === 0) {
|
|
194
|
+
return new Map();
|
|
195
|
+
}
|
|
196
|
+
const providerIds = new Map();
|
|
197
|
+
assignments.forEach((assignment, index) => {
|
|
198
|
+
if (!isObjectRecord(assignment)) {
|
|
199
|
+
throw new Error(`active binding collection: provider assignment ${index} must be an object`);
|
|
200
|
+
}
|
|
201
|
+
if (typeof assignment['requirementId'] !== 'string') {
|
|
202
|
+
throw new Error(`active binding collection: provider assignment ${index} `
|
|
203
|
+
+ 'requirementId must be a string');
|
|
204
|
+
}
|
|
205
|
+
if (typeof assignment['providerId'] !== 'string') {
|
|
206
|
+
throw new Error(`active binding collection: provider assignment ${index} providerId must be a string`);
|
|
207
|
+
}
|
|
208
|
+
const requirementId = normalizeRequiredText({
|
|
209
|
+
scope: 'active binding collection',
|
|
210
|
+
field: 'requirementId',
|
|
211
|
+
value: assignment['requirementId'],
|
|
212
|
+
});
|
|
213
|
+
if (providerIds.has(requirementId)) {
|
|
214
|
+
throw new Error(`active binding collection: duplicate provider assignment ${requirementId}`);
|
|
215
|
+
}
|
|
216
|
+
providerIds.set(requirementId, normalizeRequiredText({
|
|
217
|
+
scope: 'active binding collection',
|
|
218
|
+
field: 'providerId',
|
|
219
|
+
value: assignment['providerId'],
|
|
220
|
+
}));
|
|
221
|
+
});
|
|
222
|
+
return providerIds;
|
|
223
|
+
}
|
|
224
|
+
function activeBindingKey(ownerId, requirementId) {
|
|
225
|
+
return `${ownerId}\u0000${requirementId}`;
|
|
226
|
+
}
|
|
227
|
+
function isObjectRecord(value) {
|
|
228
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
229
|
+
}
|
|
230
|
+
function mergeDuplicateEntry(existingEntry, incomingEntry) {
|
|
231
|
+
if (existingEntry.providerId !== undefined
|
|
232
|
+
&& incomingEntry.providerId !== undefined
|
|
233
|
+
&& existingEntry.providerId !== incomingEntry.providerId) {
|
|
234
|
+
throw new Error(`active binding collection: conflicting providers for owner ${incomingEntry.owner.id} `
|
|
235
|
+
+ `requirement ${incomingEntry.requirement.id}`);
|
|
236
|
+
}
|
|
237
|
+
const providerId = existingEntry.providerId ?? incomingEntry.providerId;
|
|
238
|
+
if (providerId === existingEntry.providerId) {
|
|
239
|
+
return existingEntry;
|
|
240
|
+
}
|
|
241
|
+
return activeBindingEntry({
|
|
242
|
+
owner: existingEntry.owner,
|
|
243
|
+
requirement: existingEntry.requirement,
|
|
244
|
+
providerId,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function normalizeRequiredText(options) {
|
|
248
|
+
const normalized = options.value.trim();
|
|
249
|
+
if (normalized === '') {
|
|
250
|
+
throw new Error(`${options.scope}: ${options.field} is required`);
|
|
251
|
+
}
|
|
252
|
+
return normalized;
|
|
253
|
+
}
|
|
254
|
+
function optionalRequiredText(options) {
|
|
255
|
+
if (options.value === undefined) {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
return normalizeRequiredText({
|
|
259
|
+
scope: options.scope,
|
|
260
|
+
field: options.field,
|
|
261
|
+
value: options.value,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=active-binding-collection.js.map
|