@ankhorage/zora 21.1.3 → 22.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.
Files changed (109) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +4 -1
  3. package/dist/features/authoring/index.d.ts +0 -4
  4. package/dist/features/authoring/index.d.ts.map +1 -1
  5. package/dist/features/authoring/index.js +0 -3
  6. package/dist/features/authoring/index.js.map +1 -1
  7. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts +1 -1
  8. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts.map +1 -1
  9. package/dist/features/chess/adapters/inbound/ChessBoard.js +23 -7
  10. package/dist/features/chess/adapters/inbound/ChessBoard.js.map +1 -1
  11. package/dist/features/chess/meta.d.ts +68 -0
  12. package/dist/features/chess/meta.d.ts.map +1 -1
  13. package/dist/features/chess/meta.js +36 -1
  14. package/dist/features/chess/meta.js.map +1 -1
  15. package/dist/features/chess/public.d.ts +3 -1
  16. package/dist/features/chess/public.d.ts.map +1 -1
  17. package/dist/features/chess/public.js +2 -0
  18. package/dist/features/chess/public.js.map +1 -1
  19. package/dist/features/chess/utils/chessEngine.d.ts +8 -0
  20. package/dist/features/chess/utils/chessEngine.d.ts.map +1 -0
  21. package/dist/features/chess/utils/chessEngine.js +71 -0
  22. package/dist/features/chess/utils/chessEngine.js.map +1 -0
  23. package/dist/features/tabletop/meta.d.ts +32 -0
  24. package/dist/features/tabletop/meta.d.ts.map +1 -1
  25. package/dist/features/tabletop/meta.js +24 -0
  26. package/dist/features/tabletop/meta.js.map +1 -1
  27. package/dist/features/tabletop/public.d.ts +1 -0
  28. package/dist/features/tabletop/public.d.ts.map +1 -1
  29. package/dist/features/tabletop/public.js +1 -0
  30. package/dist/features/tabletop/public.js.map +1 -1
  31. package/dist/index.d.ts +4 -7
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -5
  34. package/dist/index.js.map +1 -1
  35. package/dist/types/chess.d.ts +10 -0
  36. package/dist/types/chess.d.ts.map +1 -1
  37. package/dist/types/chess.js.map +1 -1
  38. package/package.json +7 -6
  39. package/src/features/authoring/featureManifest.test.ts +46 -10
  40. package/src/features/authoring/index.ts +0 -8
  41. package/src/features/chess/adapters/inbound/ChessBoard.tsx +34 -11
  42. package/src/features/chess/meta.ts +36 -1
  43. package/src/features/chess/public.test.tsx +83 -0
  44. package/src/features/chess/public.ts +3 -0
  45. package/src/features/chess/utils/chessEngine.test.ts +35 -0
  46. package/src/features/chess/utils/chessEngine.ts +83 -0
  47. package/src/features/chessTabletopOwnership.test.ts +8 -4
  48. package/src/features/tabletop/meta.ts +24 -0
  49. package/src/features/tabletop/public.test.tsx +12 -0
  50. package/src/features/tabletop/public.ts +1 -0
  51. package/src/index.ts +7 -15
  52. package/src/structureOwnership.test.ts +2 -7
  53. package/src/types/chess.ts +11 -0
  54. package/web-dist/chunks/Accordion-784f23tq.js +3813 -0
  55. package/web-dist/components/card-back/CardBack.js +1 -1
  56. package/web-dist/components/card-hand/CardHand.js +1 -1
  57. package/web-dist/components/chess-board/ChessBoard.js +1 -1
  58. package/web-dist/components/opening-book/OpeningBook.js +1 -1
  59. package/web-dist/components/playing-card/PlayingCard.js +1 -1
  60. package/web-dist/components/poker-training-table/PokerTrainingTable.js +1 -1
  61. package/web-dist/components/tabletop-table/TabletopTable.js +1 -1
  62. package/web-dist/manifest.json +12 -24
  63. package/dist/features/plugin/ZORA_CORE_PLUGIN.d.ts +0 -4
  64. package/dist/features/plugin/ZORA_CORE_PLUGIN.d.ts.map +0 -1
  65. package/dist/features/plugin/ZORA_CORE_PLUGIN.js +0 -8
  66. package/dist/features/plugin/ZORA_CORE_PLUGIN.js.map +0 -1
  67. package/dist/features/plugin/ZORA_CORE_PLUGIN_METADATA.d.ts +0 -3
  68. package/dist/features/plugin/ZORA_CORE_PLUGIN_METADATA.d.ts.map +0 -1
  69. package/dist/features/plugin/ZORA_CORE_PLUGIN_METADATA.js +0 -36
  70. package/dist/features/plugin/ZORA_CORE_PLUGIN_METADATA.js.map +0 -1
  71. package/dist/features/plugin/application/use-cases/composeZoraPluginMetadata.d.ts +0 -4
  72. package/dist/features/plugin/application/use-cases/composeZoraPluginMetadata.d.ts.map +0 -1
  73. package/dist/features/plugin/application/use-cases/composeZoraPluginMetadata.js +0 -106
  74. package/dist/features/plugin/application/use-cases/composeZoraPluginMetadata.js.map +0 -1
  75. package/dist/features/plugin/application/use-cases/composeZoraPlugins.d.ts +0 -4
  76. package/dist/features/plugin/application/use-cases/composeZoraPlugins.d.ts.map +0 -1
  77. package/dist/features/plugin/application/use-cases/composeZoraPlugins.js +0 -41
  78. package/dist/features/plugin/application/use-cases/composeZoraPlugins.js.map +0 -1
  79. package/dist/features/plugin/domain/ZoraPluginCompositionError.d.ts +0 -14
  80. package/dist/features/plugin/domain/ZoraPluginCompositionError.d.ts.map +0 -1
  81. package/dist/features/plugin/domain/ZoraPluginCompositionError.js +0 -14
  82. package/dist/features/plugin/domain/ZoraPluginCompositionError.js.map +0 -1
  83. package/dist/features/plugin/public.d.ts +0 -4
  84. package/dist/features/plugin/public.d.ts.map +0 -1
  85. package/dist/features/plugin/public.js +0 -4
  86. package/dist/features/plugin/public.js.map +0 -1
  87. package/dist/features/plugin/runtime.d.ts +0 -3
  88. package/dist/features/plugin/runtime.d.ts.map +0 -1
  89. package/dist/features/plugin/runtime.js +0 -3
  90. package/dist/features/plugin/runtime.js.map +0 -1
  91. package/dist/types/plugin.d.ts +0 -29
  92. package/dist/types/plugin.d.ts.map +0 -1
  93. package/dist/types/plugin.js +0 -2
  94. package/dist/types/plugin.js.map +0 -1
  95. package/src/features/plugin/ZORA_CORE_PLUGIN.ts +0 -9
  96. package/src/features/plugin/ZORA_CORE_PLUGIN_METADATA.ts +0 -49
  97. package/src/features/plugin/application/use-cases/composeZoraPluginMetadata.ts +0 -166
  98. package/src/features/plugin/application/use-cases/composeZoraPlugins.ts +0 -76
  99. package/src/features/plugin/domain/ZoraPluginCompositionError.ts +0 -21
  100. package/src/features/plugin/pluginComposition.test.ts +0 -139
  101. package/src/features/plugin/public.ts +0 -3
  102. package/src/features/plugin/runtime.ts +0 -2
  103. package/src/types/plugin.ts +0 -43
  104. package/web-dist/chunks/Accordion-86z2tvvz.js +0 -321
  105. package/web-dist/components/zora-plugin-composition-error/ZoraPluginCompositionError.d.ts +0 -3
  106. package/web-dist/components/zora-plugin-composition-error/ZoraPluginCompositionError.js +0 -17
  107. package/web-dist/components/zora-plugin-composition-error/index.d.ts +0 -1
  108. package/web-dist/components/zora-plugin-composition-error/index.js +0 -2
  109. /package/web-dist/chunks/{Accordion-57mn1j9e.js → Accordion-z585n0mr.js} +0 -0
