@primafuture/contrib-kit-react 1.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 (128) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +294 -0
  3. package/dist/contribution-component.d.ts +82 -0
  4. package/dist/contribution-component.d.ts.map +1 -0
  5. package/dist/contribution-component.js +12 -0
  6. package/dist/contribution-component.js.map +1 -0
  7. package/dist/extension-outlet.d.ts +155 -0
  8. package/dist/extension-outlet.d.ts.map +1 -0
  9. package/dist/extension-outlet.js +229 -0
  10. package/dist/extension-outlet.js.map +1 -0
  11. package/dist/extension-registry-provider.d.ts +26 -0
  12. package/dist/extension-registry-provider.d.ts.map +1 -0
  13. package/dist/extension-registry-provider.js +82 -0
  14. package/dist/extension-registry-provider.js.map +1 -0
  15. package/dist/index.d.ts +22 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +14 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/internal/adapter-configuration.d.ts +54 -0
  20. package/dist/internal/adapter-configuration.d.ts.map +1 -0
  21. package/dist/internal/adapter-configuration.js +89 -0
  22. package/dist/internal/adapter-configuration.js.map +1 -0
  23. package/dist/internal/adapter-context.d.ts +24 -0
  24. package/dist/internal/adapter-context.d.ts.map +1 -0
  25. package/dist/internal/adapter-context.js +23 -0
  26. package/dist/internal/adapter-context.js.map +1 -0
  27. package/dist/internal/adapter-registry-bridge.d.ts +58 -0
  28. package/dist/internal/adapter-registry-bridge.d.ts.map +1 -0
  29. package/dist/internal/adapter-registry-bridge.js +494 -0
  30. package/dist/internal/adapter-registry-bridge.js.map +1 -0
  31. package/dist/internal/adapter-registry-protocol.d.ts +53 -0
  32. package/dist/internal/adapter-registry-protocol.d.ts.map +1 -0
  33. package/dist/internal/adapter-registry-protocol.js +182 -0
  34. package/dist/internal/adapter-registry-protocol.js.map +1 -0
  35. package/dist/internal/adapter-scope.d.ts +87 -0
  36. package/dist/internal/adapter-scope.d.ts.map +1 -0
  37. package/dist/internal/adapter-scope.js +346 -0
  38. package/dist/internal/adapter-scope.js.map +1 -0
  39. package/dist/internal/implementation-classifier.d.ts +21 -0
  40. package/dist/internal/implementation-classifier.d.ts.map +1 -0
  41. package/dist/internal/implementation-classifier.js +39 -0
  42. package/dist/internal/implementation-classifier.js.map +1 -0
  43. package/dist/internal/managed-lazy-generation.d.ts +100 -0
  44. package/dist/internal/managed-lazy-generation.d.ts.map +1 -0
  45. package/dist/internal/managed-lazy-generation.js +419 -0
  46. package/dist/internal/managed-lazy-generation.js.map +1 -0
  47. package/dist/internal/outlet-commit-lease.d.ts +46 -0
  48. package/dist/internal/outlet-commit-lease.d.ts.map +1 -0
  49. package/dist/internal/outlet-commit-lease.js +137 -0
  50. package/dist/internal/outlet-commit-lease.js.map +1 -0
  51. package/dist/internal/outlet-error-pipeline.d.ts +122 -0
  52. package/dist/internal/outlet-error-pipeline.d.ts.map +1 -0
  53. package/dist/internal/outlet-error-pipeline.js +214 -0
  54. package/dist/internal/outlet-error-pipeline.js.map +1 -0
  55. package/dist/internal/outlet-input.d.ts +42 -0
  56. package/dist/internal/outlet-input.d.ts.map +1 -0
  57. package/dist/internal/outlet-input.js +86 -0
  58. package/dist/internal/outlet-input.js.map +1 -0
  59. package/dist/internal/outlet-membership-boundary.d.ts +93 -0
  60. package/dist/internal/outlet-membership-boundary.d.ts.map +1 -0
  61. package/dist/internal/outlet-membership-boundary.js +710 -0
  62. package/dist/internal/outlet-membership-boundary.js.map +1 -0
  63. package/dist/internal/outlet-membership.d.ts +31 -0
  64. package/dist/internal/outlet-membership.d.ts.map +1 -0
  65. package/dist/internal/outlet-membership.js +65 -0
  66. package/dist/internal/outlet-membership.js.map +1 -0
  67. package/dist/internal/outlet-projection.d.ts +102 -0
  68. package/dist/internal/outlet-projection.d.ts.map +1 -0
  69. package/dist/internal/outlet-projection.js +228 -0
  70. package/dist/internal/outlet-projection.js.map +1 -0
  71. package/dist/internal/outlet-reporter-boundary.d.ts +42 -0
  72. package/dist/internal/outlet-reporter-boundary.d.ts.map +1 -0
  73. package/dist/internal/outlet-reporter-boundary.js +57 -0
  74. package/dist/internal/outlet-reporter-boundary.js.map +1 -0
  75. package/dist/internal/public-input-capture.d.ts +13 -0
  76. package/dist/internal/public-input-capture.d.ts.map +1 -0
  77. package/dist/internal/public-input-capture.js +34 -0
  78. package/dist/internal/public-input-capture.js.map +1 -0
  79. package/dist/internal/resolved-contributions-query.d.ts +42 -0
  80. package/dist/internal/resolved-contributions-query.d.ts.map +1 -0
  81. package/dist/internal/resolved-contributions-query.js +203 -0
  82. package/dist/internal/resolved-contributions-query.js.map +1 -0
  83. package/dist/react-adapter-diagnostics.d.ts +199 -0
  84. package/dist/react-adapter-diagnostics.d.ts.map +1 -0
  85. package/dist/react-adapter-diagnostics.js +257 -0
  86. package/dist/react-adapter-diagnostics.js.map +1 -0
  87. package/dist/react-adapter-error.d.ts +35 -0
  88. package/dist/react-adapter-error.d.ts.map +1 -0
  89. package/dist/react-adapter-error.js +37 -0
  90. package/dist/react-adapter-error.js.map +1 -0
  91. package/dist/react-extension-point.d.ts +26 -0
  92. package/dist/react-extension-point.d.ts.map +1 -0
  93. package/dist/react-extension-point.js +100 -0
  94. package/dist/react-extension-point.js.map +1 -0
  95. package/dist/react-lazy-contribution.d.ts +40 -0
  96. package/dist/react-lazy-contribution.d.ts.map +1 -0
  97. package/dist/react-lazy-contribution.js +18 -0
  98. package/dist/react-lazy-contribution.js.map +1 -0
  99. package/dist/resolved-contributions.d.ts +90 -0
  100. package/dist/resolved-contributions.d.ts.map +1 -0
  101. package/dist/resolved-contributions.js +455 -0
  102. package/dist/resolved-contributions.js.map +1 -0
  103. package/package.json +47 -0
  104. package/src/contribution-component.ts +118 -0
  105. package/src/extension-outlet.ts +590 -0
  106. package/src/extension-registry-provider.ts +179 -0
  107. package/src/index.ts +72 -0
  108. package/src/internal/adapter-configuration.ts +181 -0
  109. package/src/internal/adapter-context.ts +43 -0
  110. package/src/internal/adapter-registry-bridge.ts +723 -0
  111. package/src/internal/adapter-registry-protocol.ts +365 -0
  112. package/src/internal/adapter-scope.ts +500 -0
  113. package/src/internal/implementation-classifier.ts +59 -0
  114. package/src/internal/managed-lazy-generation.ts +540 -0
  115. package/src/internal/outlet-commit-lease.ts +216 -0
  116. package/src/internal/outlet-error-pipeline.ts +447 -0
  117. package/src/internal/outlet-input.ts +264 -0
  118. package/src/internal/outlet-membership-boundary.ts +1048 -0
  119. package/src/internal/outlet-membership.ts +125 -0
  120. package/src/internal/outlet-projection.ts +511 -0
  121. package/src/internal/outlet-reporter-boundary.ts +105 -0
  122. package/src/internal/public-input-capture.ts +55 -0
  123. package/src/internal/resolved-contributions-query.ts +318 -0
  124. package/src/react-adapter-diagnostics.ts +457 -0
  125. package/src/react-adapter-error.ts +88 -0
  126. package/src/react-extension-point.ts +181 -0
  127. package/src/react-lazy-contribution.ts +66 -0
  128. package/src/resolved-contributions.ts +895 -0
