@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.
- package/LICENSE +15 -0
- package/README.md +294 -0
- package/dist/contribution-component.d.ts +82 -0
- package/dist/contribution-component.d.ts.map +1 -0
- package/dist/contribution-component.js +12 -0
- package/dist/contribution-component.js.map +1 -0
- package/dist/extension-outlet.d.ts +155 -0
- package/dist/extension-outlet.d.ts.map +1 -0
- package/dist/extension-outlet.js +229 -0
- package/dist/extension-outlet.js.map +1 -0
- package/dist/extension-registry-provider.d.ts +26 -0
- package/dist/extension-registry-provider.d.ts.map +1 -0
- package/dist/extension-registry-provider.js +82 -0
- package/dist/extension-registry-provider.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/adapter-configuration.d.ts +54 -0
- package/dist/internal/adapter-configuration.d.ts.map +1 -0
- package/dist/internal/adapter-configuration.js +89 -0
- package/dist/internal/adapter-configuration.js.map +1 -0
- package/dist/internal/adapter-context.d.ts +24 -0
- package/dist/internal/adapter-context.d.ts.map +1 -0
- package/dist/internal/adapter-context.js +23 -0
- package/dist/internal/adapter-context.js.map +1 -0
- package/dist/internal/adapter-registry-bridge.d.ts +58 -0
- package/dist/internal/adapter-registry-bridge.d.ts.map +1 -0
- package/dist/internal/adapter-registry-bridge.js +494 -0
- package/dist/internal/adapter-registry-bridge.js.map +1 -0
- package/dist/internal/adapter-registry-protocol.d.ts +53 -0
- package/dist/internal/adapter-registry-protocol.d.ts.map +1 -0
- package/dist/internal/adapter-registry-protocol.js +182 -0
- package/dist/internal/adapter-registry-protocol.js.map +1 -0
- package/dist/internal/adapter-scope.d.ts +87 -0
- package/dist/internal/adapter-scope.d.ts.map +1 -0
- package/dist/internal/adapter-scope.js +346 -0
- package/dist/internal/adapter-scope.js.map +1 -0
- package/dist/internal/implementation-classifier.d.ts +21 -0
- package/dist/internal/implementation-classifier.d.ts.map +1 -0
- package/dist/internal/implementation-classifier.js +39 -0
- package/dist/internal/implementation-classifier.js.map +1 -0
- package/dist/internal/managed-lazy-generation.d.ts +100 -0
- package/dist/internal/managed-lazy-generation.d.ts.map +1 -0
- package/dist/internal/managed-lazy-generation.js +419 -0
- package/dist/internal/managed-lazy-generation.js.map +1 -0
- package/dist/internal/outlet-commit-lease.d.ts +46 -0
- package/dist/internal/outlet-commit-lease.d.ts.map +1 -0
- package/dist/internal/outlet-commit-lease.js +137 -0
- package/dist/internal/outlet-commit-lease.js.map +1 -0
- package/dist/internal/outlet-error-pipeline.d.ts +122 -0
- package/dist/internal/outlet-error-pipeline.d.ts.map +1 -0
- package/dist/internal/outlet-error-pipeline.js +214 -0
- package/dist/internal/outlet-error-pipeline.js.map +1 -0
- package/dist/internal/outlet-input.d.ts +42 -0
- package/dist/internal/outlet-input.d.ts.map +1 -0
- package/dist/internal/outlet-input.js +86 -0
- package/dist/internal/outlet-input.js.map +1 -0
- package/dist/internal/outlet-membership-boundary.d.ts +93 -0
- package/dist/internal/outlet-membership-boundary.d.ts.map +1 -0
- package/dist/internal/outlet-membership-boundary.js +710 -0
- package/dist/internal/outlet-membership-boundary.js.map +1 -0
- package/dist/internal/outlet-membership.d.ts +31 -0
- package/dist/internal/outlet-membership.d.ts.map +1 -0
- package/dist/internal/outlet-membership.js +65 -0
- package/dist/internal/outlet-membership.js.map +1 -0
- package/dist/internal/outlet-projection.d.ts +102 -0
- package/dist/internal/outlet-projection.d.ts.map +1 -0
- package/dist/internal/outlet-projection.js +228 -0
- package/dist/internal/outlet-projection.js.map +1 -0
- package/dist/internal/outlet-reporter-boundary.d.ts +42 -0
- package/dist/internal/outlet-reporter-boundary.d.ts.map +1 -0
- package/dist/internal/outlet-reporter-boundary.js +57 -0
- package/dist/internal/outlet-reporter-boundary.js.map +1 -0
- package/dist/internal/public-input-capture.d.ts +13 -0
- package/dist/internal/public-input-capture.d.ts.map +1 -0
- package/dist/internal/public-input-capture.js +34 -0
- package/dist/internal/public-input-capture.js.map +1 -0
- package/dist/internal/resolved-contributions-query.d.ts +42 -0
- package/dist/internal/resolved-contributions-query.d.ts.map +1 -0
- package/dist/internal/resolved-contributions-query.js +203 -0
- package/dist/internal/resolved-contributions-query.js.map +1 -0
- package/dist/react-adapter-diagnostics.d.ts +199 -0
- package/dist/react-adapter-diagnostics.d.ts.map +1 -0
- package/dist/react-adapter-diagnostics.js +257 -0
- package/dist/react-adapter-diagnostics.js.map +1 -0
- package/dist/react-adapter-error.d.ts +35 -0
- package/dist/react-adapter-error.d.ts.map +1 -0
- package/dist/react-adapter-error.js +37 -0
- package/dist/react-adapter-error.js.map +1 -0
- package/dist/react-extension-point.d.ts +26 -0
- package/dist/react-extension-point.d.ts.map +1 -0
- package/dist/react-extension-point.js +100 -0
- package/dist/react-extension-point.js.map +1 -0
- package/dist/react-lazy-contribution.d.ts +40 -0
- package/dist/react-lazy-contribution.d.ts.map +1 -0
- package/dist/react-lazy-contribution.js +18 -0
- package/dist/react-lazy-contribution.js.map +1 -0
- package/dist/resolved-contributions.d.ts +90 -0
- package/dist/resolved-contributions.d.ts.map +1 -0
- package/dist/resolved-contributions.js +455 -0
- package/dist/resolved-contributions.js.map +1 -0
- package/package.json +47 -0
- package/src/contribution-component.ts +118 -0
- package/src/extension-outlet.ts +590 -0
- package/src/extension-registry-provider.ts +179 -0
- package/src/index.ts +72 -0
- package/src/internal/adapter-configuration.ts +181 -0
- package/src/internal/adapter-context.ts +43 -0
- package/src/internal/adapter-registry-bridge.ts +723 -0
- package/src/internal/adapter-registry-protocol.ts +365 -0
- package/src/internal/adapter-scope.ts +500 -0
- package/src/internal/implementation-classifier.ts +59 -0
- package/src/internal/managed-lazy-generation.ts +540 -0
- package/src/internal/outlet-commit-lease.ts +216 -0
- package/src/internal/outlet-error-pipeline.ts +447 -0
- package/src/internal/outlet-input.ts +264 -0
- package/src/internal/outlet-membership-boundary.ts +1048 -0
- package/src/internal/outlet-membership.ts +125 -0
- package/src/internal/outlet-projection.ts +511 -0
- package/src/internal/outlet-reporter-boundary.ts +105 -0
- package/src/internal/public-input-capture.ts +55 -0
- package/src/internal/resolved-contributions-query.ts +318 -0
- package/src/react-adapter-diagnostics.ts +457 -0
- package/src/react-adapter-error.ts +88 -0
- package/src/react-extension-point.ts +181 -0
- package/src/react-lazy-contribution.ts +66 -0
- package/src/resolved-contributions.ts +895 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as react from "react";
|
|
2
|
+
|
|
3
|
+
import * as outletErrorPipeline from "./outlet-error-pipeline.js";
|
|
4
|
+
import type * as reactExtensionPoint from "../react-extension-point.js";
|
|
5
|
+
|
|
6
|
+
/** Props sink-only reporter boundary kolem host fallback rendereru. */
|
|
7
|
+
export interface OutletReporterBoundaryProps<
|
|
8
|
+
Point extends reactExtensionPoint.AnyReactExtensionPoint,
|
|
9
|
+
> {
|
|
10
|
+
/** React subtree, jehož failure se reportuje bez policy recursion. */
|
|
11
|
+
readonly children: react.ReactNode;
|
|
12
|
+
/** Metadata owning membership a committed diagnostic channelu. */
|
|
13
|
+
readonly errorInput: Omit<
|
|
14
|
+
outletErrorPipeline.OutletFallbackErrorInput<Point>,
|
|
15
|
+
"cause" | "reactComponentStack"
|
|
16
|
+
>;
|
|
17
|
+
/** Exact retry/error generation resetující reporter state. */
|
|
18
|
+
readonly generationToken: object;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Interní stav oddělující capture commit a následnou exact escalation. */
|
|
22
|
+
interface OutletReporterBoundaryState {
|
|
23
|
+
/** Captured fallback cause čekající na componentDidCatch commit. */
|
|
24
|
+
readonly cause: unknown;
|
|
25
|
+
/** Cause připravený k throw z vlastní boundary render cesty. */
|
|
26
|
+
readonly escalationCause: unknown;
|
|
27
|
+
/** Zda state skutečně obsahuje captured failure i pro undefined cause. */
|
|
28
|
+
readonly hasFailure: boolean;
|
|
29
|
+
/** Zda má následující render eskalovat exact cause. */
|
|
30
|
+
readonly hasEscalation: boolean;
|
|
31
|
+
/** Generation, pro kterou state platí. */
|
|
32
|
+
readonly generationToken: object;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Vytvoří čistý reporter state bez failure. */
|
|
36
|
+
function createReporterReadyState(generationToken: object): OutletReporterBoundaryState {
|
|
37
|
+
return {
|
|
38
|
+
cause: undefined,
|
|
39
|
+
escalationCause: undefined,
|
|
40
|
+
hasFailure: false,
|
|
41
|
+
hasEscalation: false,
|
|
42
|
+
generationToken,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Class boundary pro fallback/outlet renderer failure bez onError a policy recursion.
|
|
48
|
+
*/
|
|
49
|
+
export class OutletReporterBoundary<
|
|
50
|
+
Point extends reactExtensionPoint.AnyReactExtensionPoint,
|
|
51
|
+
> extends react.Component<
|
|
52
|
+
OutletReporterBoundaryProps<Point>,
|
|
53
|
+
OutletReporterBoundaryState
|
|
54
|
+
> {
|
|
55
|
+
/** State začíná v exact render generation props. */
|
|
56
|
+
public override state: OutletReporterBoundaryState = createReporterReadyState(
|
|
57
|
+
this.props.generationToken,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
/** Zachytí descendant failure bez user callbacku nebo sink side effectu. */
|
|
61
|
+
public static getDerivedStateFromError(cause: unknown): Partial<OutletReporterBoundaryState> {
|
|
62
|
+
return {
|
|
63
|
+
cause,
|
|
64
|
+
hasFailure: true,
|
|
65
|
+
hasEscalation: false,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Resetuje stale failure dříve, než se renderuje nová generation. */
|
|
70
|
+
public static getDerivedStateFromProps(
|
|
71
|
+
props: OutletReporterBoundaryProps<reactExtensionPoint.AnyReactExtensionPoint>,
|
|
72
|
+
state: OutletReporterBoundaryState,
|
|
73
|
+
): OutletReporterBoundaryState | null {
|
|
74
|
+
return props.generationToken === state.generationToken
|
|
75
|
+
? null
|
|
76
|
+
: createReporterReadyState(props.generationToken);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Commit point reportuje jednou a připraví exact escalation k host boundary. */
|
|
80
|
+
public override componentDidCatch(cause: unknown, info: react.ErrorInfo): void {
|
|
81
|
+
if (!this.state.hasFailure || !this.props.errorInput.isCurrent()) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const reactComponentStack = outletErrorPipeline.normalizeReactComponentStack(
|
|
85
|
+
info.componentStack,
|
|
86
|
+
);
|
|
87
|
+
const escalationCause = outletErrorPipeline.reportOutletFallbackError({
|
|
88
|
+
...this.props.errorInput,
|
|
89
|
+
cause,
|
|
90
|
+
...(reactComponentStack === undefined ? {} : { reactComponentStack }),
|
|
91
|
+
});
|
|
92
|
+
if (!this.props.errorInput.isCurrent()) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.setState({ escalationCause, hasEscalation: true });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Failed commit nejprve renderuje null, následující render eskaluje exact cause. */
|
|
99
|
+
public override render(): react.ReactNode {
|
|
100
|
+
if (this.state.hasEscalation) {
|
|
101
|
+
throw this.state.escalationCause;
|
|
102
|
+
}
|
|
103
|
+
return this.state.hasFailure ? null : this.props.children;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as reactAdapterError from "../react-adapter-error.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Oveří strukturální public input před jediným čtením jeho známých polí.
|
|
5
|
+
*/
|
|
6
|
+
export function requireInputObject(value: unknown, inputName: string): object {
|
|
7
|
+
if ((typeof value !== "object" || value === null) && typeof value !== "function") {
|
|
8
|
+
throw new reactAdapterError.ReactAdapterError(
|
|
9
|
+
"REACT_INVALID_ARGUMENT",
|
|
10
|
+
`${inputName} must be an object.`,
|
|
11
|
+
{ details: { field: inputName, phase: "configuration" } },
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Načte jedno známé pole právě jednou a zachová accessor/Proxy failure.
|
|
20
|
+
*/
|
|
21
|
+
export function readInputProperty(
|
|
22
|
+
target: object,
|
|
23
|
+
property: PropertyKey,
|
|
24
|
+
inputName: string,
|
|
25
|
+
checkpoint?: () => void,
|
|
26
|
+
): unknown {
|
|
27
|
+
let value: unknown;
|
|
28
|
+
try {
|
|
29
|
+
value = Reflect.get(target, property, target);
|
|
30
|
+
} catch (cause: unknown) {
|
|
31
|
+
throw new reactAdapterError.ReactAdapterError(
|
|
32
|
+
"REACT_INVALID_ARGUMENT",
|
|
33
|
+
`Unable to read ${inputName}.`,
|
|
34
|
+
{
|
|
35
|
+
cause,
|
|
36
|
+
details: { field: inputName, phase: "configuration" },
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
checkpoint?.();
|
|
42
|
+
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Vytvoří jednotnou strukturální chybu již zachyceného public inputu.
|
|
48
|
+
*/
|
|
49
|
+
export function throwInvalidCapturedArgument(inputName: string, message: string): never {
|
|
50
|
+
throw new reactAdapterError.ReactAdapterError(
|
|
51
|
+
"REACT_INVALID_ARGUMENT",
|
|
52
|
+
message,
|
|
53
|
+
{ details: { field: inputName, phase: "configuration" } },
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import type * as contribKitCore from "@primafuture/contrib-kit-core";
|
|
2
|
+
|
|
3
|
+
import * as adapterConfiguration from "./adapter-configuration.js";
|
|
4
|
+
import * as adapterRegistryProtocol from "./adapter-registry-protocol.js";
|
|
5
|
+
import * as reactAdapterDiagnostics from "../react-adapter-diagnostics.js";
|
|
6
|
+
import * as reactAdapterError from "../react-adapter-error.js";
|
|
7
|
+
import type * as reactExtensionPoint from "../react-extension-point.js";
|
|
8
|
+
import type * as resolvedContributions from "../resolved-contributions.js";
|
|
9
|
+
|
|
10
|
+
/** Sdílená frozen prázdná tuple použitá každým failed query výsledkem. */
|
|
11
|
+
export const EMPTY_RESOLVED_CONTRIBUTIONS: readonly [] = Object.freeze([]);
|
|
12
|
+
|
|
13
|
+
/** Jeden lokální render attempt bez externí resource identity. */
|
|
14
|
+
export interface ResolvedQueryAttempt<Point extends reactExtensionPoint.AnyReactExtensionPoint> {
|
|
15
|
+
/** Opaque token používaný pouze committed diagnostic ledgerem. */
|
|
16
|
+
readonly token: object;
|
|
17
|
+
/** Frozen public state daného render attemptu. */
|
|
18
|
+
readonly state: resolvedContributions.ResolvedContributionsState<Point>;
|
|
19
|
+
/** Projector failure doručovaná před primary resolve diagnostikou. */
|
|
20
|
+
readonly secondaryDiagnostic?: reactAdapterDiagnostics.ReactAdapterDiagnosticEvent;
|
|
21
|
+
/** Primary resolve diagnostika přítomná právě pro failed state. */
|
|
22
|
+
readonly primaryDiagnostic?: reactAdapterDiagnostics.ReactAdapterDiagnosticEvent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Vstupy jednoho synchronního Core list/resolve query. */
|
|
26
|
+
export interface ResolvedQueryInput<Point extends reactExtensionPoint.AnyReactExtensionPoint> {
|
|
27
|
+
/** Exact captured registry protocol včetně původního receiveru. */
|
|
28
|
+
readonly protocol: adapterRegistryProtocol.AdapterRegistryProtocolSnapshot;
|
|
29
|
+
/** Exact React point z public hook vstupu. */
|
|
30
|
+
readonly point: Point;
|
|
31
|
+
/** Point-specific context zachycený read-once z options. */
|
|
32
|
+
readonly context: contribKitCore.ExtensionPointContext<Point>;
|
|
33
|
+
/** Efektivní adapter konfigurace pro pure context projection. */
|
|
34
|
+
readonly configuration: adapterConfiguration.AdapterScopeConfiguration;
|
|
35
|
+
/** První bridge lifecycle fault, pokud již committed subscriber selhal. */
|
|
36
|
+
readonly bridgeFault?: reactAdapterError.ReactAdapterError;
|
|
37
|
+
/** Reentrantní authority checkpoint po každém host-observable seam. */
|
|
38
|
+
readonly checkpoint: () => void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Bezpečně vytvoří resolve chybu bez vložení raw invalidní business hodnoty. */
|
|
42
|
+
function createResolveError(
|
|
43
|
+
field: string,
|
|
44
|
+
cause?: unknown,
|
|
45
|
+
preserveCause = false,
|
|
46
|
+
): reactAdapterError.ReactAdapterError {
|
|
47
|
+
return new reactAdapterError.ReactAdapterError(
|
|
48
|
+
"REACT_RESOLVE_FAILED",
|
|
49
|
+
"The resolved contribution collection is invalid.",
|
|
50
|
+
preserveCause
|
|
51
|
+
? { cause, details: { field, phase: "resolve" } }
|
|
52
|
+
: { details: { field, phase: "resolve" } },
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Ověří structural array bez spuštění iterator user code. */
|
|
57
|
+
function requireContributionArray(value: unknown, field: string): readonly unknown[] {
|
|
58
|
+
if (!Array.isArray(value)) {
|
|
59
|
+
throw createResolveError(field);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Přečte pouze délku raw katalogu potřebnou pro empty klasifikaci. */
|
|
66
|
+
function readContributionArrayLength(
|
|
67
|
+
values: readonly unknown[],
|
|
68
|
+
field: string,
|
|
69
|
+
checkpoint: () => void,
|
|
70
|
+
): number {
|
|
71
|
+
let length: unknown;
|
|
72
|
+
try {
|
|
73
|
+
length = Reflect.get(values, "length", values);
|
|
74
|
+
} catch (cause: unknown) {
|
|
75
|
+
throw createResolveError(`${field}.length`, cause, true);
|
|
76
|
+
}
|
|
77
|
+
checkpoint();
|
|
78
|
+
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0) {
|
|
79
|
+
throw createResolveError(`${field}.length`);
|
|
80
|
+
}
|
|
81
|
+
return length;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Načte jedno známé record pole právě jednou a následně ověří autoritu. */
|
|
85
|
+
function readContributionProperty(
|
|
86
|
+
record: object,
|
|
87
|
+
property:
|
|
88
|
+
| "point"
|
|
89
|
+
| "registrationId"
|
|
90
|
+
| "contributionId"
|
|
91
|
+
| "contributorId"
|
|
92
|
+
| "localName"
|
|
93
|
+
| "label"
|
|
94
|
+
| "implementation"
|
|
95
|
+
| "data",
|
|
96
|
+
field: string,
|
|
97
|
+
checkpoint: () => void,
|
|
98
|
+
): unknown {
|
|
99
|
+
let value: unknown;
|
|
100
|
+
try {
|
|
101
|
+
value = Reflect.get(record, property, record);
|
|
102
|
+
} catch (cause: unknown) {
|
|
103
|
+
throw createResolveError(`${field}.${property}`, cause, true);
|
|
104
|
+
}
|
|
105
|
+
checkpoint();
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Ověří optional contribution metadata jako primitive string. */
|
|
110
|
+
function requireOptionalString(value: unknown, field: string): string | undefined {
|
|
111
|
+
if (value !== undefined && typeof value !== "string") {
|
|
112
|
+
throw createResolveError(field);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Zachytí jeden Core record bez neznámých polí a zachová business reference. */
|
|
119
|
+
function captureContribution<Point extends reactExtensionPoint.AnyReactExtensionPoint>(
|
|
120
|
+
value: unknown,
|
|
121
|
+
point: Point,
|
|
122
|
+
field: string,
|
|
123
|
+
checkpoint: () => void,
|
|
124
|
+
): contribKitCore.RegisteredContribution<Point> {
|
|
125
|
+
if (typeof value !== "object" || value === null) {
|
|
126
|
+
throw createResolveError(field);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const capturedPoint = readContributionProperty(value, "point", field, checkpoint);
|
|
130
|
+
const registrationId = readContributionProperty(value, "registrationId", field, checkpoint);
|
|
131
|
+
const contributionId = readContributionProperty(value, "contributionId", field, checkpoint);
|
|
132
|
+
const contributorId = readContributionProperty(value, "contributorId", field, checkpoint);
|
|
133
|
+
const localName = readContributionProperty(value, "localName", field, checkpoint);
|
|
134
|
+
const label = readContributionProperty(value, "label", field, checkpoint);
|
|
135
|
+
const implementation = readContributionProperty(value, "implementation", field, checkpoint);
|
|
136
|
+
const data = readContributionProperty(value, "data", field, checkpoint);
|
|
137
|
+
|
|
138
|
+
if (capturedPoint !== point) {
|
|
139
|
+
throw createResolveError(`${field}.point`);
|
|
140
|
+
}
|
|
141
|
+
if (typeof registrationId !== "string" || registrationId.length === 0) {
|
|
142
|
+
throw createResolveError(`${field}.registrationId`);
|
|
143
|
+
}
|
|
144
|
+
if (typeof contributionId !== "string" || contributionId.length === 0) {
|
|
145
|
+
throw createResolveError(`${field}.contributionId`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
point,
|
|
150
|
+
registrationId,
|
|
151
|
+
contributionId,
|
|
152
|
+
...(requireOptionalString(contributorId, `${field}.contributorId`) === undefined
|
|
153
|
+
? {}
|
|
154
|
+
: { contributorId: contributorId as string }),
|
|
155
|
+
...(requireOptionalString(localName, `${field}.localName`) === undefined
|
|
156
|
+
? {}
|
|
157
|
+
: { localName: localName as string }),
|
|
158
|
+
...(requireOptionalString(label, `${field}.label`) === undefined
|
|
159
|
+
? {}
|
|
160
|
+
: { label: label as string }),
|
|
161
|
+
implementation: implementation as contribKitCore.ExtensionPointImplementation<Point>,
|
|
162
|
+
data: data as contribKitCore.ExtensionPointData<Point>,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Zachytí celou ordered kolekci a odmítne duplicitní registration identity. */
|
|
167
|
+
function captureContributionArray<Point extends reactExtensionPoint.AnyReactExtensionPoint>(
|
|
168
|
+
value: unknown,
|
|
169
|
+
point: Point,
|
|
170
|
+
field: string,
|
|
171
|
+
checkpoint: () => void,
|
|
172
|
+
): readonly contribKitCore.RegisteredContribution<Point>[] {
|
|
173
|
+
const source = requireContributionArray(value, field);
|
|
174
|
+
const captured: contribKitCore.RegisteredContribution<Point>[] = [];
|
|
175
|
+
const registrationIds = new Set<string>();
|
|
176
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
177
|
+
let entry: unknown;
|
|
178
|
+
try {
|
|
179
|
+
entry = Reflect.get(source, index, source);
|
|
180
|
+
} catch (cause: unknown) {
|
|
181
|
+
throw createResolveError(`${field}[${index}]`, cause, true);
|
|
182
|
+
}
|
|
183
|
+
checkpoint();
|
|
184
|
+
const contribution = captureContribution(entry, point, `${field}[${index}]`, checkpoint);
|
|
185
|
+
if (registrationIds.has(contribution.registrationId)) {
|
|
186
|
+
throw createResolveError(`${field}[${index}].registrationId`);
|
|
187
|
+
}
|
|
188
|
+
registrationIds.add(contribution.registrationId);
|
|
189
|
+
captured.push(contribution);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return Object.freeze(captured);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Vytvoří primary a případnou secondary diagnostiku bez jejich doručení. */
|
|
196
|
+
export function createFailedResolvedQueryAttempt<
|
|
197
|
+
Point extends reactExtensionPoint.AnyReactExtensionPoint,
|
|
198
|
+
>(
|
|
199
|
+
cause: unknown,
|
|
200
|
+
point: Point,
|
|
201
|
+
context: contribKitCore.ExtensionPointContext<Point>,
|
|
202
|
+
configuration: adapterConfiguration.AdapterScopeConfiguration,
|
|
203
|
+
checkpoint: () => void,
|
|
204
|
+
): ResolvedQueryAttempt<Point> {
|
|
205
|
+
let primaryCause = cause;
|
|
206
|
+
let contextProjection: unknown;
|
|
207
|
+
let hasContextProjection = false;
|
|
208
|
+
let secondaryDiagnostic: reactAdapterDiagnostics.ReactAdapterDiagnosticEvent | undefined;
|
|
209
|
+
|
|
210
|
+
if (configuration.projectContext !== undefined) {
|
|
211
|
+
try {
|
|
212
|
+
contextProjection = Reflect.apply(configuration.projectContext, undefined, [context]);
|
|
213
|
+
hasContextProjection = true;
|
|
214
|
+
} catch (projectionCause: unknown) {
|
|
215
|
+
const pointMetadata = reactAdapterDiagnostics.createPointMetadata(point);
|
|
216
|
+
const projectionError = reactAdapterDiagnostics.createReactAdapterErrorEvent({
|
|
217
|
+
code: "REACT_CONTEXT_PROJECTION_FAILED",
|
|
218
|
+
phase: "projection",
|
|
219
|
+
cause: projectionCause,
|
|
220
|
+
...(pointMetadata === undefined ? {} : { point: pointMetadata }),
|
|
221
|
+
});
|
|
222
|
+
secondaryDiagnostic = reactAdapterDiagnostics.createErrorDiagnostic(projectionError);
|
|
223
|
+
}
|
|
224
|
+
if (hasContextProjection) {
|
|
225
|
+
try {
|
|
226
|
+
checkpoint();
|
|
227
|
+
} catch (authorityCause: unknown) {
|
|
228
|
+
primaryCause = authorityCause;
|
|
229
|
+
hasContextProjection = false;
|
|
230
|
+
contextProjection = undefined;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const coreCode = reactAdapterDiagnostics.readCoreErrorCode(primaryCause);
|
|
236
|
+
const code = reactAdapterDiagnostics.resolveReactErrorCode(primaryCause, coreCode);
|
|
237
|
+
const phase = reactAdapterDiagnostics.resolveReactErrorPhase(primaryCause);
|
|
238
|
+
const pointMetadata = reactAdapterDiagnostics.createPointMetadata(point);
|
|
239
|
+
const error = reactAdapterDiagnostics.createReactAdapterErrorEvent({
|
|
240
|
+
code,
|
|
241
|
+
phase,
|
|
242
|
+
cause: primaryCause,
|
|
243
|
+
...(coreCode === undefined ? {} : { coreCode }),
|
|
244
|
+
...(pointMetadata === undefined ? {} : { point: pointMetadata }),
|
|
245
|
+
contextProjection,
|
|
246
|
+
hasContextProjection,
|
|
247
|
+
});
|
|
248
|
+
const state: resolvedContributions.ResolvedContributionsState<Point> = Object.freeze({
|
|
249
|
+
status: "failed",
|
|
250
|
+
contributions: EMPTY_RESOLVED_CONTRIBUTIONS,
|
|
251
|
+
error,
|
|
252
|
+
});
|
|
253
|
+
return Object.freeze({
|
|
254
|
+
token: Object.freeze({}),
|
|
255
|
+
state,
|
|
256
|
+
...(secondaryDiagnostic === undefined ? {} : { secondaryDiagnostic }),
|
|
257
|
+
primaryDiagnostic: reactAdapterDiagnostics.createErrorDiagnostic(error),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Provede jeden synchronní list→resolve attempt a lokálně normalizuje jeho výsledek.
|
|
263
|
+
*/
|
|
264
|
+
export function queryResolvedContributions<
|
|
265
|
+
Point extends reactExtensionPoint.AnyReactExtensionPoint,
|
|
266
|
+
>(input: ResolvedQueryInput<Point>): ResolvedQueryAttempt<Point> {
|
|
267
|
+
try {
|
|
268
|
+
if (input.bridgeFault !== undefined) {
|
|
269
|
+
throw input.bridgeFault;
|
|
270
|
+
}
|
|
271
|
+
adapterRegistryProtocol.requireAdapterRegistryAvailable(
|
|
272
|
+
input.protocol,
|
|
273
|
+
"resolve",
|
|
274
|
+
input.checkpoint,
|
|
275
|
+
);
|
|
276
|
+
const listed = adapterRegistryProtocol.listAdapterRegistryContributions(
|
|
277
|
+
input.protocol,
|
|
278
|
+
input.point,
|
|
279
|
+
);
|
|
280
|
+
input.checkpoint();
|
|
281
|
+
const resolved = adapterRegistryProtocol.resolveAdapterRegistryContributions(
|
|
282
|
+
input.protocol,
|
|
283
|
+
input.point,
|
|
284
|
+
input.context,
|
|
285
|
+
);
|
|
286
|
+
input.checkpoint();
|
|
287
|
+
|
|
288
|
+
const contributions = captureContributionArray(
|
|
289
|
+
resolved,
|
|
290
|
+
input.point,
|
|
291
|
+
"registry.resolveContributions()",
|
|
292
|
+
input.checkpoint,
|
|
293
|
+
);
|
|
294
|
+
const rawContributionCount = readContributionArrayLength(
|
|
295
|
+
requireContributionArray(listed, "registry.listContributions()"),
|
|
296
|
+
"registry.listContributions()",
|
|
297
|
+
input.checkpoint,
|
|
298
|
+
);
|
|
299
|
+
const state: resolvedContributions.ResolvedContributionsState<Point> = Object.freeze({
|
|
300
|
+
status: "resolved",
|
|
301
|
+
contributions,
|
|
302
|
+
emptyReason: contributions.length > 0
|
|
303
|
+
? null
|
|
304
|
+
: rawContributionCount === 0
|
|
305
|
+
? "noRegistrations"
|
|
306
|
+
: "excludedByPolicy",
|
|
307
|
+
});
|
|
308
|
+
return Object.freeze({ token: Object.freeze({}), state });
|
|
309
|
+
} catch (cause: unknown) {
|
|
310
|
+
return createFailedResolvedQueryAttempt(
|
|
311
|
+
cause,
|
|
312
|
+
input.point,
|
|
313
|
+
input.context,
|
|
314
|
+
input.configuration,
|
|
315
|
+
input.checkpoint,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
}
|