houdini 1.1.7 → 1.2.0-next.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 +30737 -30175
- package/build/cmd-esm/index.js +30737 -30175
- 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-cjs/index.js +30791 -30254
- package/build/codegen-esm/index.js +30791 -30254
- package/build/lib/code.d.ts +11 -0
- package/build/lib/config.d.ts +5 -0
- package/build/lib/graphql.d.ts +5 -1
- package/build/lib/index.d.ts +1 -0
- package/build/lib/parse.d.ts +0 -7
- package/build/lib/types.d.ts +4 -1
- package/build/lib-cjs/index.js +29888 -29668
- package/build/lib-esm/index.js +29885 -29668
- package/build/runtime/cache/cache.d.ts +5 -6
- package/build/runtime/client/documentStore.d.ts +3 -0
- package/build/runtime/client/index.d.ts +7 -6
- 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/pageInfo.d.ts +7 -0
- package/build/runtime/lib/pagination.d.ts +27 -0
- package/build/runtime/lib/selection.d.ts +1 -1
- package/build/runtime/lib/types.d.ts +75 -3
- package/build/runtime-cjs/cache/cache.d.ts +5 -6
- package/build/runtime-cjs/cache/cache.js +78 -36
- package/build/runtime-cjs/cache/subscription.js +5 -5
- package/build/runtime-cjs/client/documentStore.d.ts +3 -0
- package/build/runtime-cjs/client/documentStore.js +20 -7
- package/build/runtime-cjs/client/index.d.ts +7 -6
- 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 +12 -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/fragment.js +8 -1
- package/build/runtime-cjs/client/plugins/query.js +2 -1
- 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/pageInfo.d.ts +7 -0
- package/build/runtime-cjs/lib/pageInfo.js +79 -0
- package/build/runtime-cjs/lib/pagination.d.ts +27 -0
- package/build/runtime-cjs/lib/pagination.js +219 -0
- 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 +75 -3
- package/build/runtime-cjs/lib/types.js +3 -0
- package/build/runtime-esm/cache/cache.d.ts +5 -6
- package/build/runtime-esm/cache/cache.js +79 -37
- package/build/runtime-esm/cache/subscription.js +5 -5
- package/build/runtime-esm/client/documentStore.d.ts +3 -0
- package/build/runtime-esm/client/documentStore.js +20 -7
- package/build/runtime-esm/client/index.d.ts +7 -6
- 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 +12 -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/fragment.js +8 -1
- package/build/runtime-esm/client/plugins/query.js +2 -1
- 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/pageInfo.d.ts +7 -0
- package/build/runtime-esm/lib/pageInfo.js +52 -0
- package/build/runtime-esm/lib/pagination.d.ts +27 -0
- package/build/runtime-esm/lib/pagination.js +194 -0
- 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 +75 -3
- package/build/runtime-esm/lib/types.js +2 -0
- package/build/test/index.d.ts +15 -0
- package/build/test-cjs/index.js +30699 -30140
- package/build/test-esm/index.js +30699 -30140
- package/build/vite-cjs/index.js +30765 -30205
- package/build/vite-esm/index.js +30765 -30205
- package/package.json +5 -1
|
@@ -21,7 +21,15 @@ __export(selection_exports, {
|
|
|
21
21
|
getFieldsForType: () => getFieldsForType
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(selection_exports);
|
|
24
|
-
function getFieldsForType(selection, __typename) {
|
|
24
|
+
function getFieldsForType(selection, __typename, loading) {
|
|
25
|
+
if (loading) {
|
|
26
|
+
if (selection.loadingTypes && selection.loadingTypes.length > 0) {
|
|
27
|
+
return deepMerge(
|
|
28
|
+
...selection.loadingTypes.map((type) => selection.abstractFields?.fields[type])
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return selection.fields ?? {};
|
|
32
|
+
}
|
|
25
33
|
let targetSelection = selection.fields || {};
|
|
26
34
|
if (selection.abstractFields && __typename) {
|
|
27
35
|
const mappedType = selection.abstractFields.typeMap[__typename];
|
|
@@ -33,6 +41,25 @@ function getFieldsForType(selection, __typename) {
|
|
|
33
41
|
}
|
|
34
42
|
return targetSelection;
|
|
35
43
|
}
|
|
44
|
+
function deepMerge(...objects) {
|
|
45
|
+
const mergedObj = {};
|
|
46
|
+
for (let obj of objects) {
|
|
47
|
+
if (!obj) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
for (let prop in obj) {
|
|
51
|
+
if (prop in obj) {
|
|
52
|
+
const val = obj[prop];
|
|
53
|
+
if (typeof val === "object" && val !== null && !Array.isArray(val)) {
|
|
54
|
+
mergedObj[prop] = deepMerge(mergedObj[prop] || {}, val);
|
|
55
|
+
} else {
|
|
56
|
+
mergedObj[prop] = val;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return mergedObj;
|
|
62
|
+
}
|
|
36
63
|
// Annotate the CommonJS export names for ESM import in node:
|
|
37
64
|
0 && (module.exports = {
|
|
38
65
|
getFieldsForType
|
|
@@ -25,6 +25,7 @@ declare global {
|
|
|
25
25
|
};
|
|
26
26
|
optimisticResponse?: GraphQLObject;
|
|
27
27
|
parentID?: string;
|
|
28
|
+
silenceLoading?: boolean;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -52,9 +53,12 @@ export type CompiledDocumentKind = ArtifactKinds;
|
|
|
52
53
|
export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
53
54
|
policy?: CachePolicies;
|
|
54
55
|
partial?: boolean;
|
|
56
|
+
enableLoadingState?: boolean;
|
|
55
57
|
};
|
|
56
58
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'>;
|
|
57
|
-
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'
|
|
59
|
+
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
60
|
+
enableLoadingState?: boolean;
|
|
61
|
+
};
|
|
58
62
|
export type SubscriptionArtifact = BaseCompiledDocument<'HoudiniSubscription'>;
|
|
59
63
|
export declare const RefetchUpdateMode: {
|
|
60
64
|
readonly append: "append";
|
|
@@ -128,12 +132,31 @@ export type GraphQLObject = {
|
|
|
128
132
|
[key: string]: GraphQLValue;
|
|
129
133
|
};
|
|
130
134
|
export type GraphQLValue = number | string | boolean | null | GraphQLObject | GraphQLValue[] | undefined;
|
|
135
|
+
export type LoadingSpec = {
|
|
136
|
+
kind: 'continue';
|
|
137
|
+
list?: {
|
|
138
|
+
depth: number;
|
|
139
|
+
count: number;
|
|
140
|
+
};
|
|
141
|
+
} | {
|
|
142
|
+
kind: 'value';
|
|
143
|
+
value?: any;
|
|
144
|
+
list?: {
|
|
145
|
+
depth: number;
|
|
146
|
+
count: number;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
131
149
|
export type SubscriptionSelection = {
|
|
132
|
-
|
|
150
|
+
loadingTypes?: string[];
|
|
151
|
+
fragments?: Record<string, {
|
|
152
|
+
arguments: ValueMap;
|
|
153
|
+
loading?: boolean;
|
|
154
|
+
}>;
|
|
133
155
|
fields?: {
|
|
134
156
|
[fieldName: string]: {
|
|
135
157
|
type: string;
|
|
136
158
|
nullable?: boolean;
|
|
159
|
+
required?: boolean;
|
|
137
160
|
keyRaw: string;
|
|
138
161
|
operations?: MutationOperation[];
|
|
139
162
|
list?: {
|
|
@@ -141,6 +164,7 @@ export type SubscriptionSelection = {
|
|
|
141
164
|
connection: boolean;
|
|
142
165
|
type: string;
|
|
143
166
|
};
|
|
167
|
+
loading?: LoadingSpec;
|
|
144
168
|
directives?: {
|
|
145
169
|
name: string;
|
|
146
170
|
arguments: ValueMap;
|
|
@@ -153,6 +177,7 @@ export type SubscriptionSelection = {
|
|
|
153
177
|
}>;
|
|
154
178
|
selection?: SubscriptionSelection;
|
|
155
179
|
abstract?: boolean;
|
|
180
|
+
abstractHasRequired?: boolean;
|
|
156
181
|
};
|
|
157
182
|
};
|
|
158
183
|
abstractFields?: {
|
|
@@ -194,9 +219,54 @@ export type RequestPayload<GraphQLObject = any> = {
|
|
|
194
219
|
};
|
|
195
220
|
export type NestedList<_Result = string> = (_Result | null | NestedList<_Result>)[];
|
|
196
221
|
export type ValueOf<Parent> = Parent[keyof Parent];
|
|
197
|
-
export declare const fragmentKey
|
|
222
|
+
export declare const fragmentKey: " $fragments";
|
|
198
223
|
export type ValueNode = VariableNode | IntValueNode | FloatValueNode | StringValueNode | BooleanValueNode | NullValueNode | EnumValueNode | ListValueNode | ObjectValueNode;
|
|
199
224
|
export type ValueMap = Record<string, ValueNode>;
|
|
225
|
+
export type FetchParams<_Input> = {
|
|
226
|
+
variables?: _Input;
|
|
227
|
+
/**
|
|
228
|
+
* The policy to use when performing the fetch. If set to CachePolicy.NetworkOnly,
|
|
229
|
+
* a request will always be sent, even if the variables are the same as the last call
|
|
230
|
+
* to fetch.
|
|
231
|
+
*/
|
|
232
|
+
policy?: CachePolicies;
|
|
233
|
+
/**
|
|
234
|
+
* An object that will be passed to the fetch function.
|
|
235
|
+
* You can do what you want with it!
|
|
236
|
+
*/
|
|
237
|
+
metadata?: App.Metadata;
|
|
238
|
+
};
|
|
239
|
+
export type FetchFn<_Data extends GraphQLObject, _Input = any> = (params?: FetchParams<_Input>) => Promise<QueryResult<_Data, _Input>>;
|
|
240
|
+
export type CursorHandlers<_Data extends GraphQLObject, _Input> = {
|
|
241
|
+
loadNextPage: (args?: {
|
|
242
|
+
first?: number;
|
|
243
|
+
after?: string;
|
|
244
|
+
fetch?: typeof globalThis.fetch;
|
|
245
|
+
metadata?: {};
|
|
246
|
+
}) => Promise<void>;
|
|
247
|
+
loadPreviousPage: (args?: {
|
|
248
|
+
last?: number;
|
|
249
|
+
before?: string;
|
|
250
|
+
fetch?: typeof globalThis.fetch;
|
|
251
|
+
metadata?: {};
|
|
252
|
+
}) => Promise<void>;
|
|
253
|
+
fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
|
|
254
|
+
};
|
|
255
|
+
export type OffsetHandlers<_Data extends GraphQLObject, _Input> = {
|
|
256
|
+
loadNextPage: (args?: {
|
|
257
|
+
limit?: number;
|
|
258
|
+
offset?: number;
|
|
259
|
+
metadata?: {};
|
|
260
|
+
fetch?: typeof globalThis.fetch;
|
|
261
|
+
}) => Promise<void>;
|
|
262
|
+
fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
|
|
263
|
+
};
|
|
264
|
+
export type PageInfo = {
|
|
265
|
+
startCursor: string | null;
|
|
266
|
+
endCursor: string | null;
|
|
267
|
+
hasNextPage: boolean;
|
|
268
|
+
hasPreviousPage: boolean;
|
|
269
|
+
};
|
|
200
270
|
interface IntValueNode {
|
|
201
271
|
readonly kind: 'IntValue';
|
|
202
272
|
readonly value: string;
|
|
@@ -241,4 +311,6 @@ interface VariableNode {
|
|
|
241
311
|
readonly kind: 'Variable';
|
|
242
312
|
readonly name: NameNode;
|
|
243
313
|
}
|
|
314
|
+
export declare const PendingValue: unique symbol;
|
|
315
|
+
export type LoadingType = typeof PendingValue;
|
|
244
316
|
export {};
|
|
@@ -26,6 +26,7 @@ __export(types_exports, {
|
|
|
26
26
|
CompiledSubscriptionKind: () => CompiledSubscriptionKind,
|
|
27
27
|
DataSource: () => DataSource,
|
|
28
28
|
PaginateMode: () => PaginateMode,
|
|
29
|
+
PendingValue: () => PendingValue,
|
|
29
30
|
RefetchUpdateMode: () => RefetchUpdateMode,
|
|
30
31
|
fragmentKey: () => fragmentKey
|
|
31
32
|
});
|
|
@@ -61,6 +62,7 @@ const DataSource = {
|
|
|
61
62
|
Ssr: "ssr"
|
|
62
63
|
};
|
|
63
64
|
const fragmentKey = " $fragments";
|
|
65
|
+
const PendingValue = Symbol("houdini_loading");
|
|
64
66
|
// Annotate the CommonJS export names for ESM import in node:
|
|
65
67
|
0 && (module.exports = {
|
|
66
68
|
ArtifactKind,
|
|
@@ -71,6 +73,7 @@ const fragmentKey = " $fragments";
|
|
|
71
73
|
CompiledSubscriptionKind,
|
|
72
74
|
DataSource,
|
|
73
75
|
PaginateMode,
|
|
76
|
+
PendingValue,
|
|
74
77
|
RefetchUpdateMode,
|
|
75
78
|
fragmentKey
|
|
76
79
|
});
|
|
@@ -3,7 +3,6 @@ import type { GraphQLObject, GraphQLValue, NestedList, SubscriptionSelection, Su
|
|
|
3
3
|
import { GarbageCollector } from './gc';
|
|
4
4
|
import type { ListCollection } from './lists';
|
|
5
5
|
import { ListManager } from './lists';
|
|
6
|
-
import { SchemaManager } from './schema';
|
|
7
6
|
import { StaleManager } from './staleManager';
|
|
8
7
|
import type { Layer, LayerID } from './storage';
|
|
9
8
|
import { InMemoryStorage } from './storage';
|
|
@@ -57,15 +56,13 @@ declare class CacheInternal {
|
|
|
57
56
|
cache: Cache;
|
|
58
57
|
lifetimes: GarbageCollector;
|
|
59
58
|
staleManager: StaleManager;
|
|
60
|
-
|
|
61
|
-
constructor({ storage, subscriptions, lists, cache, lifetimes, staleManager, schema, disabled, config, }: {
|
|
59
|
+
constructor({ storage, subscriptions, lists, cache, lifetimes, staleManager, disabled, config, }: {
|
|
62
60
|
storage: InMemoryStorage;
|
|
63
61
|
subscriptions: InMemorySubscriptions;
|
|
64
62
|
lists: ListManager;
|
|
65
63
|
cache: Cache;
|
|
66
64
|
lifetimes: GarbageCollector;
|
|
67
65
|
staleManager: StaleManager;
|
|
68
|
-
schema: SchemaManager;
|
|
69
66
|
disabled: boolean;
|
|
70
67
|
config?: ConfigFile;
|
|
71
68
|
});
|
|
@@ -87,12 +84,13 @@ declare class CacheInternal {
|
|
|
87
84
|
forceNotify?: boolean;
|
|
88
85
|
forceStale?: boolean;
|
|
89
86
|
}): FieldSelection[];
|
|
90
|
-
getSelection({ selection, parent, variables, stepsFromConnection, ignoreMasking, fullCheck, }: {
|
|
87
|
+
getSelection({ selection, parent, variables, stepsFromConnection, ignoreMasking, fullCheck, loading: generateLoading, }: {
|
|
91
88
|
selection: SubscriptionSelection;
|
|
92
89
|
parent?: string;
|
|
93
90
|
variables?: {};
|
|
94
91
|
stepsFromConnection?: number | null;
|
|
95
92
|
ignoreMasking?: boolean;
|
|
93
|
+
loading?: boolean;
|
|
96
94
|
fullCheck?: boolean;
|
|
97
95
|
}): {
|
|
98
96
|
data: GraphQLObject | null;
|
|
@@ -104,13 +102,14 @@ declare class CacheInternal {
|
|
|
104
102
|
id(type: string, id: string): string | null;
|
|
105
103
|
idFields(type: string): string[];
|
|
106
104
|
computeID(type: string, data: any): string;
|
|
107
|
-
hydrateNestedList({ fields, variables, linkedList, stepsFromConnection, ignoreMasking, fullCheck, }: {
|
|
105
|
+
hydrateNestedList({ fields, variables, linkedList, stepsFromConnection, ignoreMasking, fullCheck, loading, }: {
|
|
108
106
|
fields: SubscriptionSelection;
|
|
109
107
|
variables?: {};
|
|
110
108
|
linkedList: NestedList;
|
|
111
109
|
stepsFromConnection: number | null;
|
|
112
110
|
ignoreMasking: boolean;
|
|
113
111
|
fullCheck?: boolean;
|
|
112
|
+
loading?: boolean;
|
|
114
113
|
}): {
|
|
115
114
|
data: NestedList<GraphQLValue>;
|
|
116
115
|
partial: boolean;
|
|
@@ -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
|
}
|
|
@@ -447,32 +438,49 @@ class CacheInternal {
|
|
|
447
438
|
variables,
|
|
448
439
|
stepsFromConnection = null,
|
|
449
440
|
ignoreMasking,
|
|
450
|
-
fullCheck = false
|
|
441
|
+
fullCheck = false,
|
|
442
|
+
loading: generateLoading
|
|
451
443
|
}) {
|
|
452
444
|
if (parent === null) {
|
|
453
445
|
return { data: null, partial: false, stale: false, hasData: true };
|
|
454
446
|
}
|
|
455
447
|
const target = {};
|
|
456
448
|
if (selection.fragments) {
|
|
457
|
-
target[fragmentKey] =
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
+
};
|
|
466
464
|
}
|
|
467
465
|
let hasData = !!selection.fragments;
|
|
468
466
|
let partial = false;
|
|
469
467
|
let cascadeNull = false;
|
|
470
468
|
let stale = false;
|
|
471
469
|
const typename = this.storage.get(parent, "__typename").value;
|
|
472
|
-
let targetSelection = getFieldsForType(selection, typename);
|
|
470
|
+
let targetSelection = getFieldsForType(selection, typename, !!generateLoading);
|
|
473
471
|
for (const [
|
|
474
472
|
attributeName,
|
|
475
|
-
{
|
|
473
|
+
{
|
|
474
|
+
type,
|
|
475
|
+
keyRaw,
|
|
476
|
+
selection: fieldSelection,
|
|
477
|
+
nullable,
|
|
478
|
+
list,
|
|
479
|
+
visible,
|
|
480
|
+
directives,
|
|
481
|
+
loading: fieldLoading,
|
|
482
|
+
abstractHasRequired
|
|
483
|
+
}
|
|
476
484
|
] of Object.entries(targetSelection)) {
|
|
477
485
|
if (!visible && !ignoreMasking && !fullCheck) {
|
|
478
486
|
continue;
|
|
@@ -495,11 +503,17 @@ class CacheInternal {
|
|
|
495
503
|
}
|
|
496
504
|
const fieldTarget = visible || ignoreMasking ? target : {};
|
|
497
505
|
const key = evaluateKey(keyRaw, variables);
|
|
498
|
-
|
|
506
|
+
if (generateLoading && !fieldLoading) {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
let { value } = this.storage.get(parent, key);
|
|
499
510
|
const dt_field = this.staleManager.getFieldTime(parent, key);
|
|
500
511
|
if (dt_field === null) {
|
|
501
512
|
stale = true;
|
|
502
513
|
}
|
|
514
|
+
if (generateLoading) {
|
|
515
|
+
value = void 0;
|
|
516
|
+
}
|
|
503
517
|
let nextStep = stepsFromConnection;
|
|
504
518
|
if (nextStep !== null) {
|
|
505
519
|
if (nextStep >= 2) {
|
|
@@ -515,7 +529,10 @@ class CacheInternal {
|
|
|
515
529
|
if (typeof value === "undefined" && !embeddedCursor) {
|
|
516
530
|
partial = true;
|
|
517
531
|
}
|
|
518
|
-
if (
|
|
532
|
+
if (generateLoading && fieldLoading?.kind === "value") {
|
|
533
|
+
fieldTarget[attributeName] = PendingValue;
|
|
534
|
+
hasData = true;
|
|
535
|
+
} else if (!generateLoading && typeof value === "undefined" || value === null) {
|
|
519
536
|
fieldTarget[attributeName] = null;
|
|
520
537
|
if (typeof value !== "undefined") {
|
|
521
538
|
hasData = true;
|
|
@@ -535,7 +552,8 @@ class CacheInternal {
|
|
|
535
552
|
linkedList: value,
|
|
536
553
|
stepsFromConnection: nextStep,
|
|
537
554
|
ignoreMasking: !!ignoreMasking,
|
|
538
|
-
fullCheck
|
|
555
|
+
fullCheck,
|
|
556
|
+
loading: generateLoading
|
|
539
557
|
});
|
|
540
558
|
fieldTarget[attributeName] = listValue.data;
|
|
541
559
|
if (listValue.partial) {
|
|
@@ -554,7 +572,8 @@ class CacheInternal {
|
|
|
554
572
|
variables,
|
|
555
573
|
stepsFromConnection: nextStep,
|
|
556
574
|
ignoreMasking,
|
|
557
|
-
fullCheck
|
|
575
|
+
fullCheck,
|
|
576
|
+
loading: generateLoading
|
|
558
577
|
});
|
|
559
578
|
fieldTarget[attributeName] = objectFields.data;
|
|
560
579
|
if (objectFields.partial) {
|
|
@@ -567,13 +586,27 @@ class CacheInternal {
|
|
|
567
586
|
hasData = true;
|
|
568
587
|
}
|
|
569
588
|
}
|
|
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
|
+
}
|
|
570
597
|
if (fieldTarget[attributeName] === null && !nullable && !embeddedCursor) {
|
|
571
|
-
|
|
598
|
+
if (abstractHasRequired) {
|
|
599
|
+
target[attributeName] = {
|
|
600
|
+
__typename: "@required field missing; don't match this"
|
|
601
|
+
};
|
|
602
|
+
} else {
|
|
603
|
+
cascadeNull = true;
|
|
604
|
+
}
|
|
572
605
|
}
|
|
573
606
|
}
|
|
574
607
|
return {
|
|
575
608
|
data: cascadeNull ? null : target,
|
|
576
|
-
partial: hasData && partial,
|
|
609
|
+
partial: !generateLoading && hasData && partial,
|
|
577
610
|
stale: hasData && stale,
|
|
578
611
|
hasData
|
|
579
612
|
};
|
|
@@ -600,7 +633,8 @@ class CacheInternal {
|
|
|
600
633
|
linkedList,
|
|
601
634
|
stepsFromConnection,
|
|
602
635
|
ignoreMasking,
|
|
603
|
-
fullCheck
|
|
636
|
+
fullCheck,
|
|
637
|
+
loading
|
|
604
638
|
}) {
|
|
605
639
|
const result = [];
|
|
606
640
|
let partialData = false;
|
|
@@ -614,7 +648,8 @@ class CacheInternal {
|
|
|
614
648
|
linkedList: entry,
|
|
615
649
|
stepsFromConnection,
|
|
616
650
|
ignoreMasking,
|
|
617
|
-
fullCheck
|
|
651
|
+
fullCheck,
|
|
652
|
+
loading
|
|
618
653
|
});
|
|
619
654
|
result.push(nestedValue.data);
|
|
620
655
|
if (nestedValue.partial) {
|
|
@@ -637,7 +672,8 @@ class CacheInternal {
|
|
|
637
672
|
variables,
|
|
638
673
|
stepsFromConnection,
|
|
639
674
|
ignoreMasking,
|
|
640
|
-
fullCheck
|
|
675
|
+
fullCheck,
|
|
676
|
+
loading
|
|
641
677
|
});
|
|
642
678
|
result.push(data);
|
|
643
679
|
if (partial) {
|
|
@@ -744,6 +780,12 @@ function evaluateFragmentVariables(variables, args) {
|
|
|
744
780
|
Object.entries(variables).map(([key, value]) => [key, fragmentVariableValue(value, args)])
|
|
745
781
|
);
|
|
746
782
|
}
|
|
783
|
+
function wrapInLists(target, count = 0) {
|
|
784
|
+
if (count === 0) {
|
|
785
|
+
return target;
|
|
786
|
+
}
|
|
787
|
+
return wrapInLists([target], count - 1);
|
|
788
|
+
}
|
|
747
789
|
function fragmentVariableValue(value, args) {
|
|
748
790
|
if (value.kind === "StringValue") {
|
|
749
791
|
return value.value;
|
|
@@ -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);
|
|
@@ -5,6 +5,9 @@ import { Writable } from '../lib/store';
|
|
|
5
5
|
import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies } from '../lib/types';
|
|
6
6
|
export declare class DocumentStore<_Data extends GraphQLObject, _Input extends Record<string, any>> extends Writable<QueryResult<_Data, _Input>> {
|
|
7
7
|
#private;
|
|
8
|
+
pendingPromise: {
|
|
9
|
+
then: (val: any) => void;
|
|
10
|
+
} | null;
|
|
8
11
|
constructor({ artifact, plugins, pipeline, client, cache, initialValue, fetching, }: {
|
|
9
12
|
artifact: DocumentArtifact;
|
|
10
13
|
plugins?: ClientHooks[];
|
|
@@ -15,6 +15,7 @@ class DocumentStore extends Writable {
|
|
|
15
15
|
#plugins;
|
|
16
16
|
#lastVariables;
|
|
17
17
|
#lastContext = null;
|
|
18
|
+
pendingPromise = null;
|
|
18
19
|
constructor({
|
|
19
20
|
artifact,
|
|
20
21
|
plugins,
|
|
@@ -47,7 +48,15 @@ class DocumentStore extends Writable {
|
|
|
47
48
|
this.#plugins = pipeline ?? [
|
|
48
49
|
cachePolicy({
|
|
49
50
|
enabled: cache,
|
|
50
|
-
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
|
+
}
|
|
51
60
|
})(),
|
|
52
61
|
...plugins ?? []
|
|
53
62
|
];
|
|
@@ -87,7 +96,7 @@ class DocumentStore extends Writable {
|
|
|
87
96
|
const draft = context.draft();
|
|
88
97
|
draft.variables = variables ?? null;
|
|
89
98
|
context = context.apply(draft, false);
|
|
90
|
-
|
|
99
|
+
const promise = new Promise((resolve, reject) => {
|
|
91
100
|
const state = {
|
|
92
101
|
setup,
|
|
93
102
|
currentStep: 0,
|
|
@@ -96,12 +105,17 @@ class DocumentStore extends Writable {
|
|
|
96
105
|
promise: {
|
|
97
106
|
resolved: false,
|
|
98
107
|
resolve,
|
|
99
|
-
reject
|
|
108
|
+
reject,
|
|
109
|
+
then: (...args) => promise.then(...args)
|
|
100
110
|
},
|
|
101
111
|
context
|
|
102
112
|
};
|
|
113
|
+
if (this.pendingPromise === null) {
|
|
114
|
+
this.pendingPromise = state.promise;
|
|
115
|
+
}
|
|
103
116
|
this.#step("forward", state);
|
|
104
117
|
});
|
|
118
|
+
return await promise;
|
|
105
119
|
}
|
|
106
120
|
async cleanup() {
|
|
107
121
|
for (const plugin of this.#plugins) {
|
|
@@ -220,16 +234,15 @@ class DocumentStore extends Writable {
|
|
|
220
234
|
value
|
|
221
235
|
);
|
|
222
236
|
}
|
|
237
|
+
if (!ctx.silenceEcho || value.data !== this.state.data) {
|
|
238
|
+
this.set(value);
|
|
239
|
+
}
|
|
223
240
|
if (!ctx.promise.resolved) {
|
|
224
241
|
ctx.promise.resolve(value);
|
|
225
242
|
ctx.promise.resolved = true;
|
|
226
243
|
}
|
|
227
244
|
this.#lastContext = ctx.context.draft();
|
|
228
245
|
this.#lastVariables = this.#lastContext.stuff.inputs.marshaled;
|
|
229
|
-
if (ctx.silenceEcho && value.data === this.state.data) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
this.set(value);
|
|
233
246
|
}
|
|
234
247
|
}
|
|
235
248
|
class ClientPluginContextWrapper {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/// <reference path="../../../../../houdini.d.ts" />
|
|
2
2
|
import type { DocumentArtifact, GraphQLObject, NestedList } from '../lib/types';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ClientHooks, ClientPlugin } from './documentStore';
|
|
4
4
|
import { DocumentStore } from './documentStore';
|
|
5
|
-
import {
|
|
6
|
-
export { DocumentStore, type ClientPlugin } from './documentStore';
|
|
5
|
+
import type { FetchParamFn, ThrowOnErrorOperations, ThrowOnErrorParams } from './plugins';
|
|
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
|
-
|
|
23
|
+
readonly plugins: ClientPlugin[];
|
|
24
|
+
readonly throwOnError_operations: ThrowOnErrorOperations[];
|
|
25
|
+
constructor({ url, fetchParams, plugins, pipeline, throwOnError, }: HoudiniClientConstructorArgs);
|
|
25
26
|
observe<_Data extends GraphQLObject, _Input extends Record<string, any>>({ artifact, cache, initialValue, fetching, }: ObserveParams<_Data>): DocumentStore<_Data, _Input>;
|
|
26
27
|
}
|
|
27
28
|
export declare function createPluginHooks(plugins: ClientPlugin[]): ClientHooks[];
|