houdini 1.2.0-react.1 → 1.2.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 +1 -1
- package/build/cmd-cjs/index.js +2213 -1533
- package/build/cmd-esm/index.js +2213 -1533
- package/build/codegen/generators/artifacts/selection.d.ts +2 -1
- package/build/codegen/generators/typescript/inlineType.d.ts +5 -2
- package/build/codegen/generators/typescript/loadingState.d.ts +8 -0
- package/build/codegen/transforms/fragmentVariables.d.ts +0 -11
- package/build/codegen-cjs/index.js +2143 -1487
- package/build/codegen-esm/index.js +2143 -1487
- package/build/lib/config.d.ts +5 -0
- package/build/lib/graphql.d.ts +5 -1
- package/build/lib/parse.d.ts +10 -1
- package/build/lib-cjs/index.js +702 -578
- package/build/lib-esm/index.js +699 -578
- package/build/runtime/cache/cache.d.ts +9 -8
- package/build/runtime/cache/stuff.d.ts +1 -4
- package/build/runtime/client/documentStore.d.ts +3 -3
- package/build/runtime/client/index.d.ts +8 -7
- package/build/runtime/client/plugins/cache.d.ts +1 -1
- package/build/runtime/client/plugins/fetch.d.ts +1 -0
- package/build/runtime/client/plugins/subscription.d.ts +1 -0
- package/build/runtime/client/plugins/throwOnError.d.ts +2 -1
- package/build/runtime/lib/pagination.d.ts +4 -6
- package/build/runtime/lib/selection.d.ts +1 -1
- package/build/runtime/lib/types.d.ts +37 -4
- package/build/runtime-cjs/cache/cache.d.ts +9 -8
- package/build/runtime-cjs/cache/cache.js +108 -43
- package/build/runtime-cjs/cache/stuff.d.ts +1 -4
- package/build/runtime-cjs/cache/stuff.js +2 -2
- package/build/runtime-cjs/cache/subscription.js +5 -5
- package/build/runtime-cjs/client/documentStore.d.ts +3 -3
- package/build/runtime-cjs/client/documentStore.js +10 -2
- package/build/runtime-cjs/client/index.d.ts +8 -7
- package/build/runtime-cjs/client/index.js +12 -4
- package/build/runtime-cjs/client/plugins/cache.d.ts +1 -1
- package/build/runtime-cjs/client/plugins/cache.js +10 -2
- package/build/runtime-cjs/client/plugins/fetch.d.ts +1 -0
- package/build/runtime-cjs/client/plugins/fetch.js +3 -2
- package/build/runtime-cjs/client/plugins/subscription.d.ts +1 -0
- package/build/runtime-cjs/client/plugins/subscription.js +1 -0
- package/build/runtime-cjs/client/plugins/throwOnError.d.ts +2 -1
- package/build/runtime-cjs/lib/config.js +2 -1
- package/build/runtime-cjs/lib/pagination.d.ts +4 -6
- package/build/runtime-cjs/lib/pagination.js +0 -12
- package/build/runtime-cjs/lib/scalars.js +1 -1
- package/build/runtime-cjs/lib/selection.d.ts +1 -1
- package/build/runtime-cjs/lib/selection.js +28 -1
- package/build/runtime-cjs/lib/types.d.ts +37 -4
- package/build/runtime-cjs/lib/types.js +3 -0
- package/build/runtime-esm/cache/cache.d.ts +9 -8
- package/build/runtime-esm/cache/cache.js +109 -44
- package/build/runtime-esm/cache/stuff.d.ts +1 -4
- package/build/runtime-esm/cache/stuff.js +2 -2
- package/build/runtime-esm/cache/subscription.js +5 -5
- package/build/runtime-esm/client/documentStore.d.ts +3 -3
- package/build/runtime-esm/client/documentStore.js +10 -2
- package/build/runtime-esm/client/index.d.ts +8 -7
- package/build/runtime-esm/client/index.js +15 -7
- package/build/runtime-esm/client/plugins/cache.d.ts +1 -1
- package/build/runtime-esm/client/plugins/cache.js +10 -2
- package/build/runtime-esm/client/plugins/fetch.d.ts +1 -0
- package/build/runtime-esm/client/plugins/fetch.js +3 -2
- package/build/runtime-esm/client/plugins/subscription.d.ts +1 -0
- package/build/runtime-esm/client/plugins/subscription.js +1 -0
- package/build/runtime-esm/client/plugins/throwOnError.d.ts +2 -1
- package/build/runtime-esm/lib/config.js +2 -1
- package/build/runtime-esm/lib/pagination.d.ts +4 -6
- package/build/runtime-esm/lib/pagination.js +0 -12
- package/build/runtime-esm/lib/scalars.js +1 -1
- package/build/runtime-esm/lib/selection.d.ts +1 -1
- package/build/runtime-esm/lib/selection.js +28 -1
- package/build/runtime-esm/lib/types.d.ts +37 -4
- package/build/runtime-esm/lib/types.js +2 -0
- package/build/test/index.d.ts +15 -0
- package/build/test-cjs/index.js +2174 -1490
- package/build/test-esm/index.js +2174 -1490
- package/build/vite-cjs/index.js +2243 -1561
- package/build/vite-esm/index.js +2243 -1561
- package/package.json +7 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computeKey } from "../lib";
|
|
1
|
+
import { computeKey, PendingValue } from "../lib";
|
|
2
2
|
import { computeID, defaultConfigValues, keyFieldsForType, getCurrentConfig } from "../lib/config";
|
|
3
3
|
import { deepEquals } from "../lib/deepEquals";
|
|
4
4
|
import { flatten } from "../lib/flatten";
|
|
@@ -6,7 +6,6 @@ import { getFieldsForType } from "../lib/selection";
|
|
|
6
6
|
import { fragmentKey } from "../lib/types";
|
|
7
7
|
import { GarbageCollector } from "./gc";
|
|
8
8
|
import { ListManager } from "./lists";
|
|
9
|
-
import { SchemaManager } from "./schema";
|
|
10
9
|
import { StaleManager } from "./staleManager";
|
|
11
10
|
import { InMemoryStorage } from "./storage";
|
|
12
11
|
import { evaluateKey } from "./stuff";
|
|
@@ -21,7 +20,6 @@ class Cache {
|
|
|
21
20
|
lists: new ListManager(this, rootID),
|
|
22
21
|
lifetimes: new GarbageCollector(this),
|
|
23
22
|
staleManager: new StaleManager(this),
|
|
24
|
-
schema: new SchemaManager(this),
|
|
25
23
|
disabled: disabled ?? typeof globalThis.window === "undefined"
|
|
26
24
|
});
|
|
27
25
|
if (Object.keys(config).length > 0) {
|
|
@@ -132,7 +130,6 @@ class CacheInternal {
|
|
|
132
130
|
cache;
|
|
133
131
|
lifetimes;
|
|
134
132
|
staleManager;
|
|
135
|
-
schema;
|
|
136
133
|
constructor({
|
|
137
134
|
storage,
|
|
138
135
|
subscriptions,
|
|
@@ -140,7 +137,6 @@ class CacheInternal {
|
|
|
140
137
|
cache,
|
|
141
138
|
lifetimes,
|
|
142
139
|
staleManager,
|
|
143
|
-
schema,
|
|
144
140
|
disabled,
|
|
145
141
|
config
|
|
146
142
|
}) {
|
|
@@ -150,7 +146,6 @@ class CacheInternal {
|
|
|
150
146
|
this.cache = cache;
|
|
151
147
|
this.lifetimes = lifetimes;
|
|
152
148
|
this.staleManager = staleManager;
|
|
153
|
-
this.schema = schema;
|
|
154
149
|
this._config = config;
|
|
155
150
|
this._disabled = disabled;
|
|
156
151
|
try {
|
|
@@ -180,7 +175,11 @@ class CacheInternal {
|
|
|
180
175
|
if (this._disabled) {
|
|
181
176
|
return [];
|
|
182
177
|
}
|
|
183
|
-
let targetSelection = getFieldsForType(
|
|
178
|
+
let targetSelection = getFieldsForType(
|
|
179
|
+
selection,
|
|
180
|
+
data["__typename"],
|
|
181
|
+
false
|
|
182
|
+
);
|
|
184
183
|
for (const [field, value] of Object.entries(data)) {
|
|
185
184
|
if (!selection || !targetSelection[field]) {
|
|
186
185
|
continue;
|
|
@@ -191,17 +190,9 @@ class CacheInternal {
|
|
|
191
190
|
selection: fieldSelection,
|
|
192
191
|
operations,
|
|
193
192
|
abstract: isAbstract,
|
|
194
|
-
updates
|
|
195
|
-
nullable
|
|
193
|
+
updates
|
|
196
194
|
} = targetSelection[field];
|
|
197
195
|
const key = evaluateKey(keyRaw, variables);
|
|
198
|
-
this.schema.setFieldType({
|
|
199
|
-
parent,
|
|
200
|
-
key: keyRaw,
|
|
201
|
-
type: linkedType,
|
|
202
|
-
nullable,
|
|
203
|
-
link: !!fieldSelection
|
|
204
|
-
});
|
|
205
196
|
if (value && typeof value === "object" && "__typename" in value && value["__typename"]) {
|
|
206
197
|
linkedType = value["__typename"];
|
|
207
198
|
}
|
|
@@ -446,42 +437,83 @@ class CacheInternal {
|
|
|
446
437
|
parent = rootID,
|
|
447
438
|
variables,
|
|
448
439
|
stepsFromConnection = null,
|
|
449
|
-
ignoreMasking
|
|
440
|
+
ignoreMasking,
|
|
441
|
+
fullCheck = false,
|
|
442
|
+
loading: generateLoading
|
|
450
443
|
}) {
|
|
451
444
|
if (parent === null) {
|
|
452
445
|
return { data: null, partial: false, stale: false, hasData: true };
|
|
453
446
|
}
|
|
454
447
|
const target = {};
|
|
455
448
|
if (selection.fragments) {
|
|
456
|
-
target[fragmentKey] =
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
449
|
+
target[fragmentKey] = {
|
|
450
|
+
loading: Boolean(generateLoading),
|
|
451
|
+
values: Object.fromEntries(
|
|
452
|
+
Object.entries(selection.fragments).filter(([, value]) => !generateLoading || value.loading).map(([key, value]) => [
|
|
453
|
+
key,
|
|
454
|
+
{
|
|
455
|
+
parent,
|
|
456
|
+
variables: evaluateFragmentVariables(
|
|
457
|
+
value.arguments,
|
|
458
|
+
variables ?? {}
|
|
459
|
+
)
|
|
460
|
+
}
|
|
461
|
+
])
|
|
462
|
+
)
|
|
463
|
+
};
|
|
465
464
|
}
|
|
466
465
|
let hasData = !!selection.fragments;
|
|
467
466
|
let partial = false;
|
|
468
467
|
let cascadeNull = false;
|
|
469
468
|
let stale = false;
|
|
470
469
|
const typename = this.storage.get(parent, "__typename").value;
|
|
471
|
-
let targetSelection = getFieldsForType(selection, typename);
|
|
470
|
+
let targetSelection = getFieldsForType(selection, typename, !!generateLoading);
|
|
472
471
|
for (const [
|
|
473
472
|
attributeName,
|
|
474
|
-
{
|
|
473
|
+
{
|
|
474
|
+
type,
|
|
475
|
+
keyRaw,
|
|
476
|
+
selection: fieldSelection,
|
|
477
|
+
nullable,
|
|
478
|
+
list,
|
|
479
|
+
visible,
|
|
480
|
+
directives,
|
|
481
|
+
loading: fieldLoading,
|
|
482
|
+
abstractHasRequired
|
|
483
|
+
}
|
|
475
484
|
] of Object.entries(targetSelection)) {
|
|
476
|
-
if (!visible && !ignoreMasking) {
|
|
485
|
+
if (!visible && !ignoreMasking && !fullCheck) {
|
|
477
486
|
continue;
|
|
478
487
|
}
|
|
488
|
+
const includeDirective = directives?.find((d) => {
|
|
489
|
+
return d.name === "include";
|
|
490
|
+
});
|
|
491
|
+
if (includeDirective) {
|
|
492
|
+
if (!evaluateFragmentVariables(includeDirective.arguments, variables ?? {})["if"]) {
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const skipDirective = directives?.find((d) => {
|
|
497
|
+
return d.name === "skip";
|
|
498
|
+
});
|
|
499
|
+
if (skipDirective) {
|
|
500
|
+
if (evaluateFragmentVariables(skipDirective.arguments, variables ?? {})["if"]) {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const fieldTarget = visible || ignoreMasking ? target : {};
|
|
479
505
|
const key = evaluateKey(keyRaw, variables);
|
|
480
|
-
|
|
506
|
+
if (generateLoading && !fieldLoading) {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
let { value } = this.storage.get(parent, key);
|
|
481
510
|
const dt_field = this.staleManager.getFieldTime(parent, key);
|
|
482
511
|
if (dt_field === null) {
|
|
483
512
|
stale = true;
|
|
484
513
|
}
|
|
514
|
+
if (generateLoading) {
|
|
515
|
+
value = void 0;
|
|
516
|
+
}
|
|
485
517
|
let nextStep = stepsFromConnection;
|
|
486
518
|
if (nextStep !== null) {
|
|
487
519
|
if (nextStep >= 2) {
|
|
@@ -497,17 +529,20 @@ class CacheInternal {
|
|
|
497
529
|
if (typeof value === "undefined" && !embeddedCursor) {
|
|
498
530
|
partial = true;
|
|
499
531
|
}
|
|
500
|
-
if (
|
|
501
|
-
|
|
532
|
+
if (generateLoading && fieldLoading?.kind === "value") {
|
|
533
|
+
fieldTarget[attributeName] = PendingValue;
|
|
534
|
+
hasData = true;
|
|
535
|
+
} else if (!generateLoading && typeof value === "undefined" || value === null) {
|
|
536
|
+
fieldTarget[attributeName] = null;
|
|
502
537
|
if (typeof value !== "undefined") {
|
|
503
538
|
hasData = true;
|
|
504
539
|
}
|
|
505
540
|
} else if (!fieldSelection) {
|
|
506
541
|
const fnUnmarshal = this.config?.scalars?.[type]?.unmarshal;
|
|
507
542
|
if (fnUnmarshal) {
|
|
508
|
-
|
|
543
|
+
fieldTarget[attributeName] = fnUnmarshal(value);
|
|
509
544
|
} else {
|
|
510
|
-
|
|
545
|
+
fieldTarget[attributeName] = value;
|
|
511
546
|
}
|
|
512
547
|
hasData = true;
|
|
513
548
|
} else if (Array.isArray(value)) {
|
|
@@ -516,9 +551,11 @@ class CacheInternal {
|
|
|
516
551
|
variables,
|
|
517
552
|
linkedList: value,
|
|
518
553
|
stepsFromConnection: nextStep,
|
|
519
|
-
ignoreMasking: !!ignoreMasking
|
|
554
|
+
ignoreMasking: !!ignoreMasking,
|
|
555
|
+
fullCheck,
|
|
556
|
+
loading: generateLoading
|
|
520
557
|
});
|
|
521
|
-
|
|
558
|
+
fieldTarget[attributeName] = listValue.data;
|
|
522
559
|
if (listValue.partial) {
|
|
523
560
|
partial = true;
|
|
524
561
|
}
|
|
@@ -534,9 +571,11 @@ class CacheInternal {
|
|
|
534
571
|
selection: fieldSelection,
|
|
535
572
|
variables,
|
|
536
573
|
stepsFromConnection: nextStep,
|
|
537
|
-
ignoreMasking
|
|
574
|
+
ignoreMasking,
|
|
575
|
+
fullCheck,
|
|
576
|
+
loading: generateLoading
|
|
538
577
|
});
|
|
539
|
-
|
|
578
|
+
fieldTarget[attributeName] = objectFields.data;
|
|
540
579
|
if (objectFields.partial) {
|
|
541
580
|
partial = true;
|
|
542
581
|
}
|
|
@@ -547,13 +586,27 @@ class CacheInternal {
|
|
|
547
586
|
hasData = true;
|
|
548
587
|
}
|
|
549
588
|
}
|
|
550
|
-
if (
|
|
551
|
-
|
|
589
|
+
if (generateLoading && fieldLoading?.list) {
|
|
590
|
+
fieldTarget[attributeName] = wrapInLists(
|
|
591
|
+
Array.from({ length: fieldLoading.list.count }).fill(
|
|
592
|
+
fieldTarget[attributeName]
|
|
593
|
+
),
|
|
594
|
+
fieldLoading.list.depth - 1
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
if (fieldTarget[attributeName] === null && !nullable && !embeddedCursor) {
|
|
598
|
+
if (abstractHasRequired) {
|
|
599
|
+
target[attributeName] = {
|
|
600
|
+
__typename: "@required field missing; don't match this"
|
|
601
|
+
};
|
|
602
|
+
} else {
|
|
603
|
+
cascadeNull = true;
|
|
604
|
+
}
|
|
552
605
|
}
|
|
553
606
|
}
|
|
554
607
|
return {
|
|
555
608
|
data: cascadeNull ? null : target,
|
|
556
|
-
partial: hasData && partial,
|
|
609
|
+
partial: !generateLoading && hasData && partial,
|
|
557
610
|
stale: hasData && stale,
|
|
558
611
|
hasData
|
|
559
612
|
};
|
|
@@ -579,7 +632,9 @@ class CacheInternal {
|
|
|
579
632
|
variables,
|
|
580
633
|
linkedList,
|
|
581
634
|
stepsFromConnection,
|
|
582
|
-
ignoreMasking
|
|
635
|
+
ignoreMasking,
|
|
636
|
+
fullCheck,
|
|
637
|
+
loading
|
|
583
638
|
}) {
|
|
584
639
|
const result = [];
|
|
585
640
|
let partialData = false;
|
|
@@ -592,7 +647,9 @@ class CacheInternal {
|
|
|
592
647
|
variables,
|
|
593
648
|
linkedList: entry,
|
|
594
649
|
stepsFromConnection,
|
|
595
|
-
ignoreMasking
|
|
650
|
+
ignoreMasking,
|
|
651
|
+
fullCheck,
|
|
652
|
+
loading
|
|
596
653
|
});
|
|
597
654
|
result.push(nestedValue.data);
|
|
598
655
|
if (nestedValue.partial) {
|
|
@@ -614,7 +671,9 @@ class CacheInternal {
|
|
|
614
671
|
selection: fields,
|
|
615
672
|
variables,
|
|
616
673
|
stepsFromConnection,
|
|
617
|
-
ignoreMasking
|
|
674
|
+
ignoreMasking,
|
|
675
|
+
fullCheck,
|
|
676
|
+
loading
|
|
618
677
|
});
|
|
619
678
|
result.push(data);
|
|
620
679
|
if (partial) {
|
|
@@ -721,6 +780,12 @@ function evaluateFragmentVariables(variables, args) {
|
|
|
721
780
|
Object.entries(variables).map(([key, value]) => [key, fragmentVariableValue(value, args)])
|
|
722
781
|
);
|
|
723
782
|
}
|
|
783
|
+
function wrapInLists(target, count = 0) {
|
|
784
|
+
if (count === 0) {
|
|
785
|
+
return target;
|
|
786
|
+
}
|
|
787
|
+
return wrapInLists([target], count - 1);
|
|
788
|
+
}
|
|
724
789
|
function fragmentVariableValue(value, args) {
|
|
725
790
|
if (value.kind === "StringValue") {
|
|
726
791
|
return value.value;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function evaluateKey(key, variables =
|
|
1
|
+
function evaluateKey(key, variables = null) {
|
|
2
2
|
let evaluated = "";
|
|
3
3
|
let varName = "";
|
|
4
4
|
let inString = false;
|
|
@@ -8,7 +8,7 @@ function evaluateKey(key, variables = {}) {
|
|
|
8
8
|
varName += char;
|
|
9
9
|
continue;
|
|
10
10
|
}
|
|
11
|
-
const value = variables[varName.slice(1)];
|
|
11
|
+
const value = variables?.[varName.slice(1)];
|
|
12
12
|
evaluated += typeof value !== "undefined" ? JSON.stringify(value) : "undefined";
|
|
13
13
|
varName = "";
|
|
14
14
|
}
|
|
@@ -17,7 +17,7 @@ class InMemorySubscriptions {
|
|
|
17
17
|
parentType
|
|
18
18
|
}) {
|
|
19
19
|
const __typename = this.cache._internal_unstable.storage.get(parent, "__typename").value;
|
|
20
|
-
let targetSelection = getFieldsForType(selection, __typename);
|
|
20
|
+
let targetSelection = getFieldsForType(selection, __typename, false);
|
|
21
21
|
for (const fieldSelection of Object.values(targetSelection || {})) {
|
|
22
22
|
const {
|
|
23
23
|
keyRaw,
|
|
@@ -34,7 +34,7 @@ class InMemorySubscriptions {
|
|
|
34
34
|
let targetSelection2;
|
|
35
35
|
if (innerSelection) {
|
|
36
36
|
const __typename2 = this.cache._internal_unstable.storage.get(parent, "__typename").value;
|
|
37
|
-
targetSelection2 = getFieldsForType(innerSelection, __typename2);
|
|
37
|
+
targetSelection2 = getFieldsForType(innerSelection, __typename2, false);
|
|
38
38
|
}
|
|
39
39
|
this.addFieldSubscription({
|
|
40
40
|
id: parent,
|
|
@@ -145,7 +145,7 @@ class InMemorySubscriptions {
|
|
|
145
145
|
filters
|
|
146
146
|
} = selection;
|
|
147
147
|
const key = evaluateKey(keyRaw, variables);
|
|
148
|
-
const fieldSelection = innerSelection ? getFieldsForType(innerSelection, parentType) : void 0;
|
|
148
|
+
const fieldSelection = innerSelection ? getFieldsForType(innerSelection, parentType, false) : void 0;
|
|
149
149
|
this.addFieldSubscription({
|
|
150
150
|
id: parent,
|
|
151
151
|
key,
|
|
@@ -175,7 +175,7 @@ class InMemorySubscriptions {
|
|
|
175
175
|
linkedRecord,
|
|
176
176
|
"__typename"
|
|
177
177
|
).value;
|
|
178
|
-
let targetSelection2 = getFieldsForType(childSelection, __typename);
|
|
178
|
+
let targetSelection2 = getFieldsForType(childSelection, __typename, false);
|
|
179
179
|
this.addMany({
|
|
180
180
|
parent: linkedRecord,
|
|
181
181
|
variables,
|
|
@@ -194,7 +194,7 @@ class InMemorySubscriptions {
|
|
|
194
194
|
visited.push(id);
|
|
195
195
|
const linkedIDs = [];
|
|
196
196
|
const __typename = this.cache._internal_unstable.storage.get(id, "__typename").value;
|
|
197
|
-
let targetSelection = getFieldsForType(selection, __typename);
|
|
197
|
+
let targetSelection = getFieldsForType(selection, __typename, false);
|
|
198
198
|
for (const fieldSelection of Object.values(targetSelection || {})) {
|
|
199
199
|
const key = evaluateKey(fieldSelection.keyRaw, variables);
|
|
200
200
|
this.removeSubscribers(id, key, targets);
|
|
@@ -2,8 +2,8 @@ import type { HoudiniClient } from '.';
|
|
|
2
2
|
import type { Layer } from '../cache/storage';
|
|
3
3
|
import type { ConfigFile } from '../lib/config';
|
|
4
4
|
import { Writable } from '../lib/store';
|
|
5
|
-
import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies } from '../lib/types';
|
|
6
|
-
export declare class DocumentStore<_Data extends GraphQLObject, _Input extends
|
|
5
|
+
import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies, GraphQLVariables } from '../lib/types';
|
|
6
|
+
export declare class DocumentStore<_Data extends GraphQLObject, _Input extends GraphQLVariables> extends Writable<QueryResult<_Data, _Input>> {
|
|
7
7
|
#private;
|
|
8
8
|
pendingPromise: {
|
|
9
9
|
then: (val: any) => void;
|
|
@@ -20,7 +20,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends R
|
|
|
20
20
|
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
21
21
|
cleanup(): Promise<void>;
|
|
22
22
|
}
|
|
23
|
-
declare function marshalVariables<_Data extends GraphQLObject, _Input extends
|
|
23
|
+
declare function marshalVariables<_Data extends GraphQLObject, _Input extends GraphQLVariables>(ctx: ClientPluginContext): Record<string, any>;
|
|
24
24
|
export type ClientPlugin = () => ClientHooks | null | (ClientHooks | ClientPlugin | null)[];
|
|
25
25
|
export type ClientHooks = {
|
|
26
26
|
start?: ClientPluginEnterPhase;
|
|
@@ -48,7 +48,15 @@ class DocumentStore extends Writable {
|
|
|
48
48
|
this.#plugins = pipeline ?? [
|
|
49
49
|
cachePolicy({
|
|
50
50
|
enabled: cache,
|
|
51
|
-
setFetching: (fetching2
|
|
51
|
+
setFetching: (fetching2, data) => {
|
|
52
|
+
this.update((state) => {
|
|
53
|
+
const newState = { ...state, fetching: fetching2 };
|
|
54
|
+
if (fetching2 && data) {
|
|
55
|
+
newState.data = data;
|
|
56
|
+
}
|
|
57
|
+
return newState;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
52
60
|
})(),
|
|
53
61
|
...plugins ?? []
|
|
54
62
|
];
|
|
@@ -292,7 +300,7 @@ class ClientPluginContextWrapper {
|
|
|
292
300
|
};
|
|
293
301
|
const firstInit = !ctx.stuff.inputs || !ctx.stuff.inputs.init;
|
|
294
302
|
const hasChanged = Object.keys(changed).length > 0 || firstInit;
|
|
295
|
-
if (
|
|
303
|
+
if (hasChanged) {
|
|
296
304
|
const newVariables = {
|
|
297
305
|
...ctx.stuff.inputs?.marshaled,
|
|
298
306
|
...marshalInputs({
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/// <reference path="../../../../../houdini.d.ts" />
|
|
2
|
-
import type { DocumentArtifact, GraphQLObject, NestedList } from '../lib/types';
|
|
3
|
-
import type {
|
|
2
|
+
import type { DocumentArtifact, GraphQLVariables, GraphQLObject, NestedList } from '../lib/types';
|
|
3
|
+
import type { ClientHooks, ClientPlugin } from './documentStore';
|
|
4
4
|
import { DocumentStore } from './documentStore';
|
|
5
|
-
import {
|
|
5
|
+
import type { FetchParamFn, ThrowOnErrorOperations, ThrowOnErrorParams } from './plugins';
|
|
6
6
|
export { DocumentStore, type ClientPlugin, type SendParams } from './documentStore';
|
|
7
7
|
export { fetch, mutation, query, subscription } from './plugins';
|
|
8
|
-
type
|
|
8
|
+
export type HoudiniClientConstructorArgs = {
|
|
9
9
|
url: string;
|
|
10
10
|
fetchParams?: FetchParamFn;
|
|
11
11
|
plugins?: NestedList<ClientPlugin>;
|
|
@@ -19,9 +19,10 @@ export type ObserveParams<_Data extends GraphQLObject, _Artifact extends Documen
|
|
|
19
19
|
fetching?: boolean;
|
|
20
20
|
};
|
|
21
21
|
export declare class HoudiniClient {
|
|
22
|
-
#private;
|
|
23
22
|
url: string;
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
readonly plugins: ClientPlugin[];
|
|
24
|
+
readonly throwOnError_operations: ThrowOnErrorOperations[];
|
|
25
|
+
constructor({ url, fetchParams, plugins, pipeline, throwOnError, }: HoudiniClientConstructorArgs);
|
|
26
|
+
observe<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, cache, initialValue, fetching, }: ObserveParams<_Data>): DocumentStore<_Data, _Input>;
|
|
26
27
|
}
|
|
27
28
|
export declare function createPluginHooks(plugins: ClientPlugin[]): ClientHooks[];
|
|
@@ -2,25 +2,33 @@ import { flatten } from "../lib/flatten";
|
|
|
2
2
|
import { DocumentStore } from "./documentStore";
|
|
3
3
|
import {
|
|
4
4
|
fetch as fetchPlugin,
|
|
5
|
+
fetchParams as fetchParamsPlugin,
|
|
6
|
+
fragment as fragmentPlugin,
|
|
5
7
|
mutation as mutationPlugin,
|
|
6
8
|
query as queryPlugin,
|
|
7
|
-
|
|
8
|
-
throwOnError as throwOnErrorPlugin,
|
|
9
|
-
fetchParams as fetchParamsPlugin
|
|
9
|
+
throwOnError as throwOnErrorPlugin
|
|
10
10
|
} from "./plugins";
|
|
11
11
|
import pluginsFromPlugins from "./plugins/injectedPlugins";
|
|
12
12
|
import { DocumentStore as DocumentStore2 } from "./documentStore";
|
|
13
13
|
import { fetch, mutation, query, subscription } from "./plugins";
|
|
14
14
|
class HoudiniClient {
|
|
15
15
|
url;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
plugins;
|
|
17
|
+
throwOnError_operations;
|
|
18
|
+
constructor({
|
|
19
|
+
url,
|
|
20
|
+
fetchParams,
|
|
21
|
+
plugins,
|
|
22
|
+
pipeline,
|
|
23
|
+
throwOnError
|
|
24
|
+
}) {
|
|
18
25
|
if (plugins && pipeline) {
|
|
19
26
|
throw new Error(
|
|
20
27
|
"A client cannot be given a pipeline and a list of plugins at the same time."
|
|
21
28
|
);
|
|
22
29
|
}
|
|
23
|
-
this
|
|
30
|
+
this.throwOnError_operations = throwOnError?.operations ?? [];
|
|
31
|
+
this.plugins = flatten(
|
|
24
32
|
[].concat(
|
|
25
33
|
throwOnError ? [throwOnErrorPlugin(throwOnError)] : [],
|
|
26
34
|
fetchParamsPlugin(fetchParams),
|
|
@@ -46,7 +54,7 @@ class HoudiniClient {
|
|
|
46
54
|
return new DocumentStore({
|
|
47
55
|
client: this,
|
|
48
56
|
artifact,
|
|
49
|
-
plugins: createPluginHooks(this
|
|
57
|
+
plugins: createPluginHooks(this.plugins),
|
|
50
58
|
cache,
|
|
51
59
|
initialValue,
|
|
52
60
|
fetching
|
|
@@ -3,7 +3,7 @@ import { Cache } from '../../cache/cache';
|
|
|
3
3
|
import type { ClientPlugin } from '../documentStore';
|
|
4
4
|
export declare const cachePolicy: ({ enabled, setFetching, cache: localCache, serverSideFallback, }: {
|
|
5
5
|
enabled: boolean;
|
|
6
|
-
setFetching: (val: boolean) => void;
|
|
6
|
+
setFetching: (val: boolean, data?: any) => void;
|
|
7
7
|
cache?: Cache | undefined;
|
|
8
8
|
serverSideFallback?: boolean | undefined;
|
|
9
9
|
}) => ClientPlugin;
|
|
@@ -17,7 +17,7 @@ const cachePolicy = ({
|
|
|
17
17
|
const value = localCache.read({
|
|
18
18
|
selection: artifact.selection,
|
|
19
19
|
variables: marshalVariables(ctx),
|
|
20
|
-
|
|
20
|
+
fullCheck: true
|
|
21
21
|
});
|
|
22
22
|
const allowed = !value.partial || artifact.kind === ArtifactKind.Query && artifact.partial;
|
|
23
23
|
if (policy === CachePolicy.CacheOnly) {
|
|
@@ -54,7 +54,15 @@ const cachePolicy = ({
|
|
|
54
54
|
}, 0);
|
|
55
55
|
}
|
|
56
56
|
if (!ctx.stuff?.silenceLoading) {
|
|
57
|
-
|
|
57
|
+
let fetchingState = null;
|
|
58
|
+
if (!useCache && "enableLoadingState" in artifact && artifact.enableLoadingState) {
|
|
59
|
+
fetchingState = localCache.read({
|
|
60
|
+
selection: artifact.selection,
|
|
61
|
+
variables: marshalVariables(ctx),
|
|
62
|
+
loading: true
|
|
63
|
+
}).data;
|
|
64
|
+
}
|
|
65
|
+
setFetching(!useCache, fetchingState);
|
|
58
66
|
}
|
|
59
67
|
return next(ctx);
|
|
60
68
|
},
|
|
@@ -21,6 +21,7 @@ export type FetchContext = {
|
|
|
21
21
|
export type RequestHandlerArgs = FetchContext & FetchParams;
|
|
22
22
|
export type RequestHandler<_Data = any> = (args: RequestHandlerArgs) => Promise<RequestPayload<_Data>>;
|
|
23
23
|
export type FetchParams = {
|
|
24
|
+
name: string;
|
|
24
25
|
text: string;
|
|
25
26
|
hash: string;
|
|
26
27
|
variables: {
|
|
@@ -8,6 +8,7 @@ const fetch = (target) => {
|
|
|
8
8
|
}
|
|
9
9
|
const fetch2 = ctx.fetch ?? globalThis.fetch;
|
|
10
10
|
const fetchParams = {
|
|
11
|
+
name: ctx.artifact.name,
|
|
11
12
|
text: ctx.text,
|
|
12
13
|
hash: ctx.hash,
|
|
13
14
|
variables: marshalVariables(ctx)
|
|
@@ -48,10 +49,10 @@ const defaultFetch = (url, params) => {
|
|
|
48
49
|
"Could not find configured client url. Please specify one in your HoudiniClient constructor."
|
|
49
50
|
);
|
|
50
51
|
}
|
|
51
|
-
return async ({ fetch: fetch2, text, variables }) => {
|
|
52
|
+
return async ({ fetch: fetch2, name, text, variables }) => {
|
|
52
53
|
const result = await fetch2(url, {
|
|
53
54
|
method: "POST",
|
|
54
|
-
body: JSON.stringify({ query: text, variables }),
|
|
55
|
+
body: JSON.stringify({ operationName: name, query: text, variables }),
|
|
55
56
|
...params,
|
|
56
57
|
headers: {
|
|
57
58
|
Accept: "application/graphql+json, application/json",
|
|
@@ -3,6 +3,7 @@ export declare function subscription(factory: SubscriptionHandler): import("../d
|
|
|
3
3
|
export type SubscriptionHandler = (ctx: ClientPluginContext) => SubscriptionClient;
|
|
4
4
|
export type SubscriptionClient = {
|
|
5
5
|
subscribe: (payload: {
|
|
6
|
+
operationName: string;
|
|
6
7
|
query: string;
|
|
7
8
|
variables?: {};
|
|
8
9
|
}, handlers: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { QueryResult } from '../../lib';
|
|
2
2
|
import type { ClientPlugin, ClientPluginContext } from '../documentStore';
|
|
3
|
+
export type ThrowOnErrorOperations = 'all' | 'query' | 'mutation' | 'subscription';
|
|
3
4
|
export type ThrowOnErrorParams = {
|
|
4
|
-
operations:
|
|
5
|
+
operations: ThrowOnErrorOperations[];
|
|
5
6
|
error?: (errors: NonNullable<QueryResult<any, any>['errors']>, ctx: ClientPluginContext) => unknown;
|
|
6
7
|
};
|
|
7
8
|
export declare const throwOnError: ({ operations, error }: ThrowOnErrorParams) => ClientPlugin;
|
|
@@ -24,7 +24,8 @@ function defaultConfigValues(file) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
function keyFieldsForType(configFile, type) {
|
|
27
|
-
|
|
27
|
+
const withDefault = defaultConfigValues(configFile);
|
|
28
|
+
return withDefault.types?.[type]?.keys || withDefault.defaultKeys;
|
|
28
29
|
}
|
|
29
30
|
function computeID(configFile, type, data) {
|
|
30
31
|
const fields = keyFieldsForType(configFile, type);
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { SendParams } from '../client/documentStore';
|
|
2
|
-
import { FetchParams } from './types';
|
|
3
|
-
|
|
4
|
-
export declare function cursorHandlers<_Data extends GraphQLObject, _Input extends Record<string, any>>({ artifact, storeName, fetchUpdate: parentFetchUpdate, fetch: parentFetch, getState, getVariables, getSession, }: {
|
|
2
|
+
import type { CursorHandlers, FetchFn, GraphQLObject, GraphQLVariables, QueryArtifact, QueryResult, FetchParams } from './types';
|
|
3
|
+
export declare function cursorHandlers<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, fetchUpdate: parentFetchUpdate, fetch: parentFetch, getState, getVariables, getSession, }: {
|
|
5
4
|
artifact: QueryArtifact;
|
|
6
|
-
storeName: string;
|
|
7
5
|
getState: () => _Data | null;
|
|
8
|
-
getVariables: () => _Input
|
|
6
|
+
getVariables: () => NonNullable<_Input>;
|
|
9
7
|
getSession: () => Promise<App.Session>;
|
|
10
8
|
fetch: FetchFn<_Data, _Input>;
|
|
11
9
|
fetchUpdate: (arg: SendParams, updates: string[]) => ReturnType<FetchFn<_Data, _Input>>;
|
|
12
10
|
}): CursorHandlers<_Data, _Input>;
|
|
13
|
-
export declare function offsetHandlers<_Data extends GraphQLObject, _Input extends
|
|
11
|
+
export declare function offsetHandlers<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, storeName, getState, getVariables, fetch: parentFetch, fetchUpdate: parentFetchUpdate, getSession, }: {
|
|
14
12
|
artifact: QueryArtifact;
|
|
15
13
|
fetch: FetchFn<_Data, _Input>;
|
|
16
14
|
fetchUpdate: (arg: SendParams) => ReturnType<FetchFn<_Data, _Input>>;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { getCurrentConfig } from "./config";
|
|
2
|
-
import { siteURL } from "./constants";
|
|
3
2
|
import { deepEquals } from "./deepEquals";
|
|
4
3
|
import { countPage, extractPageInfo, missingPageSizeError } from "./pageInfo";
|
|
5
4
|
import { CachePolicy } from "./types";
|
|
6
5
|
function cursorHandlers({
|
|
7
6
|
artifact,
|
|
8
|
-
storeName,
|
|
9
7
|
fetchUpdate: parentFetchUpdate,
|
|
10
8
|
fetch: parentFetch,
|
|
11
9
|
getState,
|
|
@@ -39,16 +37,6 @@ function cursorHandlers({
|
|
|
39
37
|
},
|
|
40
38
|
isSinglePage ? [] : [where === "start" ? "prepend" : "append"]
|
|
41
39
|
);
|
|
42
|
-
const resultPath = [...artifact.refetch.path];
|
|
43
|
-
if (artifact.refetch.embedded) {
|
|
44
|
-
const { targetType } = artifact.refetch;
|
|
45
|
-
if (!config.types?.[targetType]?.resolve) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
`Missing type resolve configuration for ${targetType}. For more information, see ${siteURL}/guides/pagination#paginated-fragments`
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
resultPath.unshift(config.types[targetType].resolve.queryField);
|
|
51
|
-
}
|
|
52
40
|
};
|
|
53
41
|
const getPageInfo = () => {
|
|
54
42
|
return extractPageInfo(getState(), artifact.refetch?.path ?? []);
|
|
@@ -11,7 +11,7 @@ async function marshalSelection({
|
|
|
11
11
|
if (Array.isArray(data)) {
|
|
12
12
|
return await Promise.all(data.map((val) => marshalSelection({ selection, data: val })));
|
|
13
13
|
}
|
|
14
|
-
const targetSelection = getFieldsForType(selection, data["__typename"]);
|
|
14
|
+
const targetSelection = getFieldsForType(selection, data["__typename"], false);
|
|
15
15
|
return Object.fromEntries(
|
|
16
16
|
await Promise.all(
|
|
17
17
|
Object.entries(data).map(async ([fieldName, value]) => {
|