@hops-ops/distributed 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +454 -0
- package/dist/auth-headers.d.ts +8 -0
- package/dist/auth-headers.js +35 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +1 -0
- package/dist/document.d.ts +8 -0
- package/dist/document.js +6 -0
- package/dist/identity.d.ts +23 -0
- package/dist/identity.js +73 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/internal/cache-engine/create.d.ts +5 -0
- package/dist/internal/cache-engine/create.js +7 -0
- package/dist/internal/cache-engine/engine.d.ts +32 -0
- package/dist/internal/cache-engine/engine.js +1287 -0
- package/dist/internal/cache-engine/errors.d.ts +5 -0
- package/dist/internal/cache-engine/errors.js +10 -0
- package/dist/internal/cache-engine/helpers.d.ts +55 -0
- package/dist/internal/cache-engine/helpers.js +545 -0
- package/dist/internal/cache-engine/index.d.ts +3 -0
- package/dist/internal/cache-engine/index.js +2 -0
- package/dist/internal/cache-engine/types.d.ts +300 -0
- package/dist/internal/cache-engine/types.js +1 -0
- package/dist/internal/cache-engine.d.ts +3 -0
- package/dist/internal/cache-engine.js +2 -0
- package/dist/lib/assert-name.d.ts +2 -0
- package/dist/lib/assert-name.js +6 -0
- package/dist/lib/compare-code-units.d.ts +2 -0
- package/dist/lib/compare-code-units.js +4 -0
- package/dist/lib/deep-equal.d.ts +2 -0
- package/dist/lib/deep-equal.js +24 -0
- package/dist/lib/freeze-record.d.ts +2 -0
- package/dist/lib/freeze-record.js +13 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/is-plain-record.d.ts +2 -0
- package/dist/lib/is-plain-record.js +8 -0
- package/dist/lib/report.d.ts +7 -0
- package/dist/lib/report.js +26 -0
- package/dist/protocol.d.ts +179 -0
- package/dist/protocol.js +558 -0
- package/dist/react/context.d.ts +20 -0
- package/dist/react/context.js +24 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +3 -0
- package/dist/react/query.d.ts +20 -0
- package/dist/react/query.js +99 -0
- package/dist/replica/command-id.d.ts +2 -0
- package/dist/replica/command-id.js +19 -0
- package/dist/replica/command-runtime/constants.d.ts +5 -0
- package/dist/replica/command-runtime/constants.js +5 -0
- package/dist/replica/command-runtime/create.d.ts +2 -0
- package/dist/replica/command-runtime/create.js +644 -0
- package/dist/replica/command-runtime/errors.d.ts +16 -0
- package/dist/replica/command-runtime/errors.js +41 -0
- package/dist/replica/command-runtime/index.d.ts +5 -0
- package/dist/replica/command-runtime/index.js +4 -0
- package/dist/replica/command-runtime/lib/binding.d.ts +4 -0
- package/dist/replica/command-runtime/lib/binding.js +64 -0
- package/dist/replica/command-runtime/lib/effects.d.ts +11 -0
- package/dist/replica/command-runtime/lib/effects.js +89 -0
- package/dist/replica/command-runtime/lib/index.d.ts +9 -0
- package/dist/replica/command-runtime/lib/index.js +9 -0
- package/dist/replica/command-runtime/lib/inventory.d.ts +10 -0
- package/dist/replica/command-runtime/lib/inventory.js +141 -0
- package/dist/replica/command-runtime/lib/output.d.ts +13 -0
- package/dist/replica/command-runtime/lib/output.js +190 -0
- package/dist/replica/command-runtime/lib/projection.d.ts +20 -0
- package/dist/replica/command-runtime/lib/projection.js +255 -0
- package/dist/replica/command-runtime/lib/status.d.ts +7 -0
- package/dist/replica/command-runtime/lib/status.js +127 -0
- package/dist/replica/command-runtime/lib/transport.d.ts +16 -0
- package/dist/replica/command-runtime/lib/transport.js +112 -0
- package/dist/replica/command-runtime/lib/util.d.ts +16 -0
- package/dist/replica/command-runtime/lib/util.js +127 -0
- package/dist/replica/command-runtime/lifecycle.d.ts +11 -0
- package/dist/replica/command-runtime/lifecycle.js +13 -0
- package/dist/replica/command-runtime/symbols.d.ts +30 -0
- package/dist/replica/command-runtime/symbols.js +30 -0
- package/dist/replica/command-runtime/types.d.ts +222 -0
- package/dist/replica/command-runtime/types.js +1 -0
- package/dist/replica/command-runtime.d.ts +3 -0
- package/dist/replica/command-runtime.js +2 -0
- package/dist/replica/commands/clone.d.ts +12 -0
- package/dist/replica/commands/clone.js +187 -0
- package/dist/replica/commands/constants.d.ts +6 -0
- package/dist/replica/commands/constants.js +6 -0
- package/dist/replica/commands/errors.d.ts +7 -0
- package/dist/replica/commands/errors.js +22 -0
- package/dist/replica/commands/implementation.d.ts +8 -0
- package/dist/replica/commands/implementation.js +8 -0
- package/dist/replica/commands/index.d.ts +5 -0
- package/dist/replica/commands/index.js +4 -0
- package/dist/replica/commands/prepare.d.ts +27 -0
- package/dist/replica/commands/prepare.js +77 -0
- package/dist/replica/commands/presets.d.ts +12 -0
- package/dist/replica/commands/presets.js +84 -0
- package/dist/replica/commands/receipt.d.ts +3 -0
- package/dist/replica/commands/receipt.js +36 -0
- package/dist/replica/commands/resolve.d.ts +11 -0
- package/dist/replica/commands/resolve.js +165 -0
- package/dist/replica/commands/types.d.ts +278 -0
- package/dist/replica/commands/types.js +2 -0
- package/dist/replica/commands/util.d.ts +21 -0
- package/dist/replica/commands/util.js +96 -0
- package/dist/replica/commands/validate.d.ts +18 -0
- package/dist/replica/commands/validate.js +477 -0
- package/dist/replica/commands.d.ts +3 -0
- package/dist/replica/commands.js +2 -0
- package/dist/replica/diagnostics/event-log.d.ts +4 -0
- package/dist/replica/diagnostics/event-log.js +463 -0
- package/dist/replica/diagnostics/implementation.d.ts +4 -0
- package/dist/replica/diagnostics/implementation.js +4 -0
- package/dist/replica/diagnostics/index.d.ts +2 -0
- package/dist/replica/diagnostics/index.js +1 -0
- package/dist/replica/diagnostics/inspect.d.ts +6 -0
- package/dist/replica/diagnostics/inspect.js +170 -0
- package/dist/replica/diagnostics/types.d.ts +295 -0
- package/dist/replica/diagnostics/types.js +2 -0
- package/dist/replica/diagnostics.d.ts +3 -0
- package/dist/replica/diagnostics.js +2 -0
- package/dist/replica/distributed-replica/clocks.d.ts +23 -0
- package/dist/replica/distributed-replica/clocks.js +156 -0
- package/dist/replica/distributed-replica/constants.d.ts +12 -0
- package/dist/replica/distributed-replica/constants.js +10 -0
- package/dist/replica/distributed-replica/helpers.d.ts +48 -0
- package/dist/replica/distributed-replica/helpers.js +445 -0
- package/dist/replica/distributed-replica/hydration.d.ts +19 -0
- package/dist/replica/distributed-replica/hydration.js +380 -0
- package/dist/replica/distributed-replica/impl-diagnostics.d.ts +22 -0
- package/dist/replica/distributed-replica/impl-diagnostics.js +189 -0
- package/dist/replica/distributed-replica/impl-fetch-live.d.ts +39 -0
- package/dist/replica/distributed-replica/impl-fetch-live.js +395 -0
- package/dist/replica/distributed-replica/impl-hydration-orchestrate.d.ts +56 -0
- package/dist/replica/distributed-replica/impl-hydration-orchestrate.js +299 -0
- package/dist/replica/distributed-replica/impl-optimistic.d.ts +31 -0
- package/dist/replica/distributed-replica/impl-optimistic.js +172 -0
- package/dist/replica/distributed-replica/impl-protocol.d.ts +53 -0
- package/dist/replica/distributed-replica/impl-protocol.js +108 -0
- package/dist/replica/distributed-replica/impl.d.ts +44 -0
- package/dist/replica/distributed-replica/impl.js +1776 -0
- package/dist/replica/distributed-replica/index.d.ts +2 -0
- package/dist/replica/distributed-replica/index.js +4 -0
- package/dist/replica/distributed-replica/optimistic.d.ts +30 -0
- package/dist/replica/distributed-replica/optimistic.js +221 -0
- package/dist/replica/distributed-replica/types.d.ts +147 -0
- package/dist/replica/distributed-replica/types.js +1 -0
- package/dist/replica/distributed-replica/watch.d.ts +19 -0
- package/dist/replica/distributed-replica/watch.js +95 -0
- package/dist/replica/distributed-replica.d.ts +2 -0
- package/dist/replica/distributed-replica.js +2 -0
- package/dist/replica/graphql-transport.d.ts +24 -0
- package/dist/replica/graphql-transport.js +122 -0
- package/dist/replica/identity/clone.d.ts +6 -0
- package/dist/replica/identity/clone.js +54 -0
- package/dist/replica/identity/codec.d.ts +48 -0
- package/dist/replica/identity/codec.js +789 -0
- package/dist/replica/identity/constants.d.ts +3 -0
- package/dist/replica/identity/constants.js +18 -0
- package/dist/replica/identity/implementation.d.ts +5 -0
- package/dist/replica/identity/implementation.js +5 -0
- package/dist/replica/identity/index.d.ts +3 -0
- package/dist/replica/identity/index.js +3 -0
- package/dist/replica/identity/keys.d.ts +29 -0
- package/dist/replica/identity/keys.js +173 -0
- package/dist/replica/identity.d.ts +2 -0
- package/dist/replica/identity.js +2 -0
- package/dist/replica/index-maintenance/engine.d.ts +84 -0
- package/dist/replica/index-maintenance/engine.js +677 -0
- package/dist/replica/index-maintenance/implementation.d.ts +4 -0
- package/dist/replica/index-maintenance/implementation.js +4 -0
- package/dist/replica/index-maintenance/index.d.ts +2 -0
- package/dist/replica/index-maintenance/index.js +1 -0
- package/dist/replica/index-maintenance/registry.d.ts +2 -0
- package/dist/replica/index-maintenance/registry.js +49 -0
- package/dist/replica/index-maintenance/types.d.ts +58 -0
- package/dist/replica/index-maintenance/types.js +1 -0
- package/dist/replica/index-maintenance.d.ts +3 -0
- package/dist/replica/index-maintenance.js +2 -0
- package/dist/replica/index.d.ts +17 -0
- package/dist/replica/index.js +9 -0
- package/dist/replica/materialize.d.ts +10 -0
- package/dist/replica/materialize.js +163 -0
- package/dist/replica/normalize.d.ts +27 -0
- package/dist/replica/normalize.js +298 -0
- package/dist/replica/operation-binding.d.ts +14 -0
- package/dist/replica/operation-binding.js +76 -0
- package/dist/replica/persistence/idb.d.ts +20 -0
- package/dist/replica/persistence/idb.js +193 -0
- package/dist/replica/persistence/implementation.d.ts +4 -0
- package/dist/replica/persistence/implementation.js +4 -0
- package/dist/replica/persistence/index.d.ts +2 -0
- package/dist/replica/persistence/index.js +1 -0
- package/dist/replica/persistence/state.d.ts +104 -0
- package/dist/replica/persistence/state.js +734 -0
- package/dist/replica/persistence/types.d.ts +54 -0
- package/dist/replica/persistence/types.js +1 -0
- package/dist/replica/persistence.d.ts +3 -0
- package/dist/replica/persistence.js +2 -0
- package/dist/replica/query-plan/constants.d.ts +13 -0
- package/dist/replica/query-plan/constants.js +7 -0
- package/dist/replica/query-plan/filter.d.ts +39 -0
- package/dist/replica/query-plan/filter.js +544 -0
- package/dist/replica/query-plan/index.d.ts +4 -0
- package/dist/replica/query-plan/index.js +3 -0
- package/dist/replica/query-plan/order.d.ts +11 -0
- package/dist/replica/query-plan/order.js +158 -0
- package/dist/replica/query-plan/pagination.d.ts +6 -0
- package/dist/replica/query-plan/pagination.js +90 -0
- package/dist/replica/query-plan/resolve.d.ts +14 -0
- package/dist/replica/query-plan/resolve.js +163 -0
- package/dist/replica/query-plan/types.d.ts +89 -0
- package/dist/replica/query-plan/types.js +1 -0
- package/dist/replica/query-plan/util.d.ts +13 -0
- package/dist/replica/query-plan/util.js +62 -0
- package/dist/replica/query-plan.d.ts +3 -0
- package/dist/replica/query-plan.js +2 -0
- package/dist/replica/revalidation.d.ts +9 -0
- package/dist/replica/revalidation.js +86 -0
- package/dist/replica/selection.d.ts +20 -0
- package/dist/replica/selection.js +109 -0
- package/dist/replica/types.d.ts +657 -0
- package/dist/replica/types.js +1 -0
- package/dist/request.d.ts +17 -0
- package/dist/request.js +123 -0
- package/dist/sveltekit/auth.d.ts +18 -0
- package/dist/sveltekit/auth.js +9 -0
- package/dist/sveltekit/context.d.ts +28 -0
- package/dist/sveltekit/context.js +58 -0
- package/dist/sveltekit/index.d.ts +4 -0
- package/dist/sveltekit/index.js +4 -0
- package/dist/sveltekit/replica.d.ts +145 -0
- package/dist/sveltekit/replica.js +491 -0
- package/dist/sveltekit/server-replica.d.ts +52 -0
- package/dist/sveltekit/server-replica.js +176 -0
- package/dist/sveltekit/vite.d.ts +103 -0
- package/dist/sveltekit/vite.js +878 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js +1 -0
- package/dist/websocket.d.ts +41 -0
- package/dist/websocket.js +187 -0
- package/package.json +95 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile one validated command inventory into a reusable operation matcher.
|
|
3
|
+
*
|
|
4
|
+
* Adapters only forward generated plans; the replica owns knowledge of active
|
|
5
|
+
* operation artifacts and therefore remains the framework-neutral coordinator.
|
|
6
|
+
*/
|
|
7
|
+
export function createReplicaRevalidationMatcher(plan) {
|
|
8
|
+
const inventory = revalidationInventory(plan);
|
|
9
|
+
return (artifact) => inventory.global ||
|
|
10
|
+
artifact.roots.some((root) => intersects(root.dependencies, inventory.dependencies) ||
|
|
11
|
+
selectionMatches(root.selection, undefined, inventory));
|
|
12
|
+
}
|
|
13
|
+
function selectionMatches(selection, parentModel, inventory) {
|
|
14
|
+
const model = selection.storage.kind === 'normalized'
|
|
15
|
+
? selection.storage.model
|
|
16
|
+
: parentModel;
|
|
17
|
+
if (selection.storage.kind === 'normalized' &&
|
|
18
|
+
inventory.models.has(selection.storage.model)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
for (const member of selection.members) {
|
|
22
|
+
if (member.kind !== 'branch')
|
|
23
|
+
continue;
|
|
24
|
+
if (intersects(member.dependencies, inventory.dependencies))
|
|
25
|
+
return true;
|
|
26
|
+
if (member.semantic === 'relationship' &&
|
|
27
|
+
model !== undefined &&
|
|
28
|
+
inventory.relationships.has(relationshipKey(model, member.field, member.relationship.targetModel))) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (selectionMatches(member.selection, model, inventory))
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
function revalidationInventory(value) {
|
|
37
|
+
if (value === null ||
|
|
38
|
+
typeof value !== 'object' ||
|
|
39
|
+
!Array.isArray(value.dependencies) ||
|
|
40
|
+
!Array.isArray(value.models) ||
|
|
41
|
+
!Array.isArray(value.relationships)) {
|
|
42
|
+
invalidPlan();
|
|
43
|
+
}
|
|
44
|
+
const dependencies = stringSet(value.dependencies, 'dependencies');
|
|
45
|
+
const models = stringSet(value.models, 'models');
|
|
46
|
+
const relationships = new Set();
|
|
47
|
+
for (const [index, relationship] of value.relationships.entries()) {
|
|
48
|
+
if (relationship === null ||
|
|
49
|
+
typeof relationship !== 'object' ||
|
|
50
|
+
!validName(relationship.sourceModel) ||
|
|
51
|
+
!validName(relationship.field) ||
|
|
52
|
+
!validName(relationship.targetModel)) {
|
|
53
|
+
invalidPlan(`relationships[${index}]`);
|
|
54
|
+
}
|
|
55
|
+
relationships.add(relationshipKey(relationship.sourceModel, relationship.field, relationship.targetModel));
|
|
56
|
+
}
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
dependencies,
|
|
59
|
+
models,
|
|
60
|
+
relationships,
|
|
61
|
+
global: dependencies.size === 0 &&
|
|
62
|
+
models.size === 0 &&
|
|
63
|
+
relationships.size === 0
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function stringSet(values, path) {
|
|
67
|
+
const result = new Set();
|
|
68
|
+
for (const [index, value] of values.entries()) {
|
|
69
|
+
if (!validName(value))
|
|
70
|
+
invalidPlan(`${path}[${index}]`);
|
|
71
|
+
result.add(value);
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
function validName(value) {
|
|
76
|
+
return typeof value === 'string' && value.length > 0;
|
|
77
|
+
}
|
|
78
|
+
function intersects(left, right) {
|
|
79
|
+
return left.some((value) => right.has(value));
|
|
80
|
+
}
|
|
81
|
+
function relationshipKey(sourceModel, field, targetModel) {
|
|
82
|
+
return JSON.stringify([sourceModel, field, targetModel]);
|
|
83
|
+
}
|
|
84
|
+
function invalidPlan(path) {
|
|
85
|
+
throw new TypeError(`replica revalidation plan${path === undefined ? '' : ` ${path}`} is invalid`);
|
|
86
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReplicaObjectBranch, ReplicaRootSelection, ReplicaScalarSelection, ReplicaSelectionStorage } from './types.js';
|
|
2
|
+
export type RuntimeScalarSelection = ReplicaScalarSelection & {
|
|
3
|
+
readonly nullable: boolean;
|
|
4
|
+
};
|
|
5
|
+
export type RuntimeObjectSelection = {
|
|
6
|
+
readonly typename: string;
|
|
7
|
+
readonly storage: ReplicaSelectionStorage;
|
|
8
|
+
readonly members: readonly RuntimeObjectMember[];
|
|
9
|
+
};
|
|
10
|
+
export type RuntimeObjectBranch = Omit<ReplicaObjectBranch, 'selection'> & {
|
|
11
|
+
readonly selection: RuntimeObjectSelection;
|
|
12
|
+
readonly expose?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type RuntimeObjectMember = RuntimeScalarSelection | RuntimeObjectBranch;
|
|
15
|
+
export type RuntimeRootSelection = Omit<ReplicaRootSelection, 'nullable' | 'selection'> & {
|
|
16
|
+
readonly nullable: boolean;
|
|
17
|
+
readonly selection: RuntimeObjectSelection;
|
|
18
|
+
};
|
|
19
|
+
export declare function runtimeRoot(selection: ReplicaRootSelection): RuntimeRootSelection;
|
|
20
|
+
export declare function embeddedRecordKey(artifactId: string, enclosingIndexKey: string, ordinal: number | undefined): string;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { assertName } from '../lib/assert-name.js';
|
|
2
|
+
export function runtimeRoot(selection) {
|
|
3
|
+
assertBranchShape(selection, 'root');
|
|
4
|
+
if (typeof selection.nullable !== 'boolean') {
|
|
5
|
+
throw new TypeError(`root ${selection.responseKey} must declare exact nullability`);
|
|
6
|
+
}
|
|
7
|
+
return Object.freeze({
|
|
8
|
+
...selection,
|
|
9
|
+
nullable: selection.nullable,
|
|
10
|
+
selection: runtimeObject(selection.selection)
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export function embeddedRecordKey(artifactId, enclosingIndexKey, ordinal) {
|
|
14
|
+
const slot = ordinal === undefined ? 'one' : `ordinal:${ordinal}`;
|
|
15
|
+
return `embedded:${encodeURIComponent(artifactId)}:${encodeURIComponent(enclosingIndexKey)}:${slot}`;
|
|
16
|
+
}
|
|
17
|
+
function runtimeObject(selection) {
|
|
18
|
+
assertName(selection.typename, 'selection typename');
|
|
19
|
+
assertStorage(selection.storage);
|
|
20
|
+
if (!Array.isArray(selection.members)) {
|
|
21
|
+
throw new TypeError(`selection ${selection.typename} members must be an array`);
|
|
22
|
+
}
|
|
23
|
+
return Object.freeze({
|
|
24
|
+
typename: selection.typename,
|
|
25
|
+
storage: freezeStorage(selection.storage),
|
|
26
|
+
members: Object.freeze(selection.members.map((member) => {
|
|
27
|
+
if (member.kind === 'scalar')
|
|
28
|
+
return runtimeScalar(member);
|
|
29
|
+
if (member.kind !== 'branch') {
|
|
30
|
+
throw new TypeError(`selection ${selection.typename} contains an unsupported member`);
|
|
31
|
+
}
|
|
32
|
+
assertBranchShape(member, `branch ${member.responseKey}`);
|
|
33
|
+
if (member.semantic !== 'relationship' &&
|
|
34
|
+
member.semantic !== 'aggregate' &&
|
|
35
|
+
member.semantic !== 'aggregate_fields' &&
|
|
36
|
+
member.semantic !== 'aggregate_nodes') {
|
|
37
|
+
throw new TypeError(`branch ${member.responseKey} has unsupported semantic ${String(member.semantic)}`);
|
|
38
|
+
}
|
|
39
|
+
if (typeof member.nullable !== 'boolean') {
|
|
40
|
+
throw new TypeError(`branch ${member.responseKey} must declare exact nullability`);
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({
|
|
43
|
+
...member,
|
|
44
|
+
dependencies: freezeDependencies(member.dependencies, member.responseKey),
|
|
45
|
+
selection: runtimeObject(member.selection)
|
|
46
|
+
});
|
|
47
|
+
}))
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function runtimeScalar(selection) {
|
|
51
|
+
if (selection.kind !== 'scalar') {
|
|
52
|
+
throw new TypeError('object scalar member must have kind scalar');
|
|
53
|
+
}
|
|
54
|
+
assertName(selection.responseKey, 'scalar response key');
|
|
55
|
+
assertName(selection.field, `scalar ${selection.responseKey} field`);
|
|
56
|
+
assertName(selection.codec, `scalar ${selection.responseKey} codec`);
|
|
57
|
+
if (typeof selection.nullable !== 'boolean') {
|
|
58
|
+
throw new TypeError(`scalar ${selection.responseKey} must declare exact nullability`);
|
|
59
|
+
}
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
...selection,
|
|
62
|
+
nullable: selection.nullable
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function assertBranchShape(selection, description) {
|
|
66
|
+
assertName(selection.responseKey, `${description} response key`);
|
|
67
|
+
assertName(selection.field, `${description} field`);
|
|
68
|
+
if (selection.cardinality !== 'one' && selection.cardinality !== 'many') {
|
|
69
|
+
throw new TypeError(`${description} has unsupported cardinality`);
|
|
70
|
+
}
|
|
71
|
+
freezeDependencies(selection.dependencies, selection.responseKey);
|
|
72
|
+
}
|
|
73
|
+
function freezeDependencies(dependencies, responseKey) {
|
|
74
|
+
if (!Array.isArray(dependencies)) {
|
|
75
|
+
throw new TypeError(`branch ${responseKey} dependencies must be an array`);
|
|
76
|
+
}
|
|
77
|
+
for (const dependency of dependencies) {
|
|
78
|
+
assertName(dependency, `branch ${responseKey} dependency`);
|
|
79
|
+
}
|
|
80
|
+
return Object.freeze([...dependencies]);
|
|
81
|
+
}
|
|
82
|
+
function assertStorage(storage) {
|
|
83
|
+
if (storage.kind === 'embedded')
|
|
84
|
+
return;
|
|
85
|
+
if (storage.kind !== 'normalized') {
|
|
86
|
+
throw new TypeError('selection has unsupported storage');
|
|
87
|
+
}
|
|
88
|
+
assertName(storage.model, 'normalized model');
|
|
89
|
+
if (!Array.isArray(storage.identityFields) || storage.identityFields.length === 0) {
|
|
90
|
+
throw new TypeError(`normalized model ${storage.model} must declare at least one identity field`);
|
|
91
|
+
}
|
|
92
|
+
const unique = new Set();
|
|
93
|
+
for (const field of storage.identityFields) {
|
|
94
|
+
assertName(field, `normalized model ${storage.model} identity field`);
|
|
95
|
+
if (unique.has(field)) {
|
|
96
|
+
throw new TypeError(`normalized model ${storage.model} contains duplicate identity field ${field}`);
|
|
97
|
+
}
|
|
98
|
+
unique.add(field);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function freezeStorage(storage) {
|
|
102
|
+
if (storage.kind === 'embedded')
|
|
103
|
+
return Object.freeze({ kind: 'embedded' });
|
|
104
|
+
return Object.freeze({
|
|
105
|
+
kind: 'normalized',
|
|
106
|
+
model: storage.model,
|
|
107
|
+
identityFields: Object.freeze([...storage.identityFields])
|
|
108
|
+
});
|
|
109
|
+
}
|