@@ -0,0 +1,895 @@
1
+ import * as contribKitCore from "@primafuture/contrib-kit-core";
2
+ import * as react from "react";
3
+
4
+ import * as adapterConfiguration from "./internal/adapter-configuration.js";
5
+ import * as adapterContext from "./internal/adapter-context.js";
6
+ import * as adapterRegistryBridge from "./internal/adapter-registry-bridge.js";
7
+ import * as adapterRegistryProtocol from "./internal/adapter-registry-protocol.js";
8
+ import * as adapterScope from "./internal/adapter-scope.js";
9
+ import * as outletCommitLease from "./internal/outlet-commit-lease.js";
10
+ import * as outletInput from "./internal/outlet-input.js";
11
+ import * as publicInputCapture from "./internal/public-input-capture.js";
12
+ import * as resolvedContributionsQuery from "./internal/resolved-contributions-query.js";
13
+ import * as reactAdapterDiagnostics from "./react-adapter-diagnostics.js";
14
+ import * as reactAdapterError from "./react-adapter-error.js";
15
+ import type * as reactExtensionPoint from "./react-extension-point.js";
16
+
17
+ /** Empty klasifikace úspěšného resolved view. @public */
18
+ export type ExtensionOutletEmptyReason = "noRegistrations" | "excludedByPolicy";
19
+
20
+ /**
21
+ * Frozen synchronní výsledek jednoho render-time Core query.
22
+ *
23
+ * @public
24
+ */
25
+ export type ResolvedContributionsState<
26
+ Point extends import("./react-extension-point.js").AnyReactExtensionPoint,
27
+ > =
28
+ | {
29
+ /** Rozlišuje úspěšný resolved view od failure. */
30
+ readonly status: "resolved";
31
+ /** Frozen normalized contributions v přesném Core pořadí. */
32
+ readonly contributions: readonly contribKitCore.RegisteredContribution<Point>[];
33
+ /** Důvod prázdného výsledku nebo null pro neprázdnou kolekci. */
34
+ readonly emptyReason: ExtensionOutletEmptyReason | null;
35
+ }
36
+ | {
37
+ /** Rozlišuje resolve failure od úspěšného empty view. */
38
+ readonly status: "failed";
39
+ /** Sdílená frozen prázdná tuple bez stale příspěvků. */
40
+ readonly contributions: readonly [];
41
+ /** Frozen bezpečný error event připravený pro UI i sink. */
42
+ readonly error: import("./react-adapter-diagnostics.js").ReactAdapterErrorEvent;
43
+ };
44
+
45
+ /**
46
+ * Read-once vstup synchronního resolved hooku.
47
+ *
48
+ * @public
49
+ */
50
+ export interface UseResolvedContributionsOptions<
51
+ Point extends import("./react-extension-point.js").AnyReactExtensionPoint,
52
+ > {
53
+ /** Point-specific context předaný Core resolution pipeline. */
54
+ readonly context: contribKitCore.ExtensionPointContext<Point>;
55
+ /** Exact canonical React extension point. */
56
+ readonly point: Point;
57
+ /** Lokální pure context projector; null zruší inherited projector. */
58
+ readonly projectContext?: (
59
+ (context: contribKitCore.ExtensionPointContext<Point>) => unknown
60
+ ) | null | undefined;
61
+ /** Explicitní registry s předností před nearest providerem. */
62
+ readonly registry?: contribKitCore.ExtensionRegistry | undefined;
63
+ /** Lokální diagnostic sink; null obnoví bezpečný package fallback. */
64
+ readonly sink?: import("./react-adapter-diagnostics.js").ReactAdapterSink | null | undefined;
65
+ }
66
+
67
+ /**
68
+ * Frozen návrat synchronního resolved hooku.
69
+ *
70
+ * @public
71
+ */
72
+ export interface UseResolvedContributionsResult<
73
+ Point extends import("./react-extension-point.js").AnyReactExtensionPoint,
74
+ > {
75
+ /** Aktuální frozen resolved nebo failed stav. */
76
+ readonly state: ResolvedContributionsState<Point>;
77
+ /** Stabilní lokální invalidace bez Core commitu. */
78
+ refresh(): void;
79
+ }
80
+
81
+ /** Úspěšný read-once hook capture bez committed resource. */
82
+ interface CapturedResolvedHook<Point extends reactExtensionPoint.AnyReactExtensionPoint> {
83
+ /** Rozlišuje validní capture od synchronní configuration chyby. */
84
+ readonly kind: "captured";
85
+ /** Exact point zachycený jako první známé options pole. */
86
+ readonly point: Point;
87
+ /** Exact context zachycený jako druhé známé options pole. */
88
+ readonly context: contribKitCore.ExtensionPointContext<Point>;
89
+ /** Fresh read-once protocol používaný render query. */
90
+ readonly protocol: adapterRegistryProtocol.AdapterRegistryProtocolSnapshot;
91
+ /** Scope provideru nebo consumer-local scope mimo provider. */
92
+ readonly scope: adapterScope.AdapterScopeRuntime;
93
+ /** Provider nebo standalone generation vlastnící committed bridge. */
94
+ readonly generation: adapterScope.AdapterScopeGeneration;
95
+ /** Efektivní hook-local diagnostická konfigurace. */
96
+ readonly configuration: adapterConfiguration.AdapterScopeConfiguration;
97
+ /** Zda committed lifecycle musí vlastnit consumer-local scope owner lease. */
98
+ readonly standalone: boolean;
99
+ }
100
+
101
+ /** Validní input, jehož registry již odmítá novou práci. */
102
+ interface UnavailableResolvedHook<Point extends reactExtensionPoint.AnyReactExtensionPoint> {
103
+ /** Rozlišuje business failure od configuration throw. */
104
+ readonly kind: "unavailable";
105
+ /** Exact point potřebný pro bezpečný failed event. */
106
+ readonly point: Point;
107
+ /** Exact context dostupný případnému pure projector callbacku. */
108
+ readonly context: contribKitCore.ExtensionPointContext<Point>;
109
+ /** Efektivní config i bez vzniku external-store bindingu. */
110
+ readonly configuration: adapterConfiguration.AdapterScopeConfiguration;
111
+ /** Scope-local diagnostic ledger. */
112
+ readonly scope: adapterScope.AdapterScopeRuntime;
113
+ /** Exact structural registry identity i po odmítnutí nové práce. */
114
+ readonly rawRegistry: object;
115
+ /** Provider generation, pokud unavailable query běží uvnitř provideru. */
116
+ readonly generation: adapterScope.AdapterScopeGeneration | undefined;
117
+ /** Přesná unavailable chyba z úplného protocol capture. */
118
+ readonly cause: reactAdapterError.ReactAdapterError;
119
+ }
120
+
121
+ /** Synchronní configuration failure držená do zavolání všech React hooks. */
122
+ interface FailedResolvedHookCapture {
123
+ /** Rozlišuje throw větev od public failed state. */
124
+ readonly kind: "configurationFailure";
125
+ /** Přesný accessor nebo shape cause. */
126
+ readonly cause: unknown;
127
+ }
128
+
129
+ /** Jeden úplný hook capture výsledek. */
130
+ type ResolvedHookCapture<Point extends reactExtensionPoint.AnyReactExtensionPoint> =
131
+ | CapturedResolvedHook<Point>
132
+ | UnavailableResolvedHook<Point>
133
+ | FailedResolvedHookCapture;
134
+
135
+ /** Jeden read-once capture doplněný o consumer-specific čistá data. */
136
+ interface ResolvedHookCaptureEnvelope<
137
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
138
+ Payload,
139
+ > {
140
+ /** Registry/query capture sdílený public hookem a outletem. */
141
+ readonly captured: ResolvedHookCapture<Point>;
142
+ /** Čistý vstup konkrétního consumeru bez resource identity. */
143
+ readonly payload: Payload;
144
+ }
145
+
146
+ /** Capture factory volaná uvnitř stabilního pořadí React hooks. */
147
+ type ResolvedHookCaptureFactory<
148
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
149
+ Payload,
150
+ > = (
151
+ parent: adapterContext.AdapterContextValue | undefined,
152
+ localScope: adapterScope.AdapterScopeRuntime,
153
+ checkpoint: () => void,
154
+ ) => ResolvedHookCaptureEnvelope<Point, Payload>;
155
+
156
+ /** Interní binding, který outletu zpřístupní přesně stejnou query a scope autoritu. */
157
+ export interface OutletResolvedContributionsBinding<
158
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
159
+ > {
160
+ /** Read-once outlet input použitý query i rendererem. */
161
+ readonly input: outletInput.CapturedOutletInput<Point>;
162
+ /** Public frozen resolved výsledek stejného render attemptu. */
163
+ readonly result: UseResolvedContributionsResult<Point>;
164
+ /** Opaque query attempt pro committed callback deduplikaci. */
165
+ readonly attempt: resolvedContributionsQuery.ResolvedQueryAttempt<Point>;
166
+ /** Scope-local owner bridge, diagnostik a commit leases. */
167
+ readonly scope: adapterScope.AdapterScopeRuntime;
168
+ /** Active generation nutná pro membership commit lease. */
169
+ readonly generation: adapterScope.AdapterScopeGeneration | undefined;
170
+ /** Exact raw registry reference tvořící první osu membership identity. */
171
+ readonly rawRegistry: object;
172
+ /** Ověří, že render attempt je právě committed a commandově current. */
173
+ readonly isCurrent: () => boolean;
174
+ /** Render-time authority checkpoint pro atomickou outlet projection. */
175
+ readonly checkpoint: () => void;
176
+ /** Commit-owned outlet identita, dostupná až po autoritativním mountu. */
177
+ readonly outletLease: outletCommitLease.OutletCommitLease | undefined;
178
+ /** True při serveru a prvním hydration renderu nad společným sentinel snapshotem. */
179
+ readonly serverSnapshot: boolean;
180
+ }
181
+
182
+ /** Stable external-store fallback pro configuration a unavailable větve. */
183
+ const EMPTY_EXTERNAL_STORE: adapterScope.AdapterExternalStoreBinding = Object.freeze({
184
+ /** Resource-free subscribe vracející idempotentní no-op. */
185
+ subscribe(): contribKitCore.Unsubscribe {
186
+ /** Resource-free unsubscribe fallback. */
187
+ function unsubscribe(): void {
188
+ // Bez validního registry protocolu nevznikla žádná resource.
189
+ }
190
+ return unsubscribe;
191
+ },
192
+ /** Konstantní client snapshot bez host reads. */
193
+ getSnapshot(): adapterRegistryProtocol.AdapterRegistrySnapshotToken {
194
+ return "disposed:0";
195
+ },
196
+ /** Konstantní server snapshot sdílený s normálním bridgem. */
197
+ getServerSnapshot(): "contrib-kit-react:server" {
198
+ return "contrib-kit-react:server";
199
+ },
200
+ /** Neexistující bridge nemůže mít committed fault. */
201
+ readFault(): undefined {
202
+ return undefined;
203
+ },
204
+ /** Fallback pouze splní interní structural interface. */
205
+ readRegistryState(): "disposed" {
206
+ return "disposed";
207
+ },
208
+ });
209
+
210
+ /** Poslední referenčně stabilní external-store binding jednoho hooku. */
211
+ interface ExternalStoreCache {
212
+ /** Scope identity owning bridge mapu. */
213
+ readonly scope: adapterScope.AdapterScopeRuntime;
214
+ /** Scope generation použitá při materializaci bindingu. */
215
+ readonly generation: adapterScope.AdapterScopeGeneration;
216
+ /** Raw registry reference; zachycené metody zůstávají v bindingu. */
217
+ readonly rawRegistry: object;
218
+ /** Registry ID chrání proti in-place identity změně structural fake. */
219
+ readonly registryId: string;
220
+ /** Exact canonical point reference. */
221
+ readonly point: contribKitCore.AnyExtensionPoint;
222
+ /** Pure nebo committed external-store closures. */
223
+ readonly binding: adapterScope.AdapterExternalStoreBinding;
224
+ }
225
+
226
+ /** Mutable control stabilní refresh closure bez stale render capture. */
227
+ interface ResolvedHookControl {
228
+ /** Určuje, zda uniklý refresh ještě smí naplánovat React update. */
229
+ mounted: boolean;
230
+ /** Poslední committed scope. */
231
+ scope?: adapterScope.AdapterScopeRuntime;
232
+ /** Poslední committed generation pro lifecycle gate. */
233
+ generation?: adapterScope.AdapterScopeGeneration;
234
+ /** Standalone unavailable větev nemá aktivovatelnou generation. */
235
+ allowWithoutGeneration: boolean;
236
+ }
237
+
238
+ /** Committed authority jednoho render attemptu a command epochy. */
239
+ interface CommittedResolvedAttempt {
240
+ /** Exact query attempt lokální právě committed renderu. */
241
+ readonly attempt: resolvedContributionsQuery.ResolvedQueryAttempt<reactExtensionPoint.AnyReactExtensionPoint>;
242
+ /** Command epoch platná při effect setupu. */
243
+ readonly commandEpoch: number;
244
+ /** Scope-local diagnostic ledger owning token. */
245
+ readonly scope: adapterScope.AdapterScopeRuntime;
246
+ /** Efektivní sink konfigurace daného attemptu. */
247
+ readonly configuration: adapterConfiguration.AdapterScopeConfiguration;
248
+ }
249
+
250
+ /** Vytvoří resource-free consumer-local scope jako lazy React state. */
251
+ function createConsumerScope(): adapterScope.AdapterScopeRuntime {
252
+ return new adapterScope.AdapterScopeRuntime();
253
+ }
254
+
255
+ /** Ověří, že point může bezpečně sloužit jako exact WeakMap capability key. */
256
+ function requirePointObject<Point extends reactExtensionPoint.AnyReactExtensionPoint>(
257
+ value: unknown,
258
+ ): Point {
259
+ if (typeof value !== "object" || value === null) {
260
+ throw new reactAdapterError.ReactAdapterError(
261
+ "REACT_INVALID_ARGUMENT",
262
+ "options.point must be a non-null object.",
263
+ { details: { field: "options.point", phase: "configuration" } },
264
+ );
265
+ }
266
+ return value as Point;
267
+ }
268
+
269
+ /** Rozpozná unavailable query failure, která patří do public failed state. */
270
+ function isUnavailableProtocolError(
271
+ cause: unknown,
272
+ ): cause is reactAdapterError.ReactAdapterError {
273
+ return cause instanceof reactAdapterError.ReactAdapterError
274
+ && cause.code === "REACT_REGISTRY_UNAVAILABLE"
275
+ && cause.details.phase === "resolve";
276
+ }
277
+
278
+ /**
279
+ * Zachytí structural registry protocol pro již read-once point/context/config vstup.
280
+ */
281
+ function captureResolvedRegistry<
282
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
283
+ >(
284
+ point: Point,
285
+ context: contribKitCore.ExtensionPointContext<Point>,
286
+ registry: unknown,
287
+ configuration: adapterConfiguration.AdapterScopeConfiguration,
288
+ parent: adapterContext.AdapterContextValue | undefined,
289
+ localScope: adapterScope.AdapterScopeRuntime,
290
+ checkpoint: () => void,
291
+ ): ResolvedHookCapture<Point> {
292
+ const scope = parent?.scope ?? localScope;
293
+ let protocol: adapterRegistryProtocol.AdapterRegistryProtocolSnapshot;
294
+ try {
295
+ protocol = adapterRegistryProtocol.captureAdapterRegistryProtocol(registry, checkpoint);
296
+ } catch (cause: unknown) {
297
+ if (isUnavailableProtocolError(cause)) {
298
+ return Object.freeze({
299
+ kind: "unavailable",
300
+ point,
301
+ context,
302
+ configuration,
303
+ scope,
304
+ rawRegistry: registry as object,
305
+ generation: parent?.generation,
306
+ cause,
307
+ });
308
+ }
309
+ throw cause;
310
+ }
311
+
312
+ const generation = parent?.generation
313
+ ?? adapterScope.createAdapterScopeGeneration(protocol, configuration);
314
+ return Object.freeze({
315
+ kind: "captured",
316
+ point,
317
+ context,
318
+ protocol,
319
+ scope,
320
+ generation,
321
+ configuration,
322
+ standalone: parent === undefined,
323
+ });
324
+ }
325
+
326
+ /** Zachytí hook options v přesném veřejném pořadí bez partial publication. */
327
+ function captureResolvedHook<Point extends reactExtensionPoint.AnyReactExtensionPoint>(
328
+ options: UseResolvedContributionsOptions<Point>,
329
+ parent: adapterContext.AdapterContextValue | undefined,
330
+ localScope: adapterScope.AdapterScopeRuntime,
331
+ checkpoint: () => void,
332
+ ): ResolvedHookCapture<Point> {
333
+ const source = publicInputCapture.requireInputObject(options, "options");
334
+ const pointValue = publicInputCapture.readInputProperty(
335
+ source,
336
+ "point",
337
+ "options.point",
338
+ checkpoint,
339
+ );
340
+ const context = publicInputCapture.readInputProperty(
341
+ source,
342
+ "context",
343
+ "options.context",
344
+ checkpoint,
345
+ ) as contribKitCore.ExtensionPointContext<Point>;
346
+ const registryValue = publicInputCapture.readInputProperty(
347
+ source,
348
+ "registry",
349
+ "options.registry",
350
+ checkpoint,
351
+ );
352
+ const sinkValue = publicInputCapture.readInputProperty(
353
+ source,
354
+ "sink",
355
+ "options.sink",
356
+ checkpoint,
357
+ );
358
+ const projectContextValue = publicInputCapture.readInputProperty(
359
+ source,
360
+ "projectContext",
361
+ "options.projectContext",
362
+ checkpoint,
363
+ );
364
+ const point = requirePointObject<Point>(pointValue);
365
+ const patch = adapterConfiguration.captureAdapterConfigurationPatch(
366
+ sinkValue,
367
+ undefined,
368
+ projectContextValue,
369
+ checkpoint,
370
+ );
371
+ const configuration = adapterConfiguration.resolveAdapterScopeConfiguration(
372
+ parent?.generation.configuration,
373
+ patch,
374
+ );
375
+ const registry = adapterConfiguration.resolveAdapterRegistryInput(
376
+ registryValue,
377
+ parent?.generation.defaultProtocol.rawRegistry,
378
+ );
379
+ return captureResolvedRegistry(
380
+ point,
381
+ context,
382
+ registry,
383
+ configuration,
384
+ parent,
385
+ localScope,
386
+ checkpoint,
387
+ );
388
+ }
389
+
390
+ /** Zachytí outlet props jednou a připraví query nad stejným config/scope vstupem. */
391
+ function captureOutletResolvedHook<
392
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
393
+ >(
394
+ props: object,
395
+ parent: adapterContext.AdapterContextValue | undefined,
396
+ localScope: adapterScope.AdapterScopeRuntime,
397
+ checkpoint: () => void,
398
+ ): ResolvedHookCaptureEnvelope<Point, outletInput.CapturedOutletInput<Point>> {
399
+ const input = outletInput.captureOutletInput<Point>(
400
+ props,
401
+ parent?.generation.defaultProtocol.rawRegistry,
402
+ parent?.generation.configuration,
403
+ checkpoint,
404
+ );
405
+ const captured = captureResolvedRegistry(
406
+ input.point,
407
+ input.context,
408
+ input.registry,
409
+ input.configuration,
410
+ parent,
411
+ localScope,
412
+ checkpoint,
413
+ );
414
+ return Object.freeze({ captured, payload: input });
415
+ }
416
+
417
+ /** Vrátí stabilní binding a zachová první committed method capture bridge. */
418
+ function resolveExternalStoreBinding(
419
+ captured: CapturedResolvedHook<reactExtensionPoint.AnyReactExtensionPoint>,
420
+ cacheRef: react.MutableRefObject<ExternalStoreCache | undefined>,
421
+ ): adapterScope.AdapterExternalStoreBinding {
422
+ const cached = cacheRef.current;
423
+ if (cached !== undefined
424
+ && cached.scope === captured.scope
425
+ && cached.rawRegistry === captured.protocol.rawRegistry
426
+ && cached.registryId === captured.protocol.registryId
427
+ && cached.point === captured.point
428
+ && adapterScope.isSameAdapterScopeGeneration(cached.generation, captured.generation)) {
429
+ return cached.binding;
430
+ }
431
+
432
+ const binding = captured.scope.createExternalStore(
433
+ captured.generation,
434
+ captured.protocol,
435
+ captured.point,
436
+ );
437
+ cacheRef.current = Object.freeze({
438
+ scope: captured.scope,
439
+ generation: captured.generation,
440
+ rawRegistry: captured.protocol.rawRegistry,
441
+ registryId: captured.protocol.registryId,
442
+ point: captured.point,
443
+ binding,
444
+ });
445
+ return binding;
446
+ }
447
+
448
+ /** Ověří committed autoritu po každém sink callbacku. */
449
+ function isCommittedAttemptCurrent(
450
+ authority: CommittedResolvedAttempt,
451
+ committedRef: react.MutableRefObject<CommittedResolvedAttempt | undefined>,
452
+ commandEpochRef: react.MutableRefObject<number>,
453
+ ): boolean {
454
+ return committedRef.current === authority
455
+ && commandEpochRef.current === authority.commandEpoch;
456
+ }
457
+
458
+ /** Výsledek společného hook enginu včetně outlet-only committed autority. */
459
+ interface ResolvedHookEngineResult<
460
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
461
+ Payload,
462
+ > {
463
+ /** Consumer-specific read-once payload. */
464
+ readonly payload: Payload;
465
+ /** Public frozen result sdílený hookem i outletem. */
466
+ readonly result: UseResolvedContributionsResult<Point>;
467
+ /** Exact query attempt current renderu. */
468
+ readonly attempt: resolvedContributionsQuery.ResolvedQueryAttempt<Point>;
469
+ /** Scope owning bridge a committed diagnostics. */
470
+ readonly scope: adapterScope.AdapterScopeRuntime;
471
+ /** Current generation; unavailable standalone capture ji nemá. */
472
+ readonly generation: adapterScope.AdapterScopeGeneration | undefined;
473
+ /** Exact raw registry reference pro membership identity. */
474
+ readonly rawRegistry: object;
475
+ /** Committed-attempt authority probe pro následné outlet effecty. */
476
+ readonly isCurrent: () => boolean;
477
+ /** Current render authority probe bez committed side effectu. */
478
+ readonly checkpoint: () => void;
479
+ /** Optional commit-owned outlet lease sdílená všemi memberships. */
480
+ readonly outletLease: outletCommitLease.OutletCommitLease | undefined;
481
+ /** True pouze pro server nebo první hydration render nad konstantním snapshotem. */
482
+ readonly serverSnapshot: boolean;
483
+ }
484
+
485
+ /** Optional engine požadavek na commit-owned outlet identitu. */
486
+ interface ResolvedHookCommitOwner {
487
+ /** Render-pure opaque outlet token. */
488
+ readonly token: outletCommitLease.OutletInstanceToken;
489
+ }
490
+
491
+ /** Commit observer používaný pouze public outletem po sink effectu. */
492
+ type ResolvedHookCommitObserver<
493
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
494
+ Payload,
495
+ > = (result: ResolvedHookEngineResult<Point, Payload>) => void;
496
+
497
+ /**
498
+ * Sdílí Hook pořadí, external-store bridge a query mezi public hookem a outletem.
499
+ */
500
+ function useResolvedContributionsEngine<
501
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
502
+ Payload,
503
+ >(
504
+ captureFactory: ResolvedHookCaptureFactory<Point, Payload>,
505
+ commitOwner?: ResolvedHookCommitOwner,
506
+ commitObserver?: ResolvedHookCommitObserver<Point, Payload>,
507
+ ): ResolvedHookEngineResult<Point, Payload> {
508
+ const parent = adapterContext.useAdapterContext();
509
+ const [localScope] = react.useState(createConsumerScope);
510
+ const [, forceRefresh] = react.useReducer(
511
+ /** Monotonicky posune pouze hook-local render command. */
512
+ function incrementRefreshEpoch(value: number): number {
513
+ return value + 1;
514
+ },
515
+ 0,
516
+ );
517
+ const renderSerialRef = react.useRef(0);
518
+ const commandEpochRef = react.useRef(0);
519
+ const controlRef = react.useRef<ResolvedHookControl>({
520
+ mounted: false,
521
+ allowWithoutGeneration: false,
522
+ });
523
+ const committedRef = react.useRef<CommittedResolvedAttempt | undefined>(undefined);
524
+ const storeCacheRef = react.useRef<ExternalStoreCache | undefined>(undefined);
525
+ const [outletLease, setOutletLease] = react.useState<
526
+ outletCommitLease.OutletCommitLease | undefined
527
+ >(undefined);
528
+ const [refresh] = react.useState(
529
+ /** Vytvoří právě jednu referenčně stabilní refresh capability. */
530
+ function createRefresh(): () => void {
531
+ /** Invaliduje předchozí command autoritu před React update schedulingem. */
532
+ function refreshResolvedContributions(): void {
533
+ const control = controlRef.current;
534
+ if (!control.mounted) {
535
+ return;
536
+ }
537
+ if (!control.allowWithoutGeneration
538
+ && (control.scope === undefined
539
+ || control.generation === undefined
540
+ || !control.scope.isGenerationActive(control.generation))) {
541
+ return;
542
+ }
543
+ commandEpochRef.current += 1;
544
+ forceRefresh();
545
+ }
546
+ return refreshResolvedContributions;
547
+ },
548
+ );
549
+
550
+ renderSerialRef.current += 1;
551
+ const renderSerial = renderSerialRef.current;
552
+ const renderCommandEpoch = commandEpochRef.current;
553
+ /** Ukončí reentrantně stale capture nebo query bez dalšího public Getu. */
554
+ function checkpointRenderAuthority(): void {
555
+ if (renderSerialRef.current !== renderSerial
556
+ || commandEpochRef.current !== renderCommandEpoch) {
557
+ throw new reactAdapterError.ReactAdapterError(
558
+ "REACT_ADAPTER_DISPOSED",
559
+ "The resolved contribution render attempt is no longer current.",
560
+ { details: { field: "hook.render", phase: "lifecycle" } },
561
+ );
562
+ }
563
+ }
564
+
565
+ let captured: ResolvedHookCapture<Point>;
566
+ let payload: Payload | undefined;
567
+ try {
568
+ const envelope = captureFactory(parent, localScope, checkpointRenderAuthority);
569
+ captured = envelope.captured;
570
+ payload = envelope.payload;
571
+ } catch (cause: unknown) {
572
+ captured = Object.freeze({ kind: "configurationFailure", cause });
573
+ }
574
+
575
+ const externalStore = captured.kind === "captured"
576
+ ? resolveExternalStoreBinding(
577
+ captured as CapturedResolvedHook<reactExtensionPoint.AnyReactExtensionPoint>,
578
+ storeCacheRef,
579
+ )
580
+ : EMPTY_EXTERNAL_STORE;
581
+ let renderAttempt: resolvedContributionsQuery.ResolvedQueryAttempt<Point> | undefined;
582
+ let renderConfiguration: adapterConfiguration.AdapterScopeConfiguration | undefined;
583
+ let renderScope: adapterScope.AdapterScopeRuntime | undefined;
584
+ let renderGeneration: adapterScope.AdapterScopeGeneration | undefined;
585
+ let renderStandalone = false;
586
+ const outletRegistryIdentity = captured.kind === "captured"
587
+ ? captured.protocol.rawRegistry
588
+ : captured.kind === "unavailable"
589
+ ? captured.rawRegistry
590
+ : undefined;
591
+
592
+ react.useEffect(
593
+ /** Standalone hook vlastní scope epochu pouze po React commitu. */
594
+ function acquireStandaloneScope(): void | (() => void) {
595
+ if (!renderStandalone || renderGeneration === undefined || renderScope === undefined) {
596
+ return undefined;
597
+ }
598
+ return renderScope.acquireOwner(renderGeneration);
599
+ },
600
+ [captured.kind === "captured" ? captured.scope : undefined,
601
+ captured.kind === "captured" ? captured.generation : undefined,
602
+ captured.kind === "captured" ? captured.standalone : false],
603
+ );
604
+
605
+ react.useEffect(
606
+ /** Publikuje pouze committed attempt autoritu a synchronně ji invaliduje při cleanupu. */
607
+ function commitResolvedAttempt(): () => void {
608
+ if (renderAttempt === undefined || renderScope === undefined) {
609
+ return function cleanupMissingAttempt(): void {
610
+ // Configuration failure nemá committed autoritu k invalidaci.
611
+ };
612
+ }
613
+ const authority: CommittedResolvedAttempt = Object.freeze({
614
+ attempt: renderAttempt as resolvedContributionsQuery.ResolvedQueryAttempt<
615
+ reactExtensionPoint.AnyReactExtensionPoint
616
+ >,
617
+ commandEpoch: commandEpochRef.current,
618
+ scope: renderScope,
619
+ configuration: renderConfiguration
620
+ ?? adapterConfiguration.EMPTY_ADAPTER_SCOPE_CONFIGURATION,
621
+ });
622
+ committedRef.current = authority;
623
+ controlRef.current = {
624
+ mounted: true,
625
+ scope: renderScope,
626
+ ...(renderGeneration === undefined ? {} : { generation: renderGeneration }),
627
+ allowWithoutGeneration: renderGeneration === undefined,
628
+ };
629
+ /** Zneplatní uniklé command capability před resource effect cleanupem. */
630
+ function cleanupCommittedAttempt(): void {
631
+ if (committedRef.current !== authority) {
632
+ return;
633
+ }
634
+ committedRef.current = undefined;
635
+ controlRef.current.mounted = false;
636
+ commandEpochRef.current += 1;
637
+ }
638
+ return cleanupCommittedAttempt;
639
+ },
640
+ );
641
+
642
+ react.useEffect(
643
+ /** Doručí secondary a primary diagnostiku pouze jednou pro committed attempt. */
644
+ function reportCommittedResolveFailure(): void {
645
+ const authority = committedRef.current;
646
+ if (authority === undefined
647
+ || authority.attempt !== renderAttempt
648
+ || renderAttempt?.primaryDiagnostic === undefined
649
+ || !authority.scope.claimDiagnosticAttempt(renderAttempt.token)) {
650
+ return;
651
+ }
652
+
653
+ if (renderAttempt.secondaryDiagnostic !== undefined) {
654
+ reactAdapterDiagnostics.reportReactAdapterDiagnostic(
655
+ renderAttempt.secondaryDiagnostic,
656
+ authority.configuration,
657
+ );
658
+ if (!isCommittedAttemptCurrent(authority, committedRef, commandEpochRef)) {
659
+ return;
660
+ }
661
+ }
662
+ reactAdapterDiagnostics.reportReactAdapterDiagnostic(
663
+ renderAttempt.primaryDiagnostic,
664
+ authority.configuration,
665
+ );
666
+ },
667
+ );
668
+
669
+ react.useEffect(
670
+ /** Přidělí outlet ID až po committed query autoritě a active scope epoše. */
671
+ function acquireOutletCommitLease(): void | (() => void) {
672
+ if (commitOwner === undefined
673
+ || renderGeneration === undefined
674
+ || renderScope === undefined
675
+ || renderAttempt?.state.status !== "resolved"
676
+ || committedRef.current?.attempt !== renderAttempt) {
677
+ return undefined;
678
+ }
679
+ const lease = renderScope.acquireCommitLease(
680
+ renderGeneration,
681
+ "outlet",
682
+ commitOwner.token,
683
+ );
684
+ setOutletLease(lease);
685
+ /** Synchronous cleanup zneplatní ID před další scope/outlet prací. */
686
+ function releaseOutletCommitLease(): void {
687
+ lease.release();
688
+ }
689
+ return releaseOutletCommitLease;
690
+ },
691
+ [commitOwner?.token, outletRegistryIdentity, renderScope, renderGeneration],
692
+ );
693
+
694
+ react.useEffect(
695
+ /** Doručí outlet observer až po committed authority, sinku a lease effectu. */
696
+ function notifyCommittedResolvedObserver(): void {
697
+ const attempt = renderAttempt;
698
+ const scope = renderScope;
699
+ if (commitObserver === undefined
700
+ || attempt === undefined
701
+ || scope === undefined
702
+ || payload === undefined) {
703
+ return;
704
+ }
705
+ const authority = committedRef.current;
706
+ if (authority === undefined
707
+ || authority.attempt !== attempt
708
+ || !isCommittedAttemptCurrent(authority, committedRef, commandEpochRef)) {
709
+ return;
710
+ }
711
+ const rawRegistry = captured.kind === "captured"
712
+ ? captured.protocol.rawRegistry
713
+ : captured.kind === "unavailable"
714
+ ? captured.rawRegistry
715
+ : undefined;
716
+ if (rawRegistry === undefined) {
717
+ return;
718
+ }
719
+ const committedAuthority: CommittedResolvedAttempt = authority;
720
+ /** Ověří tutéž authority i po user-observable callback seamu. */
721
+ function isCurrent(): boolean {
722
+ return isCommittedAttemptCurrent(
723
+ committedAuthority,
724
+ committedRef,
725
+ commandEpochRef,
726
+ );
727
+ }
728
+ const result: UseResolvedContributionsResult<Point> = Object.freeze({
729
+ state: attempt.state,
730
+ refresh,
731
+ });
732
+ try {
733
+ commitObserver(Object.freeze({
734
+ payload,
735
+ result,
736
+ attempt,
737
+ scope,
738
+ generation: renderGeneration,
739
+ rawRegistry,
740
+ isCurrent,
741
+ checkpoint: checkpointRenderAuthority,
742
+ outletLease,
743
+ serverSnapshot,
744
+ }));
745
+ } catch {
746
+ // Interní observer musí vlastní host callback chyby bezpečně normalizovat.
747
+ }
748
+ },
749
+ );
750
+
751
+ const externalStoreSnapshot = react.useSyncExternalStore(
752
+ externalStore.subscribe,
753
+ externalStore.getSnapshot,
754
+ externalStore.getServerSnapshot,
755
+ );
756
+ const serverSnapshot = externalStoreSnapshot === adapterRegistryBridge.ADAPTER_SERVER_SNAPSHOT;
757
+
758
+ if (captured.kind === "configurationFailure") {
759
+ throw captured.cause;
760
+ }
761
+
762
+ renderConfiguration = captured.configuration;
763
+ renderScope = captured.scope;
764
+ if (captured.kind === "captured") {
765
+ renderGeneration = captured.generation;
766
+ renderStandalone = captured.standalone;
767
+ const bridgeFault = externalStore.readFault();
768
+ renderAttempt = resolvedContributionsQuery.queryResolvedContributions({
769
+ protocol: captured.protocol,
770
+ point: captured.point,
771
+ context: captured.context,
772
+ configuration: captured.configuration,
773
+ ...(bridgeFault === undefined ? {} : { bridgeFault }),
774
+ checkpoint: checkpointRenderAuthority,
775
+ });
776
+ } else {
777
+ renderAttempt = resolvedContributionsQuery.createFailedResolvedQueryAttempt(
778
+ captured.cause,
779
+ captured.point,
780
+ captured.context,
781
+ captured.configuration,
782
+ checkpointRenderAuthority,
783
+ );
784
+ }
785
+
786
+ const attempt = renderAttempt;
787
+ const scope = renderScope;
788
+ if (attempt === undefined || scope === undefined || payload === undefined) {
789
+ throw new reactAdapterError.ReactAdapterError(
790
+ "REACT_ADAPTER_DISPOSED",
791
+ "The resolved contribution render attempt did not produce a complete binding.",
792
+ { details: { field: "hook.binding", phase: "lifecycle" } },
793
+ );
794
+ }
795
+ const rawRegistry = captured.kind === "captured"
796
+ ? captured.protocol.rawRegistry
797
+ : captured.rawRegistry;
798
+ const result: UseResolvedContributionsResult<Point> = Object.freeze({
799
+ state: attempt.state,
800
+ refresh,
801
+ });
802
+ /** Ověří exact attempt po jeho committed effectu a command epoch gate. */
803
+ function isCurrent(): boolean {
804
+ const authority = committedRef.current;
805
+ return authority !== undefined
806
+ && authority.attempt === attempt
807
+ && isCommittedAttemptCurrent(authority, committedRef, commandEpochRef);
808
+ }
809
+ return Object.freeze({
810
+ payload,
811
+ result,
812
+ attempt,
813
+ scope,
814
+ generation: renderGeneration,
815
+ rawRegistry,
816
+ isCurrent,
817
+ checkpoint: checkpointRenderAuthority,
818
+ outletLease,
819
+ serverSnapshot,
820
+ });
821
+ }
822
+
823
+ /**
824
+ * Synchronně promítne public Core katalog do React render state.
825
+ *
826
+ * @public
827
+ */
828
+ export function useResolvedContributions<
829
+ Point extends import("./react-extension-point.js").AnyReactExtensionPoint,
830
+ >(
831
+ options: UseResolvedContributionsOptions<Point>,
832
+ ): UseResolvedContributionsResult<Point> {
833
+ const engine = useResolvedContributionsEngine<Point, true>(
834
+ /** Zachytí public hook options uvnitř společného Hook-order-safe enginu. */
835
+ function capturePublicResolvedHook(parent, localScope, checkpoint) {
836
+ return Object.freeze({
837
+ captured: captureResolvedHook(options, parent, localScope, checkpoint),
838
+ payload: true as const,
839
+ });
840
+ },
841
+ );
842
+ return engine.result;
843
+ }
844
+
845
+ /**
846
+ * Interně promítne outlet props stejným subscriberem, query a committed autoritou.
847
+ */
848
+ export function useResolvedContributionsForOutlet<
849
+ Point extends reactExtensionPoint.AnyReactExtensionPoint,
850
+ >(
851
+ props: object,
852
+ commitObserver?: (
853
+ binding: OutletResolvedContributionsBinding<Point>,
854
+ ) => void,
855
+ ): OutletResolvedContributionsBinding<Point> {
856
+ const [outletToken] = react.useState(outletCommitLease.createOutletInstanceToken);
857
+ const engine = useResolvedContributionsEngine<
858
+ Point,
859
+ outletInput.CapturedOutletInput<Point>
860
+ >(
861
+ /** Zachytí celý outlet vstup právě jednou v normativním pořadí. */
862
+ function captureOutletHook(parent, localScope, checkpoint) {
863
+ return captureOutletResolvedHook<Point>(props, parent, localScope, checkpoint);
864
+ },
865
+ { token: outletToken },
866
+ commitObserver === undefined
867
+ ? undefined
868
+ : function observeCommittedOutlet(engineResult): void {
869
+ commitObserver(Object.freeze({
870
+ input: engineResult.payload,
871
+ result: engineResult.result,
872
+ attempt: engineResult.attempt,
873
+ scope: engineResult.scope,
874
+ generation: engineResult.generation,
875
+ rawRegistry: engineResult.rawRegistry,
876
+ isCurrent: engineResult.isCurrent,
877
+ checkpoint: engineResult.checkpoint,
878
+ outletLease: engineResult.outletLease,
879
+ serverSnapshot: engineResult.serverSnapshot,
880
+ }));
881
+ },
882
+ );
883
+ return Object.freeze({
884
+ input: engine.payload,
885
+ result: engine.result,
886
+ attempt: engine.attempt,
887
+ scope: engine.scope,
888
+ generation: engine.generation,
889
+ rawRegistry: engine.rawRegistry,
890
+ isCurrent: engine.isCurrent,
891
+ checkpoint: engine.checkpoint,
892
+ outletLease: engine.outletLease,
893
+ serverSnapshot: engine.serverSnapshot,
894
+ });
895
+ }