@@ -1,49 +0,0 @@
1
- import type { UiComponentMetaRegistry } from '@ankhorage/contracts';
2
-
3
- import type { ZoraComponentMetaRegistry } from '../../types/authoring';
4
- import type { ZoraPluginMetadata } from '../../types/plugin';
5
- import { ZORA_BINDABLE_COMPONENT_META } from '../authoring/bindableComponentMeta';
6
- import { ZORA_COMPONENT_META } from '../authoring/componentMeta';
7
-
8
- const CORE_EXTENSION_HOSTS = [
9
- 'Card',
10
- 'Grid',
11
- 'MessageBubble',
12
- 'PostCard',
13
- 'Screen',
14
- 'ScreenSection',
15
- 'View',
16
- ] as const;
17
-
18
- export const ZORA_CORE_PLUGIN_METADATA: ZoraPluginMetadata = {
19
- packageName: '@ankhorage/zora',
20
- displayName: 'ZORA',
21
- componentMeta: mergeBindableMeta(ZORA_COMPONENT_META, ZORA_BINDABLE_COMPONENT_META),
22
- extensionHosts: CORE_EXTENSION_HOSTS,
23
- };
24
-
25
- function mergeBindableMeta(
26
- componentMeta: ZoraComponentMetaRegistry,
27
- bindableMeta: UiComponentMetaRegistry,
28
- ): ZoraComponentMetaRegistry {
29
- const bindingsByComponent = new Map(
30
- Object.entries(bindableMeta).map(([componentName, meta]) => [componentName, meta.bindings]),
31
- );
32
- return Object.fromEntries(
33
- Object.entries(componentMeta).map(([componentName, meta]) => [
34
- componentName,
35
- bindingsByComponent.get(componentName)
36
- ? {
37
- ...meta,
38
- bindings: {
39
- props: { ...bindingsByComponent.get(componentName)?.props, ...meta.bindings?.props },
40
- events: {
41
- ...bindingsByComponent.get(componentName)?.events,
42
- ...meta.bindings?.events,
43
- },
44
- },
45
- }
46
- : meta,
47
- ]),
48
- );
49
- }
@@ -1,166 +0,0 @@
1
- import type { ZoraComponentMeta } from '../../../../types/authoring';
2
- import type {
3
- ComposedZoraPluginMetadataCatalog,
4
- ZoraPluginCompositionErrorCode,
5
- ZoraPluginMetadata,
6
- ZoraPluginPlacement,
7
- } from '../../../../types/plugin';
8
- import { ZoraPluginCompositionError } from '../../domain/ZoraPluginCompositionError';
9
-
10
- /*** Compose a selected ZORA metadata set for authoring tools that must not load React Native runtime modules. */
11
- export function composeZoraPluginMetadata(
12
- plugins: readonly ZoraPluginMetadata[],
13
- ): ComposedZoraPluginMetadataCatalog {
14
- const descriptors = sortPlugins(plugins);
15
- const packages = new Set<string>();
16
- const componentOwners = new Map<string, string>();
17
- const componentMeta = new Map<string, ZoraComponentMeta>();
18
- const extensionHosts = new Set<string>();
19
- const interactionPolicySupportedComponents = new Set<string>();
20
-
21
- for (const descriptor of descriptors) {
22
- validateUniquePackage(descriptor, packages);
23
- validateMetadata(descriptor);
24
- for (const [componentName, meta] of sortedEntries(descriptor.componentMeta)) {
25
- claimComponent(componentName, descriptor.packageName, componentOwners);
26
- componentMeta.set(componentName, meta);
27
- }
28
- for (const componentName of descriptor.extensionHosts ?? []) extensionHosts.add(componentName);
29
- for (const componentName of descriptor.interactionPolicySupportedComponents ?? []) {
30
- interactionPolicySupportedComponents.add(componentName);
31
- }
32
- }
33
-
34
- for (const descriptor of descriptors) {
35
- for (const placement of descriptor.placements ?? []) {
36
- applyPlacement({ descriptor, placement, componentMeta, extensionHosts });
37
- }
38
- }
39
-
40
- return {
41
- componentMeta: Object.fromEntries(componentMeta),
42
- bindableComponentMeta: Object.fromEntries(componentMeta),
43
- packageManifests: descriptors.map(({ packageName, displayName, componentMeta: meta }) => ({
44
- packageName,
45
- ...(displayName === undefined ? {} : { displayName }),
46
- components: meta,
47
- })),
48
- interactionPolicySupportedComponents: Object.fromEntries(
49
- [...interactionPolicySupportedComponents]
50
- .sort()
51
- .map((componentName) => [componentName, true]),
52
- ),
53
- };
54
- }
55
-
56
- function validateUniquePackage(descriptor: ZoraPluginMetadata, packages: Set<string>): void {
57
- if (packages.has(descriptor.packageName)) {
58
- throw compositionError(
59
- 'duplicate-package',
60
- descriptor.packageName,
61
- `Duplicate ZORA plugin package '${descriptor.packageName}'.`,
62
- );
63
- }
64
- packages.add(descriptor.packageName);
65
- }
66
-
67
- function validateMetadata(descriptor: ZoraPluginMetadata): void {
68
- for (const [componentName, meta] of sortedEntries(descriptor.componentMeta)) {
69
- if (meta.name !== componentName) {
70
- throw compositionError(
71
- 'invalid-component-meta',
72
- descriptor.packageName,
73
- `ZORA plugin '${descriptor.packageName}' metadata key '${componentName}' does not match meta.name '${meta.name}'.`,
74
- componentName,
75
- );
76
- }
77
- }
78
- }
79
-
80
- function claimComponent(
81
- componentName: string,
82
- packageName: string,
83
- owners: Map<string, string>,
84
- ): void {
85
- const existingOwner = owners.get(componentName);
86
- if (existingOwner) {
87
- throw compositionError(
88
- 'duplicate-component',
89
- packageName,
90
- `ZORA component '${componentName}' is owned by both '${existingOwner}' and '${packageName}'.`,
91
- componentName,
92
- );
93
- }
94
- owners.set(componentName, packageName);
95
- }
96
-
97
- function applyPlacement(args: {
98
- descriptor: ZoraPluginMetadata;
99
- placement: ZoraPluginPlacement;
100
- componentMeta: Map<string, ZoraComponentMeta>;
101
- extensionHosts: ReadonlySet<string>;
102
- }): void {
103
- const { descriptor, placement, componentMeta, extensionHosts } = args;
104
- const childMeta = descriptor.componentMeta[placement.child];
105
- if (!childMeta?.directManifestNode) {
106
- throw compositionError(
107
- 'invalid-placement-child',
108
- descriptor.packageName,
109
- `ZORA plugin '${descriptor.packageName}' placement child '${placement.child}' is not an owned direct manifest node.`,
110
- placement.child,
111
- );
112
- }
113
- for (const parentName of [...placement.parents].sort()) {
114
- const parentMeta = componentMeta.get(parentName);
115
- if (!parentMeta || !extensionHosts.has(parentName)) {
116
- throw compositionError(
117
- 'invalid-placement-parent',
118
- descriptor.packageName,
119
- `ZORA plugin '${descriptor.packageName}' placement parent '${parentName}' is not a declared extension host.`,
120
- placement.child,
121
- );
122
- }
123
- componentMeta.set(parentName, addAllowedChild(parentMeta, placement.child));
124
- }
125
- }
126
-
127
- function addAllowedChild(meta: ZoraComponentMeta, child: string): ZoraComponentMeta {
128
- const allowedChildren = appendUnique(meta.allowedChildren, child);
129
- const childrenSlot = meta.slots?.children;
130
- return {
131
- ...meta,
132
- allowedChildren,
133
- ...(childrenSlot
134
- ? {
135
- slots: {
136
- ...meta.slots,
137
- children: {
138
- ...childrenSlot,
139
- allowedChildren: appendUnique(childrenSlot.allowedChildren ?? [], child),
140
- },
141
- },
142
- }
143
- : {}),
144
- };
145
- }
146
-
147
- function appendUnique(values: readonly string[], value: string): readonly string[] {
148
- return values.includes(value) ? values : [...values, value];
149
- }
150
-
151
- function sortedEntries<T>(value: Readonly<Record<string, T>>): [string, T][] {
152
- return Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
153
- }
154
-
155
- function sortPlugins<T extends ZoraPluginMetadata>(plugins: readonly T[]): T[] {
156
- return [...plugins].sort((left, right) => left.packageName.localeCompare(right.packageName));
157
- }
158
-
159
- function compositionError(
160
- code: ZoraPluginCompositionErrorCode,
161
- packageName: string,
162
- message: string,
163
- componentName?: string,
164
- ): ZoraPluginCompositionError {
165
- return new ZoraPluginCompositionError({ code, packageName, message, componentName });
166
- }
@@ -1,76 +0,0 @@
1
- import type {
2
- ComposedZoraPluginCatalog,
3
- ZoraPluginCompositionErrorCode,
4
- ZoraPluginDescriptor,
5
- } from '../../../../types/plugin';
6
- import type { ZoraComponentRegistry } from '../../../../types/registry';
7
- import { ZoraPluginCompositionError } from '../../domain/ZoraPluginCompositionError';
8
- import { composeZoraPluginMetadata } from './composeZoraPluginMetadata';
9
-
10
- /*** Compose a selected ZORA core/plugin descriptor set into one validated authoring/runtime catalog. */
11
- export function composeZoraPlugins(
12
- plugins: readonly ZoraPluginDescriptor[],
13
- ): ComposedZoraPluginCatalog {
14
- const descriptors = [...plugins].sort((left, right) =>
15
- left.packageName.localeCompare(right.packageName),
16
- );
17
- const componentRegistry = new Map<string, ZoraComponentRegistry[string]>();
18
-
19
- for (const descriptor of descriptors) {
20
- validateRuntime(descriptor);
21
- for (const [componentName, component] of sortedEntries(descriptor.componentRegistry)) {
22
- componentRegistry.set(componentName, component);
23
- }
24
- }
25
- const metadataCatalog = composeZoraPluginMetadata(descriptors);
26
-
27
- return { ...metadataCatalog, componentRegistry: Object.fromEntries(componentRegistry) };
28
- }
29
-
30
- function validateRuntime(descriptor: ZoraPluginDescriptor): void {
31
- const componentMetaNames = new Set(Object.keys(descriptor.componentMeta));
32
- const runtimeComponentNames = new Set(Object.keys(descriptor.componentRegistry));
33
- for (const componentName of Object.keys(descriptor.componentRegistry).sort()) {
34
- if (!componentMetaNames.has(componentName)) {
35
- throw compositionError(
36
- 'missing-component-meta',
37
- descriptor.packageName,
38
- `ZORA plugin '${descriptor.packageName}' registers runtime component '${componentName}' without component metadata.`,
39
- componentName,
40
- );
41
- }
42
- }
43
- for (const [componentName, meta] of sortedEntries(descriptor.componentMeta)) {
44
- if (meta.directManifestNode && !runtimeComponentNames.has(componentName)) {
45
- throw compositionError(
46
- 'missing-runtime-component',
47
- descriptor.packageName,
48
- `ZORA plugin '${descriptor.packageName}' exposes direct manifest node '${componentName}' without a runtime component.`,
49
- componentName,
50
- );
51
- }
52
- }
53
- for (const componentName of descriptor.interactionPolicySupportedComponents ?? []) {
54
- if (!runtimeComponentNames.has(componentName)) {
55
- throw compositionError(
56
- 'invalid-interaction-policy-component',
57
- descriptor.packageName,
58
- `ZORA plugin '${descriptor.packageName}' declares interaction-policy support for unregistered component '${componentName}'.`,
59
- componentName,
60
- );
61
- }
62
- }
63
- }
64
-
65
- function sortedEntries<T>(value: Readonly<Record<string, T>>): [string, T][] {
66
- return Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
67
- }
68
-
69
- function compositionError(
70
- code: ZoraPluginCompositionErrorCode,
71
- packageName: string,
72
- message: string,
73
- componentName?: string,
74
- ): ZoraPluginCompositionError {
75
- return new ZoraPluginCompositionError({ code, packageName, message, componentName });
76
- }
@@ -1,21 +0,0 @@
1
- import type { ZoraPluginCompositionErrorCode } from '../../../types/plugin';
2
-
3
- /*** Report one deterministic plugin composition contract violation. */
4
- export class ZoraPluginCompositionError extends Error {
5
- readonly code: ZoraPluginCompositionErrorCode;
6
- readonly packageName: string;
7
- readonly componentName?: string;
8
-
9
- constructor(args: {
10
- readonly code: ZoraPluginCompositionErrorCode;
11
- readonly packageName: string;
12
- readonly message: string;
13
- readonly componentName?: string;
14
- }) {
15
- super(args.message);
16
- this.name = 'ZoraPluginCompositionError';
17
- this.code = args.code;
18
- this.packageName = args.packageName;
19
- this.componentName = args.componentName;
20
- }
21
- }
@@ -1,139 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import type { ZoraComponentMeta } from '../../types/authoring';
4
- import type { ZoraPluginDescriptor } from '../../types/plugin';
5
- import { composeZoraPlugins } from './application/use-cases/composeZoraPlugins';
6
- import { ZoraPluginCompositionError } from './domain/ZoraPluginCompositionError';
7
-
8
- const pluginLeafMeta: ZoraComponentMeta = {
9
- name: 'PluginLeaf',
10
- category: 'component',
11
- directManifestNode: true,
12
- allowedChildren: [],
13
- blueprint: { label: 'Plugin leaf' },
14
- bindings: {
15
- props: {
16
- value: { value: { type: 'string' } },
17
- },
18
- },
19
- props: {
20
- value: { type: 'string', category: 'Content', authoring: { authority: 'instance' } },
21
- },
22
- };
23
-
24
- const PluginLeaf = () => null;
25
-
26
- const Host = () => null;
27
-
28
- const core = {
29
- packageName: '@example/core',
30
- componentRegistry: { Host },
31
- componentMeta: {
32
- Host: {
33
- name: 'Host',
34
- category: 'layout',
35
- directManifestNode: true,
36
- allowedChildren: [],
37
- props: {},
38
- },
39
- },
40
- extensionHosts: ['Host'],
41
- } satisfies ZoraPluginDescriptor;
42
-
43
- const plugin = {
44
- packageName: '@example/zora-plugin',
45
- displayName: 'Example plugin',
46
- componentRegistry: { PluginLeaf },
47
- componentMeta: { PluginLeaf: pluginLeafMeta },
48
- placements: [{ child: 'PluginLeaf', parents: ['Host'] }],
49
- } satisfies ZoraPluginDescriptor;
50
-
51
- describe('composeZoraPlugins', () => {
52
- test('composes runtime, authoring, binding, package, and placement projections', () => {
53
- const catalog = composeZoraPlugins([core, plugin]);
54
-
55
- expect(catalog.componentRegistry.PluginLeaf).toBe(PluginLeaf);
56
- expect(catalog.componentMeta.PluginLeaf).toBe(pluginLeafMeta);
57
- expect(catalog.bindableComponentMeta.PluginLeaf?.bindings).toEqual(pluginLeafMeta.bindings);
58
- expect(catalog.componentMeta.Host.allowedChildren).toContain('PluginLeaf');
59
- expect(catalog.packageManifests.map((entry) => entry.packageName)).toEqual([
60
- '@example/core',
61
- '@example/zora-plugin',
62
- ]);
63
- });
64
-
65
- test('is deterministic regardless of plugin input order', () => {
66
- const Alpha = () => null;
67
- const alpha = createPlugin('@example/alpha', 'Alpha', Alpha);
68
- const beta = createPlugin('@example/beta', 'Beta', () => null);
69
-
70
- expect(Object.keys(composeZoraPlugins([core, beta, alpha]).componentMeta)).toEqual(
71
- Object.keys(composeZoraPlugins([alpha, core, beta]).componentMeta),
72
- );
73
- });
74
-
75
- test('rejects duplicate component ownership with a stable diagnostic code', () => {
76
- const duplicate = createPlugin('@example/duplicate', 'Host', () => null);
77
-
78
- expect(() => composeZoraPlugins([core, duplicate])).toThrow(ZoraPluginCompositionError);
79
- try {
80
- composeZoraPlugins([core, duplicate]);
81
- } catch (error) {
82
- expect(error).toMatchObject({
83
- code: 'duplicate-component',
84
- packageName: '@example/duplicate',
85
- componentName: 'Host',
86
- });
87
- }
88
- });
89
-
90
- test('rejects runtime and metadata mismatches', () => {
91
- const invalid = {
92
- ...plugin,
93
- packageName: '@example/invalid',
94
- componentMeta: {},
95
- } satisfies ZoraPluginDescriptor;
96
-
97
- expectCompositionError(invalid, 'missing-component-meta');
98
- });
99
-
100
- test('rejects placement into components that did not opt in as extension hosts', () => {
101
- const invalid = {
102
- ...plugin,
103
- packageName: '@example/invalid-placement',
104
- placements: [{ child: 'PluginLeaf', parents: ['PluginLeaf'] }],
105
- } satisfies ZoraPluginDescriptor;
106
-
107
- expectCompositionError(invalid, 'invalid-placement-parent');
108
- });
109
- });
110
-
111
- function createPlugin(
112
- packageName: string,
113
- componentName: string,
114
- component: ZoraPluginDescriptor['componentRegistry'][string],
115
- ): ZoraPluginDescriptor {
116
- return {
117
- packageName,
118
- componentRegistry: { [componentName]: component },
119
- componentMeta: {
120
- [componentName]: {
121
- ...pluginLeafMeta,
122
- name: componentName,
123
- },
124
- },
125
- };
126
- }
127
-
128
- function expectCompositionError(
129
- descriptor: ZoraPluginDescriptor,
130
- code: ZoraPluginCompositionError['code'],
131
- ): void {
132
- try {
133
- composeZoraPlugins([core, descriptor]);
134
- throw new Error('Expected plugin composition to fail.');
135
- } catch (error) {
136
- expect(error).toBeInstanceOf(ZoraPluginCompositionError);
137
- expect(error).toMatchObject({ code });
138
- }
139
- }
@@ -1,3 +0,0 @@
1
- export { composeZoraPluginMetadata } from './application/use-cases/composeZoraPluginMetadata';
2
- export { ZoraPluginCompositionError } from './domain/ZoraPluginCompositionError';
3
- export { ZORA_CORE_PLUGIN_METADATA } from './ZORA_CORE_PLUGIN_METADATA';
@@ -1,2 +0,0 @@
1
- export { composeZoraPlugins } from './application/use-cases/composeZoraPlugins';
2
- export { ZORA_CORE_PLUGIN } from './ZORA_CORE_PLUGIN';
@@ -1,43 +0,0 @@
1
- import type { UiComponentMetaRegistry, UiComponentPackageManifest } from '@ankhorage/contracts';
2
-
3
- import type { ZoraComponentMetaRegistry } from './authoring';
4
- import type { ZoraComponentRegistry } from './registry';
5
-
6
- export type ZoraPluginCompositionErrorCode =
7
- | 'duplicate-component'
8
- | 'duplicate-package'
9
- | 'invalid-component-meta'
10
- | 'invalid-interaction-policy-component'
11
- | 'invalid-placement-child'
12
- | 'invalid-placement-parent'
13
- | 'missing-component-meta'
14
- | 'missing-runtime-component';
15
-
16
- export interface ZoraPluginPlacement {
17
- readonly child: string;
18
- readonly parents: readonly string[];
19
- }
20
-
21
- export interface ZoraPluginMetadata {
22
- readonly packageName: string;
23
- readonly displayName?: string;
24
- readonly componentMeta: ZoraComponentMetaRegistry;
25
- readonly extensionHosts?: readonly string[];
26
- readonly placements?: readonly ZoraPluginPlacement[];
27
- readonly interactionPolicySupportedComponents?: readonly string[];
28
- }
29
-
30
- export interface ZoraPluginDescriptor extends ZoraPluginMetadata {
31
- readonly componentRegistry: ZoraComponentRegistry;
32
- }
33
-
34
- export interface ComposedZoraPluginMetadataCatalog {
35
- readonly componentMeta: ZoraComponentMetaRegistry;
36
- readonly bindableComponentMeta: UiComponentMetaRegistry;
37
- readonly packageManifests: readonly UiComponentPackageManifest[];
38
- readonly interactionPolicySupportedComponents: Readonly<Record<string, true>>;
39
- }
40
-
41
- export interface ComposedZoraPluginCatalog extends ComposedZoraPluginMetadataCatalog {
42
- readonly componentRegistry: ZoraComponentRegistry;
43
- }