houdini 1.2.61 → 1.2.62
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/build/cmd-cjs/index.js +35 -3
- package/build/cmd-esm/index.js +35 -3
- package/build/codegen-cjs/index.js +30 -1
- package/build/codegen-esm/index.js +30 -1
- package/build/lib/config.d.ts +1 -0
- package/build/lib-cjs/index.js +34 -3
- package/build/lib-esm/index.js +34 -3
- package/build/runtime/client/documentStore.d.ts +4 -1
- package/build/runtime/lib/types.d.ts +4 -2
- package/build/runtime-cjs/client/documentStore.d.ts +4 -1
- package/build/runtime-cjs/client/documentStore.js +27 -2
- package/build/runtime-cjs/client/plugins/fetch.js +4 -1
- package/build/runtime-cjs/lib/pagination.js +23 -9
- package/build/runtime-cjs/lib/types.d.ts +4 -2
- package/build/runtime-esm/client/documentStore.d.ts +4 -1
- package/build/runtime-esm/client/documentStore.js +27 -2
- package/build/runtime-esm/client/plugins/fetch.js +4 -1
- package/build/runtime-esm/lib/pagination.js +24 -10
- package/build/runtime-esm/lib/types.d.ts +4 -2
- package/build/test-cjs/index.js +33 -1
- package/build/test-esm/index.js +33 -1
- package/build/vite-cjs/index.js +33 -1
- package/build/vite-esm/index.js +33 -1
- package/package.json +1 -1
package/build/cmd-cjs/index.js
CHANGED
|
@@ -67974,6 +67974,9 @@ var Config = class {
|
|
|
67974
67974
|
get listDirective() {
|
|
67975
67975
|
return "list";
|
|
67976
67976
|
}
|
|
67977
|
+
get dedupeDirective() {
|
|
67978
|
+
return "dedupe";
|
|
67979
|
+
}
|
|
67977
67980
|
get optimisticKeyDirective() {
|
|
67978
67981
|
return "optimisticKey";
|
|
67979
67982
|
}
|
|
@@ -70654,7 +70657,17 @@ async function paginate(config, documents) {
|
|
|
70654
70657
|
);
|
|
70655
70658
|
return {
|
|
70656
70659
|
...node,
|
|
70657
|
-
variableDefinitions: finalVariables
|
|
70660
|
+
variableDefinitions: finalVariables,
|
|
70661
|
+
directives: [
|
|
70662
|
+
...node.directives || [],
|
|
70663
|
+
{
|
|
70664
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
70665
|
+
name: {
|
|
70666
|
+
kind: graphql13.Kind.NAME,
|
|
70667
|
+
value: config.dedupeDirective
|
|
70668
|
+
}
|
|
70669
|
+
}
|
|
70670
|
+
]
|
|
70658
70671
|
};
|
|
70659
70672
|
},
|
|
70660
70673
|
FragmentDefinition(node) {
|
|
@@ -71977,6 +71990,7 @@ function artifactGenerator(stats) {
|
|
|
71977
71990
|
let rootType = "";
|
|
71978
71991
|
let selectionSet;
|
|
71979
71992
|
let originalSelectionSet = null;
|
|
71993
|
+
let dedupe;
|
|
71980
71994
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
71981
71995
|
(definition) => definition.kind === "FragmentDefinition"
|
|
71982
71996
|
).reduce(
|
|
@@ -72001,6 +72015,15 @@ function artifactGenerator(stats) {
|
|
|
72001
72015
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
72002
72016
|
});
|
|
72003
72017
|
}
|
|
72018
|
+
const dedupeDirective = operation.directives?.find(
|
|
72019
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
72020
|
+
);
|
|
72021
|
+
if (dedupeDirective) {
|
|
72022
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
72023
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
72024
|
+
);
|
|
72025
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
72026
|
+
}
|
|
72004
72027
|
selectionSet = operation.selectionSet;
|
|
72005
72028
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
72006
72029
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -72078,6 +72101,9 @@ function artifactGenerator(stats) {
|
|
|
72078
72101
|
};
|
|
72079
72102
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
72080
72103
|
artifact.hash = hash_value;
|
|
72104
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
72105
|
+
artifact.dedupe = dedupe;
|
|
72106
|
+
}
|
|
72081
72107
|
applyMask(
|
|
72082
72108
|
config,
|
|
72083
72109
|
artifact.selection,
|
|
@@ -75663,6 +75689,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
75663
75689
|
"""
|
|
75664
75690
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
75665
75691
|
|
|
75692
|
+
"""
|
|
75693
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
75694
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
75695
|
+
"""
|
|
75696
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
75697
|
+
|
|
75666
75698
|
"""
|
|
75667
75699
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
75668
75700
|
"""
|
|
@@ -78412,12 +78444,12 @@ async function packageJSON(targetPath, frameworkInfo) {
|
|
|
78412
78444
|
}
|
|
78413
78445
|
packageJSON2.devDependencies = {
|
|
78414
78446
|
...packageJSON2.devDependencies,
|
|
78415
|
-
houdini: "^1.2.
|
|
78447
|
+
houdini: "^1.2.62"
|
|
78416
78448
|
};
|
|
78417
78449
|
if (frameworkInfo.framework === "svelte" || frameworkInfo.framework === "kit") {
|
|
78418
78450
|
packageJSON2.devDependencies = {
|
|
78419
78451
|
...packageJSON2.devDependencies,
|
|
78420
|
-
"houdini-svelte": "^1.2.
|
|
78452
|
+
"houdini-svelte": "^1.2.62"
|
|
78421
78453
|
};
|
|
78422
78454
|
} else {
|
|
78423
78455
|
throw new Error(`Unmanaged framework: "${JSON.stringify(frameworkInfo)}"`);
|
package/build/cmd-esm/index.js
CHANGED
|
@@ -67979,6 +67979,9 @@ var Config = class {
|
|
|
67979
67979
|
get listDirective() {
|
|
67980
67980
|
return "list";
|
|
67981
67981
|
}
|
|
67982
|
+
get dedupeDirective() {
|
|
67983
|
+
return "dedupe";
|
|
67984
|
+
}
|
|
67982
67985
|
get optimisticKeyDirective() {
|
|
67983
67986
|
return "optimisticKey";
|
|
67984
67987
|
}
|
|
@@ -70659,7 +70662,17 @@ async function paginate(config, documents) {
|
|
|
70659
70662
|
);
|
|
70660
70663
|
return {
|
|
70661
70664
|
...node,
|
|
70662
|
-
variableDefinitions: finalVariables
|
|
70665
|
+
variableDefinitions: finalVariables,
|
|
70666
|
+
directives: [
|
|
70667
|
+
...node.directives || [],
|
|
70668
|
+
{
|
|
70669
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
70670
|
+
name: {
|
|
70671
|
+
kind: graphql13.Kind.NAME,
|
|
70672
|
+
value: config.dedupeDirective
|
|
70673
|
+
}
|
|
70674
|
+
}
|
|
70675
|
+
]
|
|
70663
70676
|
};
|
|
70664
70677
|
},
|
|
70665
70678
|
FragmentDefinition(node) {
|
|
@@ -71982,6 +71995,7 @@ function artifactGenerator(stats) {
|
|
|
71982
71995
|
let rootType = "";
|
|
71983
71996
|
let selectionSet;
|
|
71984
71997
|
let originalSelectionSet = null;
|
|
71998
|
+
let dedupe;
|
|
71985
71999
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
71986
72000
|
(definition) => definition.kind === "FragmentDefinition"
|
|
71987
72001
|
).reduce(
|
|
@@ -72006,6 +72020,15 @@ function artifactGenerator(stats) {
|
|
|
72006
72020
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
72007
72021
|
});
|
|
72008
72022
|
}
|
|
72023
|
+
const dedupeDirective = operation.directives?.find(
|
|
72024
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
72025
|
+
);
|
|
72026
|
+
if (dedupeDirective) {
|
|
72027
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
72028
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
72029
|
+
);
|
|
72030
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
72031
|
+
}
|
|
72009
72032
|
selectionSet = operation.selectionSet;
|
|
72010
72033
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
72011
72034
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -72083,6 +72106,9 @@ function artifactGenerator(stats) {
|
|
|
72083
72106
|
};
|
|
72084
72107
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
72085
72108
|
artifact.hash = hash_value;
|
|
72109
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
72110
|
+
artifact.dedupe = dedupe;
|
|
72111
|
+
}
|
|
72086
72112
|
applyMask(
|
|
72087
72113
|
config,
|
|
72088
72114
|
artifact.selection,
|
|
@@ -75668,6 +75694,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
75668
75694
|
"""
|
|
75669
75695
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
75670
75696
|
|
|
75697
|
+
"""
|
|
75698
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
75699
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
75700
|
+
"""
|
|
75701
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
75702
|
+
|
|
75671
75703
|
"""
|
|
75672
75704
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
75673
75705
|
"""
|
|
@@ -78417,12 +78449,12 @@ async function packageJSON(targetPath, frameworkInfo) {
|
|
|
78417
78449
|
}
|
|
78418
78450
|
packageJSON2.devDependencies = {
|
|
78419
78451
|
...packageJSON2.devDependencies,
|
|
78420
|
-
houdini: "^1.2.
|
|
78452
|
+
houdini: "^1.2.62"
|
|
78421
78453
|
};
|
|
78422
78454
|
if (frameworkInfo.framework === "svelte" || frameworkInfo.framework === "kit") {
|
|
78423
78455
|
packageJSON2.devDependencies = {
|
|
78424
78456
|
...packageJSON2.devDependencies,
|
|
78425
|
-
"houdini-svelte": "^1.2.
|
|
78457
|
+
"houdini-svelte": "^1.2.62"
|
|
78426
78458
|
};
|
|
78427
78459
|
} else {
|
|
78428
78460
|
throw new Error(`Unmanaged framework: "${JSON.stringify(frameworkInfo)}"`);
|
|
@@ -58855,7 +58855,17 @@ async function paginate(config, documents) {
|
|
|
58855
58855
|
);
|
|
58856
58856
|
return {
|
|
58857
58857
|
...node,
|
|
58858
|
-
variableDefinitions: finalVariables
|
|
58858
|
+
variableDefinitions: finalVariables,
|
|
58859
|
+
directives: [
|
|
58860
|
+
...node.directives || [],
|
|
58861
|
+
{
|
|
58862
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
58863
|
+
name: {
|
|
58864
|
+
kind: graphql13.Kind.NAME,
|
|
58865
|
+
value: config.dedupeDirective
|
|
58866
|
+
}
|
|
58867
|
+
}
|
|
58868
|
+
]
|
|
58859
58869
|
};
|
|
58860
58870
|
},
|
|
58861
58871
|
FragmentDefinition(node) {
|
|
@@ -60178,6 +60188,7 @@ function artifactGenerator(stats) {
|
|
|
60178
60188
|
let rootType = "";
|
|
60179
60189
|
let selectionSet;
|
|
60180
60190
|
let originalSelectionSet = null;
|
|
60191
|
+
let dedupe;
|
|
60181
60192
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
60182
60193
|
(definition) => definition.kind === "FragmentDefinition"
|
|
60183
60194
|
).reduce(
|
|
@@ -60202,6 +60213,15 @@ function artifactGenerator(stats) {
|
|
|
60202
60213
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
60203
60214
|
});
|
|
60204
60215
|
}
|
|
60216
|
+
const dedupeDirective = operation.directives?.find(
|
|
60217
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
60218
|
+
);
|
|
60219
|
+
if (dedupeDirective) {
|
|
60220
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
60221
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
60222
|
+
);
|
|
60223
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
60224
|
+
}
|
|
60205
60225
|
selectionSet = operation.selectionSet;
|
|
60206
60226
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
60207
60227
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -60279,6 +60299,9 @@ function artifactGenerator(stats) {
|
|
|
60279
60299
|
};
|
|
60280
60300
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
60281
60301
|
artifact.hash = hash_value;
|
|
60302
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
60303
|
+
artifact.dedupe = dedupe;
|
|
60304
|
+
}
|
|
60282
60305
|
applyMask(
|
|
60283
60306
|
config,
|
|
60284
60307
|
artifact.selection,
|
|
@@ -63864,6 +63887,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
63864
63887
|
"""
|
|
63865
63888
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
63866
63889
|
|
|
63890
|
+
"""
|
|
63891
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
63892
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
63893
|
+
"""
|
|
63894
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
63895
|
+
|
|
63867
63896
|
"""
|
|
63868
63897
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
63869
63898
|
"""
|
|
@@ -58854,7 +58854,17 @@ async function paginate(config, documents) {
|
|
|
58854
58854
|
);
|
|
58855
58855
|
return {
|
|
58856
58856
|
...node,
|
|
58857
|
-
variableDefinitions: finalVariables
|
|
58857
|
+
variableDefinitions: finalVariables,
|
|
58858
|
+
directives: [
|
|
58859
|
+
...node.directives || [],
|
|
58860
|
+
{
|
|
58861
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
58862
|
+
name: {
|
|
58863
|
+
kind: graphql13.Kind.NAME,
|
|
58864
|
+
value: config.dedupeDirective
|
|
58865
|
+
}
|
|
58866
|
+
}
|
|
58867
|
+
]
|
|
58858
58868
|
};
|
|
58859
58869
|
},
|
|
58860
58870
|
FragmentDefinition(node) {
|
|
@@ -60177,6 +60187,7 @@ function artifactGenerator(stats) {
|
|
|
60177
60187
|
let rootType = "";
|
|
60178
60188
|
let selectionSet;
|
|
60179
60189
|
let originalSelectionSet = null;
|
|
60190
|
+
let dedupe;
|
|
60180
60191
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
60181
60192
|
(definition) => definition.kind === "FragmentDefinition"
|
|
60182
60193
|
).reduce(
|
|
@@ -60201,6 +60212,15 @@ function artifactGenerator(stats) {
|
|
|
60201
60212
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
60202
60213
|
});
|
|
60203
60214
|
}
|
|
60215
|
+
const dedupeDirective = operation.directives?.find(
|
|
60216
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
60217
|
+
);
|
|
60218
|
+
if (dedupeDirective) {
|
|
60219
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
60220
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
60221
|
+
);
|
|
60222
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
60223
|
+
}
|
|
60204
60224
|
selectionSet = operation.selectionSet;
|
|
60205
60225
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
60206
60226
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -60278,6 +60298,9 @@ function artifactGenerator(stats) {
|
|
|
60278
60298
|
};
|
|
60279
60299
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
60280
60300
|
artifact.hash = hash_value;
|
|
60301
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
60302
|
+
artifact.dedupe = dedupe;
|
|
60303
|
+
}
|
|
60281
60304
|
applyMask(
|
|
60282
60305
|
config,
|
|
60283
60306
|
artifact.selection,
|
|
@@ -63863,6 +63886,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
63863
63886
|
"""
|
|
63864
63887
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
63865
63888
|
|
|
63889
|
+
"""
|
|
63890
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
63891
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
63892
|
+
"""
|
|
63893
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
63894
|
+
|
|
63866
63895
|
"""
|
|
63867
63896
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
63868
63897
|
"""
|
package/build/lib/config.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ export declare class Config {
|
|
|
102
102
|
get maskEnableDirective(): string;
|
|
103
103
|
get maskDisableDirective(): string;
|
|
104
104
|
get listDirective(): string;
|
|
105
|
+
get dedupeDirective(): string;
|
|
105
106
|
get optimisticKeyDirective(): string;
|
|
106
107
|
get listPrependDirective(): string;
|
|
107
108
|
get listAppendDirective(): string;
|
package/build/lib-cjs/index.js
CHANGED
|
@@ -66193,7 +66193,10 @@ var fetch2 = (target) => {
|
|
|
66193
66193
|
const result = await fetchFn({
|
|
66194
66194
|
fetch: (url, args) => {
|
|
66195
66195
|
const newArgs = handleMultipart(fetchParams2, args) ?? args;
|
|
66196
|
-
return fetch3(url,
|
|
66196
|
+
return fetch3(url, {
|
|
66197
|
+
...newArgs,
|
|
66198
|
+
signal: ctx.abortController.signal
|
|
66199
|
+
});
|
|
66197
66200
|
},
|
|
66198
66201
|
metadata: ctx.metadata,
|
|
66199
66202
|
session: ctx.session || {},
|
|
@@ -67038,6 +67041,7 @@ var steps = {
|
|
|
67038
67041
|
forward: ["start", "beforeNetwork", "network"],
|
|
67039
67042
|
backwards: ["end", "afterNetwork"]
|
|
67040
67043
|
};
|
|
67044
|
+
var inflightRequests = {};
|
|
67041
67045
|
var DocumentStore = class extends Writable {
|
|
67042
67046
|
artifact;
|
|
67043
67047
|
#client;
|
|
@@ -67047,6 +67051,9 @@ var DocumentStore = class extends Writable {
|
|
|
67047
67051
|
#lastContext = null;
|
|
67048
67052
|
pendingPromise = null;
|
|
67049
67053
|
serverSideFallback;
|
|
67054
|
+
controllerKey(variables) {
|
|
67055
|
+
return this.artifact.name;
|
|
67056
|
+
}
|
|
67050
67057
|
constructor({
|
|
67051
67058
|
artifact,
|
|
67052
67059
|
plugins: plugins2,
|
|
@@ -67104,9 +67111,23 @@ var DocumentStore = class extends Writable {
|
|
|
67104
67111
|
stuff,
|
|
67105
67112
|
cacheParams,
|
|
67106
67113
|
setup = false,
|
|
67107
|
-
silenceEcho = false
|
|
67114
|
+
silenceEcho = false,
|
|
67115
|
+
abortController = new AbortController()
|
|
67108
67116
|
} = {}) {
|
|
67117
|
+
if ("dedupe" in this.artifact) {
|
|
67118
|
+
if (inflightRequests[this.controllerKey(variables)]) {
|
|
67119
|
+
if (this.artifact.dedupe === "first") {
|
|
67120
|
+
inflightRequests[this.controllerKey(variables)].abort();
|
|
67121
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
67122
|
+
} else {
|
|
67123
|
+
abortController.abort();
|
|
67124
|
+
}
|
|
67125
|
+
} else {
|
|
67126
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
67127
|
+
}
|
|
67128
|
+
}
|
|
67109
67129
|
let context = new ClientPluginContextWrapper({
|
|
67130
|
+
abortController,
|
|
67110
67131
|
config: this.#configFile,
|
|
67111
67132
|
name: this.artifact.name,
|
|
67112
67133
|
text: this.artifact.raw,
|
|
@@ -67150,7 +67171,9 @@ var DocumentStore = class extends Writable {
|
|
|
67150
67171
|
}
|
|
67151
67172
|
this.#step("forward", state);
|
|
67152
67173
|
});
|
|
67153
|
-
|
|
67174
|
+
const response = await promise;
|
|
67175
|
+
delete inflightRequests[this.controllerKey(variables)];
|
|
67176
|
+
return response;
|
|
67154
67177
|
}
|
|
67155
67178
|
async cleanup() {
|
|
67156
67179
|
for (const plugin2 of this.#plugins) {
|
|
@@ -67259,6 +67282,11 @@ var DocumentStore = class extends Writable {
|
|
|
67259
67282
|
};
|
|
67260
67283
|
}
|
|
67261
67284
|
try {
|
|
67285
|
+
if (draft.abortController.signal.aborted) {
|
|
67286
|
+
const abortError = new Error("aborted");
|
|
67287
|
+
abortError.name = "AbortError";
|
|
67288
|
+
throw abortError;
|
|
67289
|
+
}
|
|
67262
67290
|
const result = target(draft, handlers);
|
|
67263
67291
|
result?.catch((err) => {
|
|
67264
67292
|
this.#step("error", { ...ctx, index: index - 1 }, err);
|
|
@@ -68241,6 +68269,9 @@ var Config = class {
|
|
|
68241
68269
|
get listDirective() {
|
|
68242
68270
|
return "list";
|
|
68243
68271
|
}
|
|
68272
|
+
get dedupeDirective() {
|
|
68273
|
+
return "dedupe";
|
|
68274
|
+
}
|
|
68244
68275
|
get optimisticKeyDirective() {
|
|
68245
68276
|
return "optimisticKey";
|
|
68246
68277
|
}
|
package/build/lib-esm/index.js
CHANGED
|
@@ -66108,7 +66108,10 @@ var fetch2 = (target) => {
|
|
|
66108
66108
|
const result = await fetchFn({
|
|
66109
66109
|
fetch: (url, args) => {
|
|
66110
66110
|
const newArgs = handleMultipart(fetchParams2, args) ?? args;
|
|
66111
|
-
return fetch3(url,
|
|
66111
|
+
return fetch3(url, {
|
|
66112
|
+
...newArgs,
|
|
66113
|
+
signal: ctx.abortController.signal
|
|
66114
|
+
});
|
|
66112
66115
|
},
|
|
66113
66116
|
metadata: ctx.metadata,
|
|
66114
66117
|
session: ctx.session || {},
|
|
@@ -66953,6 +66956,7 @@ var steps = {
|
|
|
66953
66956
|
forward: ["start", "beforeNetwork", "network"],
|
|
66954
66957
|
backwards: ["end", "afterNetwork"]
|
|
66955
66958
|
};
|
|
66959
|
+
var inflightRequests = {};
|
|
66956
66960
|
var DocumentStore = class extends Writable {
|
|
66957
66961
|
artifact;
|
|
66958
66962
|
#client;
|
|
@@ -66962,6 +66966,9 @@ var DocumentStore = class extends Writable {
|
|
|
66962
66966
|
#lastContext = null;
|
|
66963
66967
|
pendingPromise = null;
|
|
66964
66968
|
serverSideFallback;
|
|
66969
|
+
controllerKey(variables) {
|
|
66970
|
+
return this.artifact.name;
|
|
66971
|
+
}
|
|
66965
66972
|
constructor({
|
|
66966
66973
|
artifact,
|
|
66967
66974
|
plugins: plugins2,
|
|
@@ -67019,9 +67026,23 @@ var DocumentStore = class extends Writable {
|
|
|
67019
67026
|
stuff,
|
|
67020
67027
|
cacheParams,
|
|
67021
67028
|
setup = false,
|
|
67022
|
-
silenceEcho = false
|
|
67029
|
+
silenceEcho = false,
|
|
67030
|
+
abortController = new AbortController()
|
|
67023
67031
|
} = {}) {
|
|
67032
|
+
if ("dedupe" in this.artifact) {
|
|
67033
|
+
if (inflightRequests[this.controllerKey(variables)]) {
|
|
67034
|
+
if (this.artifact.dedupe === "first") {
|
|
67035
|
+
inflightRequests[this.controllerKey(variables)].abort();
|
|
67036
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
67037
|
+
} else {
|
|
67038
|
+
abortController.abort();
|
|
67039
|
+
}
|
|
67040
|
+
} else {
|
|
67041
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
67042
|
+
}
|
|
67043
|
+
}
|
|
67024
67044
|
let context = new ClientPluginContextWrapper({
|
|
67045
|
+
abortController,
|
|
67025
67046
|
config: this.#configFile,
|
|
67026
67047
|
name: this.artifact.name,
|
|
67027
67048
|
text: this.artifact.raw,
|
|
@@ -67065,7 +67086,9 @@ var DocumentStore = class extends Writable {
|
|
|
67065
67086
|
}
|
|
67066
67087
|
this.#step("forward", state);
|
|
67067
67088
|
});
|
|
67068
|
-
|
|
67089
|
+
const response = await promise;
|
|
67090
|
+
delete inflightRequests[this.controllerKey(variables)];
|
|
67091
|
+
return response;
|
|
67069
67092
|
}
|
|
67070
67093
|
async cleanup() {
|
|
67071
67094
|
for (const plugin2 of this.#plugins) {
|
|
@@ -67174,6 +67197,11 @@ var DocumentStore = class extends Writable {
|
|
|
67174
67197
|
};
|
|
67175
67198
|
}
|
|
67176
67199
|
try {
|
|
67200
|
+
if (draft.abortController.signal.aborted) {
|
|
67201
|
+
const abortError = new Error("aborted");
|
|
67202
|
+
abortError.name = "AbortError";
|
|
67203
|
+
throw abortError;
|
|
67204
|
+
}
|
|
67177
67205
|
const result = target(draft, handlers);
|
|
67178
67206
|
result?.catch((err) => {
|
|
67179
67207
|
this.#step("error", { ...ctx, index: index - 1 }, err);
|
|
@@ -68155,6 +68183,9 @@ var Config = class {
|
|
|
68155
68183
|
get listDirective() {
|
|
68156
68184
|
return "list";
|
|
68157
68185
|
}
|
|
68186
|
+
get dedupeDirective() {
|
|
68187
|
+
return "dedupe";
|
|
68188
|
+
}
|
|
68158
68189
|
get optimisticKeyDirective() {
|
|
68159
68190
|
return "optimisticKey";
|
|
68160
68191
|
}
|
|
@@ -11,6 +11,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
11
11
|
then: (val: any) => void;
|
|
12
12
|
} | null;
|
|
13
13
|
serverSideFallback?: boolean;
|
|
14
|
+
controllerKey(variables: any): string;
|
|
14
15
|
constructor({ artifact, plugins, pipeline, client, cache, enableCache, initialValue, initialVariables, fetching, }: {
|
|
15
16
|
artifact: DocumentArtifact;
|
|
16
17
|
plugins?: ClientHooks[];
|
|
@@ -23,7 +24,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
23
24
|
serverSideFallback?: boolean;
|
|
24
25
|
initialVariables?: _Input;
|
|
25
26
|
});
|
|
26
|
-
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
|
+
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, abortController, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
28
|
cleanup(): Promise<void>;
|
|
28
29
|
getFetch(getSession: () => App.Session | null | undefined): (input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>;
|
|
29
30
|
}
|
|
@@ -51,6 +52,7 @@ export type ClientPluginContext = {
|
|
|
51
52
|
metadata?: App.Metadata | null;
|
|
52
53
|
session?: App.Session | null;
|
|
53
54
|
fetchParams?: RequestInit;
|
|
55
|
+
abortController: AbortController;
|
|
54
56
|
cacheParams?: {
|
|
55
57
|
layer?: Layer;
|
|
56
58
|
notifySubscribers?: SubscriptionSpec[];
|
|
@@ -100,5 +102,6 @@ export type SendParams = {
|
|
|
100
102
|
cacheParams?: ClientPluginContext['cacheParams'];
|
|
101
103
|
setup?: boolean;
|
|
102
104
|
silenceEcho?: boolean;
|
|
105
|
+
abortController?: AbortController;
|
|
103
106
|
};
|
|
104
107
|
export {};
|
|
@@ -60,9 +60,11 @@ export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
|
60
60
|
policy?: CachePolicies;
|
|
61
61
|
partial?: boolean;
|
|
62
62
|
enableLoadingState?: 'global' | 'local';
|
|
63
|
+
dedupe?: 'first' | 'last';
|
|
63
64
|
};
|
|
64
65
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
|
|
65
66
|
optimisticKeys?: boolean;
|
|
67
|
+
dedupe?: 'first' | 'last';
|
|
66
68
|
};
|
|
67
69
|
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
68
70
|
enableLoadingState?: 'global' | 'local';
|
|
@@ -270,13 +272,13 @@ export type CursorHandlers<_Data extends GraphQLObject, _Input> = {
|
|
|
270
272
|
after?: string;
|
|
271
273
|
fetch?: typeof globalThis.fetch;
|
|
272
274
|
metadata?: {};
|
|
273
|
-
}) => Promise<
|
|
275
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
274
276
|
loadPreviousPage: (args?: {
|
|
275
277
|
last?: number;
|
|
276
278
|
before?: string;
|
|
277
279
|
fetch?: typeof globalThis.fetch;
|
|
278
280
|
metadata?: {};
|
|
279
|
-
}) => Promise<
|
|
281
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
280
282
|
fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
|
|
281
283
|
};
|
|
282
284
|
export type OffsetHandlers<_Data extends GraphQLObject, _Input> = {
|
|
@@ -11,6 +11,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
11
11
|
then: (val: any) => void;
|
|
12
12
|
} | null;
|
|
13
13
|
serverSideFallback?: boolean;
|
|
14
|
+
controllerKey(variables: any): string;
|
|
14
15
|
constructor({ artifact, plugins, pipeline, client, cache, enableCache, initialValue, initialVariables, fetching, }: {
|
|
15
16
|
artifact: DocumentArtifact;
|
|
16
17
|
plugins?: ClientHooks[];
|
|
@@ -23,7 +24,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
23
24
|
serverSideFallback?: boolean;
|
|
24
25
|
initialVariables?: _Input;
|
|
25
26
|
});
|
|
26
|
-
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
|
+
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, abortController, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
28
|
cleanup(): Promise<void>;
|
|
28
29
|
getFetch(getSession: () => App.Session | null | undefined): (input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>;
|
|
29
30
|
}
|
|
@@ -51,6 +52,7 @@ export type ClientPluginContext = {
|
|
|
51
52
|
metadata?: App.Metadata | null;
|
|
52
53
|
session?: App.Session | null;
|
|
53
54
|
fetchParams?: RequestInit;
|
|
55
|
+
abortController: AbortController;
|
|
54
56
|
cacheParams?: {
|
|
55
57
|
layer?: Layer;
|
|
56
58
|
notifySubscribers?: SubscriptionSpec[];
|
|
@@ -100,5 +102,6 @@ export type SendParams = {
|
|
|
100
102
|
cacheParams?: ClientPluginContext['cacheParams'];
|
|
101
103
|
setup?: boolean;
|
|
102
104
|
silenceEcho?: boolean;
|
|
105
|
+
abortController?: AbortController;
|
|
103
106
|
};
|
|
104
107
|
export {};
|
|
@@ -31,6 +31,7 @@ const steps = {
|
|
|
31
31
|
forward: ["start", "beforeNetwork", "network"],
|
|
32
32
|
backwards: ["end", "afterNetwork"]
|
|
33
33
|
};
|
|
34
|
+
let inflightRequests = {};
|
|
34
35
|
class DocumentStore extends import_store.Writable {
|
|
35
36
|
artifact;
|
|
36
37
|
#client;
|
|
@@ -40,6 +41,9 @@ class DocumentStore extends import_store.Writable {
|
|
|
40
41
|
#lastContext = null;
|
|
41
42
|
pendingPromise = null;
|
|
42
43
|
serverSideFallback;
|
|
44
|
+
controllerKey(variables) {
|
|
45
|
+
return this.artifact.name;
|
|
46
|
+
}
|
|
43
47
|
constructor({
|
|
44
48
|
artifact,
|
|
45
49
|
plugins,
|
|
@@ -97,9 +101,23 @@ class DocumentStore extends import_store.Writable {
|
|
|
97
101
|
stuff,
|
|
98
102
|
cacheParams,
|
|
99
103
|
setup = false,
|
|
100
|
-
silenceEcho = false
|
|
104
|
+
silenceEcho = false,
|
|
105
|
+
abortController = new AbortController()
|
|
101
106
|
} = {}) {
|
|
107
|
+
if ("dedupe" in this.artifact) {
|
|
108
|
+
if (inflightRequests[this.controllerKey(variables)]) {
|
|
109
|
+
if (this.artifact.dedupe === "first") {
|
|
110
|
+
inflightRequests[this.controllerKey(variables)].abort();
|
|
111
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
112
|
+
} else {
|
|
113
|
+
abortController.abort();
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
102
119
|
let context = new ClientPluginContextWrapper({
|
|
120
|
+
abortController,
|
|
103
121
|
config: this.#configFile,
|
|
104
122
|
name: this.artifact.name,
|
|
105
123
|
text: this.artifact.raw,
|
|
@@ -143,7 +161,9 @@ class DocumentStore extends import_store.Writable {
|
|
|
143
161
|
}
|
|
144
162
|
this.#step("forward", state);
|
|
145
163
|
});
|
|
146
|
-
|
|
164
|
+
const response = await promise;
|
|
165
|
+
delete inflightRequests[this.controllerKey(variables)];
|
|
166
|
+
return response;
|
|
147
167
|
}
|
|
148
168
|
async cleanup() {
|
|
149
169
|
for (const plugin of this.#plugins) {
|
|
@@ -252,6 +272,11 @@ class DocumentStore extends import_store.Writable {
|
|
|
252
272
|
};
|
|
253
273
|
}
|
|
254
274
|
try {
|
|
275
|
+
if (draft.abortController.signal.aborted) {
|
|
276
|
+
const abortError = new Error("aborted");
|
|
277
|
+
abortError.name = "AbortError";
|
|
278
|
+
throw abortError;
|
|
279
|
+
}
|
|
255
280
|
const result = target(draft, handlers);
|
|
256
281
|
result?.catch((err) => {
|
|
257
282
|
this.#step("error", { ...ctx, index: index - 1 }, err);
|
|
@@ -52,7 +52,10 @@ const fetch = (target) => {
|
|
|
52
52
|
const result = await fetchFn({
|
|
53
53
|
fetch: (url, args) => {
|
|
54
54
|
const newArgs = handleMultipart(fetchParams, args) ?? args;
|
|
55
|
-
return fetch2(url,
|
|
55
|
+
return fetch2(url, {
|
|
56
|
+
...newArgs,
|
|
57
|
+
signal: ctx.abortController.signal
|
|
58
|
+
});
|
|
56
59
|
},
|
|
57
60
|
metadata: ctx.metadata,
|
|
58
61
|
session: ctx.session || {},
|
|
@@ -22,7 +22,6 @@ __export(pagination_exports, {
|
|
|
22
22
|
offsetHandlers: () => offsetHandlers
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(pagination_exports);
|
|
25
|
-
var import_config = require("./config");
|
|
26
25
|
var import_deepEquals = require("./deepEquals");
|
|
27
26
|
var import_pageInfo = require("./pageInfo");
|
|
28
27
|
var import_types = require("./types");
|
|
@@ -42,7 +41,6 @@ function cursorHandlers({
|
|
|
42
41
|
fetch,
|
|
43
42
|
where
|
|
44
43
|
}) => {
|
|
45
|
-
const config = (0, import_config.getCurrentConfig)();
|
|
46
44
|
const loadVariables = {
|
|
47
45
|
...getVariables(),
|
|
48
46
|
...input
|
|
@@ -51,7 +49,7 @@ function cursorHandlers({
|
|
|
51
49
|
throw (0, import_pageInfo.missingPageSizeError)(functionName);
|
|
52
50
|
}
|
|
53
51
|
let isSinglePage = artifact.refetch?.mode === "SinglePage";
|
|
54
|
-
|
|
52
|
+
return (isSinglePage ? parentFetch : parentFetchUpdate)(
|
|
55
53
|
{
|
|
56
54
|
variables: loadVariables,
|
|
57
55
|
fetch,
|
|
@@ -66,7 +64,7 @@ function cursorHandlers({
|
|
|
66
64
|
return (0, import_pageInfo.extractPageInfo)(getState(), artifact.refetch?.path ?? []);
|
|
67
65
|
};
|
|
68
66
|
return {
|
|
69
|
-
loadNextPage:
|
|
67
|
+
loadNextPage: ({
|
|
70
68
|
first,
|
|
71
69
|
after,
|
|
72
70
|
fetch,
|
|
@@ -74,7 +72,15 @@ function cursorHandlers({
|
|
|
74
72
|
} = {}) => {
|
|
75
73
|
const currentPageInfo = getPageInfo();
|
|
76
74
|
if (!currentPageInfo.hasNextPage) {
|
|
77
|
-
return
|
|
75
|
+
return Promise.resolve({
|
|
76
|
+
data: getState(),
|
|
77
|
+
errors: null,
|
|
78
|
+
fetching: false,
|
|
79
|
+
partial: false,
|
|
80
|
+
stale: false,
|
|
81
|
+
source: import_types.DataSource.Cache,
|
|
82
|
+
variables: getVariables()
|
|
83
|
+
});
|
|
78
84
|
}
|
|
79
85
|
const input = {
|
|
80
86
|
first: first ?? artifact.refetch.pageSize,
|
|
@@ -82,7 +88,7 @@ function cursorHandlers({
|
|
|
82
88
|
before: null,
|
|
83
89
|
last: null
|
|
84
90
|
};
|
|
85
|
-
return
|
|
91
|
+
return loadPage({
|
|
86
92
|
pageSizeVar: "first",
|
|
87
93
|
functionName: "loadNextPage",
|
|
88
94
|
input,
|
|
@@ -91,7 +97,7 @@ function cursorHandlers({
|
|
|
91
97
|
where: "end"
|
|
92
98
|
});
|
|
93
99
|
},
|
|
94
|
-
loadPreviousPage:
|
|
100
|
+
loadPreviousPage: ({
|
|
95
101
|
last,
|
|
96
102
|
before,
|
|
97
103
|
fetch,
|
|
@@ -99,7 +105,15 @@ function cursorHandlers({
|
|
|
99
105
|
} = {}) => {
|
|
100
106
|
const currentPageInfo = getPageInfo();
|
|
101
107
|
if (!currentPageInfo.hasPreviousPage) {
|
|
102
|
-
return
|
|
108
|
+
return Promise.resolve({
|
|
109
|
+
data: getState(),
|
|
110
|
+
errors: null,
|
|
111
|
+
fetching: false,
|
|
112
|
+
partial: false,
|
|
113
|
+
stale: false,
|
|
114
|
+
source: import_types.DataSource.Cache,
|
|
115
|
+
variables: getVariables()
|
|
116
|
+
});
|
|
103
117
|
}
|
|
104
118
|
const input = {
|
|
105
119
|
before: before ?? currentPageInfo.startCursor,
|
|
@@ -107,7 +121,7 @@ function cursorHandlers({
|
|
|
107
121
|
first: null,
|
|
108
122
|
after: null
|
|
109
123
|
};
|
|
110
|
-
return
|
|
124
|
+
return loadPage({
|
|
111
125
|
pageSizeVar: "last",
|
|
112
126
|
functionName: "loadPreviousPage",
|
|
113
127
|
input,
|
|
@@ -60,9 +60,11 @@ export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
|
60
60
|
policy?: CachePolicies;
|
|
61
61
|
partial?: boolean;
|
|
62
62
|
enableLoadingState?: 'global' | 'local';
|
|
63
|
+
dedupe?: 'first' | 'last';
|
|
63
64
|
};
|
|
64
65
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
|
|
65
66
|
optimisticKeys?: boolean;
|
|
67
|
+
dedupe?: 'first' | 'last';
|
|
66
68
|
};
|
|
67
69
|
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
68
70
|
enableLoadingState?: 'global' | 'local';
|
|
@@ -270,13 +272,13 @@ export type CursorHandlers<_Data extends GraphQLObject, _Input> = {
|
|
|
270
272
|
after?: string;
|
|
271
273
|
fetch?: typeof globalThis.fetch;
|
|
272
274
|
metadata?: {};
|
|
273
|
-
}) => Promise<
|
|
275
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
274
276
|
loadPreviousPage: (args?: {
|
|
275
277
|
last?: number;
|
|
276
278
|
before?: string;
|
|
277
279
|
fetch?: typeof globalThis.fetch;
|
|
278
280
|
metadata?: {};
|
|
279
|
-
}) => Promise<
|
|
281
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
280
282
|
fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
|
|
281
283
|
};
|
|
282
284
|
export type OffsetHandlers<_Data extends GraphQLObject, _Input> = {
|
|
@@ -11,6 +11,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
11
11
|
then: (val: any) => void;
|
|
12
12
|
} | null;
|
|
13
13
|
serverSideFallback?: boolean;
|
|
14
|
+
controllerKey(variables: any): string;
|
|
14
15
|
constructor({ artifact, plugins, pipeline, client, cache, enableCache, initialValue, initialVariables, fetching, }: {
|
|
15
16
|
artifact: DocumentArtifact;
|
|
16
17
|
plugins?: ClientHooks[];
|
|
@@ -23,7 +24,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends G
|
|
|
23
24
|
serverSideFallback?: boolean;
|
|
24
25
|
initialVariables?: _Input;
|
|
25
26
|
});
|
|
26
|
-
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
|
+
send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, abortController, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
|
|
27
28
|
cleanup(): Promise<void>;
|
|
28
29
|
getFetch(getSession: () => App.Session | null | undefined): (input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>;
|
|
29
30
|
}
|
|
@@ -51,6 +52,7 @@ export type ClientPluginContext = {
|
|
|
51
52
|
metadata?: App.Metadata | null;
|
|
52
53
|
session?: App.Session | null;
|
|
53
54
|
fetchParams?: RequestInit;
|
|
55
|
+
abortController: AbortController;
|
|
54
56
|
cacheParams?: {
|
|
55
57
|
layer?: Layer;
|
|
56
58
|
notifySubscribers?: SubscriptionSpec[];
|
|
@@ -100,5 +102,6 @@ export type SendParams = {
|
|
|
100
102
|
cacheParams?: ClientPluginContext['cacheParams'];
|
|
101
103
|
setup?: boolean;
|
|
102
104
|
silenceEcho?: boolean;
|
|
105
|
+
abortController?: AbortController;
|
|
103
106
|
};
|
|
104
107
|
export {};
|
|
@@ -8,6 +8,7 @@ const steps = {
|
|
|
8
8
|
forward: ["start", "beforeNetwork", "network"],
|
|
9
9
|
backwards: ["end", "afterNetwork"]
|
|
10
10
|
};
|
|
11
|
+
let inflightRequests = {};
|
|
11
12
|
class DocumentStore extends Writable {
|
|
12
13
|
artifact;
|
|
13
14
|
#client;
|
|
@@ -17,6 +18,9 @@ class DocumentStore extends Writable {
|
|
|
17
18
|
#lastContext = null;
|
|
18
19
|
pendingPromise = null;
|
|
19
20
|
serverSideFallback;
|
|
21
|
+
controllerKey(variables) {
|
|
22
|
+
return this.artifact.name;
|
|
23
|
+
}
|
|
20
24
|
constructor({
|
|
21
25
|
artifact,
|
|
22
26
|
plugins,
|
|
@@ -74,9 +78,23 @@ class DocumentStore extends Writable {
|
|
|
74
78
|
stuff,
|
|
75
79
|
cacheParams,
|
|
76
80
|
setup = false,
|
|
77
|
-
silenceEcho = false
|
|
81
|
+
silenceEcho = false,
|
|
82
|
+
abortController = new AbortController()
|
|
78
83
|
} = {}) {
|
|
84
|
+
if ("dedupe" in this.artifact) {
|
|
85
|
+
if (inflightRequests[this.controllerKey(variables)]) {
|
|
86
|
+
if (this.artifact.dedupe === "first") {
|
|
87
|
+
inflightRequests[this.controllerKey(variables)].abort();
|
|
88
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
89
|
+
} else {
|
|
90
|
+
abortController.abort();
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
inflightRequests[this.controllerKey(variables)] = abortController;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
79
96
|
let context = new ClientPluginContextWrapper({
|
|
97
|
+
abortController,
|
|
80
98
|
config: this.#configFile,
|
|
81
99
|
name: this.artifact.name,
|
|
82
100
|
text: this.artifact.raw,
|
|
@@ -120,7 +138,9 @@ class DocumentStore extends Writable {
|
|
|
120
138
|
}
|
|
121
139
|
this.#step("forward", state);
|
|
122
140
|
});
|
|
123
|
-
|
|
141
|
+
const response = await promise;
|
|
142
|
+
delete inflightRequests[this.controllerKey(variables)];
|
|
143
|
+
return response;
|
|
124
144
|
}
|
|
125
145
|
async cleanup() {
|
|
126
146
|
for (const plugin of this.#plugins) {
|
|
@@ -229,6 +249,11 @@ class DocumentStore extends Writable {
|
|
|
229
249
|
};
|
|
230
250
|
}
|
|
231
251
|
try {
|
|
252
|
+
if (draft.abortController.signal.aborted) {
|
|
253
|
+
const abortError = new Error("aborted");
|
|
254
|
+
abortError.name = "AbortError";
|
|
255
|
+
throw abortError;
|
|
256
|
+
}
|
|
232
257
|
const result = target(draft, handlers);
|
|
233
258
|
result?.catch((err) => {
|
|
234
259
|
this.#step("error", { ...ctx, index: index - 1 }, err);
|
|
@@ -27,7 +27,10 @@ const fetch = (target) => {
|
|
|
27
27
|
const result = await fetchFn({
|
|
28
28
|
fetch: (url, args) => {
|
|
29
29
|
const newArgs = handleMultipart(fetchParams, args) ?? args;
|
|
30
|
-
return fetch2(url,
|
|
30
|
+
return fetch2(url, {
|
|
31
|
+
...newArgs,
|
|
32
|
+
signal: ctx.abortController.signal
|
|
33
|
+
});
|
|
31
34
|
},
|
|
32
35
|
metadata: ctx.metadata,
|
|
33
36
|
session: ctx.session || {},
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { getCurrentConfig } from "./config";
|
|
2
1
|
import { deepEquals } from "./deepEquals";
|
|
3
2
|
import { countPage, extractPageInfo, missingPageSizeError } from "./pageInfo";
|
|
4
|
-
import { CachePolicy } from "./types";
|
|
3
|
+
import { CachePolicy, DataSource } from "./types";
|
|
5
4
|
function cursorHandlers({
|
|
6
5
|
artifact,
|
|
7
6
|
fetchUpdate: parentFetchUpdate,
|
|
@@ -18,7 +17,6 @@ function cursorHandlers({
|
|
|
18
17
|
fetch,
|
|
19
18
|
where
|
|
20
19
|
}) => {
|
|
21
|
-
const config = getCurrentConfig();
|
|
22
20
|
const loadVariables = {
|
|
23
21
|
...getVariables(),
|
|
24
22
|
...input
|
|
@@ -27,7 +25,7 @@ function cursorHandlers({
|
|
|
27
25
|
throw missingPageSizeError(functionName);
|
|
28
26
|
}
|
|
29
27
|
let isSinglePage = artifact.refetch?.mode === "SinglePage";
|
|
30
|
-
|
|
28
|
+
return (isSinglePage ? parentFetch : parentFetchUpdate)(
|
|
31
29
|
{
|
|
32
30
|
variables: loadVariables,
|
|
33
31
|
fetch,
|
|
@@ -42,7 +40,7 @@ function cursorHandlers({
|
|
|
42
40
|
return extractPageInfo(getState(), artifact.refetch?.path ?? []);
|
|
43
41
|
};
|
|
44
42
|
return {
|
|
45
|
-
loadNextPage:
|
|
43
|
+
loadNextPage: ({
|
|
46
44
|
first,
|
|
47
45
|
after,
|
|
48
46
|
fetch,
|
|
@@ -50,7 +48,15 @@ function cursorHandlers({
|
|
|
50
48
|
} = {}) => {
|
|
51
49
|
const currentPageInfo = getPageInfo();
|
|
52
50
|
if (!currentPageInfo.hasNextPage) {
|
|
53
|
-
return
|
|
51
|
+
return Promise.resolve({
|
|
52
|
+
data: getState(),
|
|
53
|
+
errors: null,
|
|
54
|
+
fetching: false,
|
|
55
|
+
partial: false,
|
|
56
|
+
stale: false,
|
|
57
|
+
source: DataSource.Cache,
|
|
58
|
+
variables: getVariables()
|
|
59
|
+
});
|
|
54
60
|
}
|
|
55
61
|
const input = {
|
|
56
62
|
first: first ?? artifact.refetch.pageSize,
|
|
@@ -58,7 +64,7 @@ function cursorHandlers({
|
|
|
58
64
|
before: null,
|
|
59
65
|
last: null
|
|
60
66
|
};
|
|
61
|
-
return
|
|
67
|
+
return loadPage({
|
|
62
68
|
pageSizeVar: "first",
|
|
63
69
|
functionName: "loadNextPage",
|
|
64
70
|
input,
|
|
@@ -67,7 +73,7 @@ function cursorHandlers({
|
|
|
67
73
|
where: "end"
|
|
68
74
|
});
|
|
69
75
|
},
|
|
70
|
-
loadPreviousPage:
|
|
76
|
+
loadPreviousPage: ({
|
|
71
77
|
last,
|
|
72
78
|
before,
|
|
73
79
|
fetch,
|
|
@@ -75,7 +81,15 @@ function cursorHandlers({
|
|
|
75
81
|
} = {}) => {
|
|
76
82
|
const currentPageInfo = getPageInfo();
|
|
77
83
|
if (!currentPageInfo.hasPreviousPage) {
|
|
78
|
-
return
|
|
84
|
+
return Promise.resolve({
|
|
85
|
+
data: getState(),
|
|
86
|
+
errors: null,
|
|
87
|
+
fetching: false,
|
|
88
|
+
partial: false,
|
|
89
|
+
stale: false,
|
|
90
|
+
source: DataSource.Cache,
|
|
91
|
+
variables: getVariables()
|
|
92
|
+
});
|
|
79
93
|
}
|
|
80
94
|
const input = {
|
|
81
95
|
before: before ?? currentPageInfo.startCursor,
|
|
@@ -83,7 +97,7 @@ function cursorHandlers({
|
|
|
83
97
|
first: null,
|
|
84
98
|
after: null
|
|
85
99
|
};
|
|
86
|
-
return
|
|
100
|
+
return loadPage({
|
|
87
101
|
pageSizeVar: "last",
|
|
88
102
|
functionName: "loadPreviousPage",
|
|
89
103
|
input,
|
|
@@ -60,9 +60,11 @@ export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
|
60
60
|
policy?: CachePolicies;
|
|
61
61
|
partial?: boolean;
|
|
62
62
|
enableLoadingState?: 'global' | 'local';
|
|
63
|
+
dedupe?: 'first' | 'last';
|
|
63
64
|
};
|
|
64
65
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
|
|
65
66
|
optimisticKeys?: boolean;
|
|
67
|
+
dedupe?: 'first' | 'last';
|
|
66
68
|
};
|
|
67
69
|
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
68
70
|
enableLoadingState?: 'global' | 'local';
|
|
@@ -270,13 +272,13 @@ export type CursorHandlers<_Data extends GraphQLObject, _Input> = {
|
|
|
270
272
|
after?: string;
|
|
271
273
|
fetch?: typeof globalThis.fetch;
|
|
272
274
|
metadata?: {};
|
|
273
|
-
}) => Promise<
|
|
275
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
274
276
|
loadPreviousPage: (args?: {
|
|
275
277
|
last?: number;
|
|
276
278
|
before?: string;
|
|
277
279
|
fetch?: typeof globalThis.fetch;
|
|
278
280
|
metadata?: {};
|
|
279
|
-
}) => Promise<
|
|
281
|
+
}) => Promise<QueryResult<_Data, _Input>>;
|
|
280
282
|
fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
|
|
281
283
|
};
|
|
282
284
|
export type OffsetHandlers<_Data extends GraphQLObject, _Input> = {
|
package/build/test-cjs/index.js
CHANGED
|
@@ -57154,6 +57154,9 @@ var Config = class {
|
|
|
57154
57154
|
get listDirective() {
|
|
57155
57155
|
return "list";
|
|
57156
57156
|
}
|
|
57157
|
+
get dedupeDirective() {
|
|
57158
|
+
return "dedupe";
|
|
57159
|
+
}
|
|
57157
57160
|
get optimisticKeyDirective() {
|
|
57158
57161
|
return "optimisticKey";
|
|
57159
57162
|
}
|
|
@@ -59221,7 +59224,17 @@ async function paginate(config, documents) {
|
|
|
59221
59224
|
);
|
|
59222
59225
|
return {
|
|
59223
59226
|
...node,
|
|
59224
|
-
variableDefinitions: finalVariables
|
|
59227
|
+
variableDefinitions: finalVariables,
|
|
59228
|
+
directives: [
|
|
59229
|
+
...node.directives || [],
|
|
59230
|
+
{
|
|
59231
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
59232
|
+
name: {
|
|
59233
|
+
kind: graphql13.Kind.NAME,
|
|
59234
|
+
value: config.dedupeDirective
|
|
59235
|
+
}
|
|
59236
|
+
}
|
|
59237
|
+
]
|
|
59225
59238
|
};
|
|
59226
59239
|
},
|
|
59227
59240
|
FragmentDefinition(node) {
|
|
@@ -60544,6 +60557,7 @@ function artifactGenerator(stats) {
|
|
|
60544
60557
|
let rootType = "";
|
|
60545
60558
|
let selectionSet;
|
|
60546
60559
|
let originalSelectionSet = null;
|
|
60560
|
+
let dedupe;
|
|
60547
60561
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
60548
60562
|
(definition) => definition.kind === "FragmentDefinition"
|
|
60549
60563
|
).reduce(
|
|
@@ -60568,6 +60582,15 @@ function artifactGenerator(stats) {
|
|
|
60568
60582
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
60569
60583
|
});
|
|
60570
60584
|
}
|
|
60585
|
+
const dedupeDirective = operation.directives?.find(
|
|
60586
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
60587
|
+
);
|
|
60588
|
+
if (dedupeDirective) {
|
|
60589
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
60590
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
60591
|
+
);
|
|
60592
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
60593
|
+
}
|
|
60571
60594
|
selectionSet = operation.selectionSet;
|
|
60572
60595
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
60573
60596
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -60645,6 +60668,9 @@ function artifactGenerator(stats) {
|
|
|
60645
60668
|
};
|
|
60646
60669
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
60647
60670
|
artifact.hash = hash_value;
|
|
60671
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
60672
|
+
artifact.dedupe = dedupe;
|
|
60673
|
+
}
|
|
60648
60674
|
applyMask(
|
|
60649
60675
|
config,
|
|
60650
60676
|
artifact.selection,
|
|
@@ -64230,6 +64256,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
64230
64256
|
"""
|
|
64231
64257
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
64232
64258
|
|
|
64259
|
+
"""
|
|
64260
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
64261
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
64262
|
+
"""
|
|
64263
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
64264
|
+
|
|
64233
64265
|
"""
|
|
64234
64266
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
64235
64267
|
"""
|
package/build/test-esm/index.js
CHANGED
|
@@ -57150,6 +57150,9 @@ var Config = class {
|
|
|
57150
57150
|
get listDirective() {
|
|
57151
57151
|
return "list";
|
|
57152
57152
|
}
|
|
57153
|
+
get dedupeDirective() {
|
|
57154
|
+
return "dedupe";
|
|
57155
|
+
}
|
|
57153
57156
|
get optimisticKeyDirective() {
|
|
57154
57157
|
return "optimisticKey";
|
|
57155
57158
|
}
|
|
@@ -59217,7 +59220,17 @@ async function paginate(config, documents) {
|
|
|
59217
59220
|
);
|
|
59218
59221
|
return {
|
|
59219
59222
|
...node,
|
|
59220
|
-
variableDefinitions: finalVariables
|
|
59223
|
+
variableDefinitions: finalVariables,
|
|
59224
|
+
directives: [
|
|
59225
|
+
...node.directives || [],
|
|
59226
|
+
{
|
|
59227
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
59228
|
+
name: {
|
|
59229
|
+
kind: graphql13.Kind.NAME,
|
|
59230
|
+
value: config.dedupeDirective
|
|
59231
|
+
}
|
|
59232
|
+
}
|
|
59233
|
+
]
|
|
59221
59234
|
};
|
|
59222
59235
|
},
|
|
59223
59236
|
FragmentDefinition(node) {
|
|
@@ -60540,6 +60553,7 @@ function artifactGenerator(stats) {
|
|
|
60540
60553
|
let rootType = "";
|
|
60541
60554
|
let selectionSet;
|
|
60542
60555
|
let originalSelectionSet = null;
|
|
60556
|
+
let dedupe;
|
|
60543
60557
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
60544
60558
|
(definition) => definition.kind === "FragmentDefinition"
|
|
60545
60559
|
).reduce(
|
|
@@ -60564,6 +60578,15 @@ function artifactGenerator(stats) {
|
|
|
60564
60578
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
60565
60579
|
});
|
|
60566
60580
|
}
|
|
60581
|
+
const dedupeDirective = operation.directives?.find(
|
|
60582
|
+
(directive2) => directive2.name.value === config.dedupeDirective
|
|
60583
|
+
);
|
|
60584
|
+
if (dedupeDirective) {
|
|
60585
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
60586
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
60587
|
+
);
|
|
60588
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
60589
|
+
}
|
|
60567
60590
|
selectionSet = operation.selectionSet;
|
|
60568
60591
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
60569
60592
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -60641,6 +60664,9 @@ function artifactGenerator(stats) {
|
|
|
60641
60664
|
};
|
|
60642
60665
|
const hash_value = hashPluginBaseRaw({ config, document: { ...doc, artifact } });
|
|
60643
60666
|
artifact.hash = hash_value;
|
|
60667
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
60668
|
+
artifact.dedupe = dedupe;
|
|
60669
|
+
}
|
|
60644
60670
|
applyMask(
|
|
60645
60671
|
config,
|
|
60646
60672
|
artifact.selection,
|
|
@@ -64226,6 +64252,12 @@ directive @${config.paginateDirective}(${config.listOrPaginateNameArg}: String,
|
|
|
64226
64252
|
"""
|
|
64227
64253
|
directive @${config.listPrependDirective} on FRAGMENT_SPREAD
|
|
64228
64254
|
|
|
64255
|
+
"""
|
|
64256
|
+
@${config.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
64257
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
64258
|
+
"""
|
|
64259
|
+
directive @${config.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
64260
|
+
|
|
64229
64261
|
"""
|
|
64230
64262
|
@${config.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
64231
64263
|
"""
|
package/build/vite-cjs/index.js
CHANGED
|
@@ -69371,6 +69371,9 @@ var Config = class {
|
|
|
69371
69371
|
get listDirective() {
|
|
69372
69372
|
return "list";
|
|
69373
69373
|
}
|
|
69374
|
+
get dedupeDirective() {
|
|
69375
|
+
return "dedupe";
|
|
69376
|
+
}
|
|
69374
69377
|
get optimisticKeyDirective() {
|
|
69375
69378
|
return "optimisticKey";
|
|
69376
69379
|
}
|
|
@@ -72120,7 +72123,17 @@ async function paginate(config2, documents) {
|
|
|
72120
72123
|
);
|
|
72121
72124
|
return {
|
|
72122
72125
|
...node,
|
|
72123
|
-
variableDefinitions: finalVariables
|
|
72126
|
+
variableDefinitions: finalVariables,
|
|
72127
|
+
directives: [
|
|
72128
|
+
...node.directives || [],
|
|
72129
|
+
{
|
|
72130
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
72131
|
+
name: {
|
|
72132
|
+
kind: graphql13.Kind.NAME,
|
|
72133
|
+
value: config2.dedupeDirective
|
|
72134
|
+
}
|
|
72135
|
+
}
|
|
72136
|
+
]
|
|
72124
72137
|
};
|
|
72125
72138
|
},
|
|
72126
72139
|
FragmentDefinition(node) {
|
|
@@ -73443,6 +73456,7 @@ function artifactGenerator(stats) {
|
|
|
73443
73456
|
let rootType = "";
|
|
73444
73457
|
let selectionSet;
|
|
73445
73458
|
let originalSelectionSet = null;
|
|
73459
|
+
let dedupe;
|
|
73446
73460
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
73447
73461
|
(definition) => definition.kind === "FragmentDefinition"
|
|
73448
73462
|
).reduce(
|
|
@@ -73467,6 +73481,15 @@ function artifactGenerator(stats) {
|
|
|
73467
73481
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
73468
73482
|
});
|
|
73469
73483
|
}
|
|
73484
|
+
const dedupeDirective = operation.directives?.find(
|
|
73485
|
+
(directive2) => directive2.name.value === config2.dedupeDirective
|
|
73486
|
+
);
|
|
73487
|
+
if (dedupeDirective) {
|
|
73488
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
73489
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
73490
|
+
);
|
|
73491
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
73492
|
+
}
|
|
73470
73493
|
selectionSet = operation.selectionSet;
|
|
73471
73494
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
73472
73495
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -73544,6 +73567,9 @@ function artifactGenerator(stats) {
|
|
|
73544
73567
|
};
|
|
73545
73568
|
const hash_value = hashPluginBaseRaw({ config: config2, document: { ...doc, artifact } });
|
|
73546
73569
|
artifact.hash = hash_value;
|
|
73570
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
73571
|
+
artifact.dedupe = dedupe;
|
|
73572
|
+
}
|
|
73547
73573
|
applyMask(
|
|
73548
73574
|
config2,
|
|
73549
73575
|
artifact.selection,
|
|
@@ -77129,6 +77155,12 @@ directive @${config2.paginateDirective}(${config2.listOrPaginateNameArg}: String
|
|
|
77129
77155
|
"""
|
|
77130
77156
|
directive @${config2.listPrependDirective} on FRAGMENT_SPREAD
|
|
77131
77157
|
|
|
77158
|
+
"""
|
|
77159
|
+
@${config2.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
77160
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
77161
|
+
"""
|
|
77162
|
+
directive @${config2.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
77163
|
+
|
|
77132
77164
|
"""
|
|
77133
77165
|
@${config2.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
77134
77166
|
"""
|
package/build/vite-esm/index.js
CHANGED
|
@@ -69364,6 +69364,9 @@ var Config = class {
|
|
|
69364
69364
|
get listDirective() {
|
|
69365
69365
|
return "list";
|
|
69366
69366
|
}
|
|
69367
|
+
get dedupeDirective() {
|
|
69368
|
+
return "dedupe";
|
|
69369
|
+
}
|
|
69367
69370
|
get optimisticKeyDirective() {
|
|
69368
69371
|
return "optimisticKey";
|
|
69369
69372
|
}
|
|
@@ -72113,7 +72116,17 @@ async function paginate(config2, documents) {
|
|
|
72113
72116
|
);
|
|
72114
72117
|
return {
|
|
72115
72118
|
...node,
|
|
72116
|
-
variableDefinitions: finalVariables
|
|
72119
|
+
variableDefinitions: finalVariables,
|
|
72120
|
+
directives: [
|
|
72121
|
+
...node.directives || [],
|
|
72122
|
+
{
|
|
72123
|
+
kind: graphql13.Kind.DIRECTIVE,
|
|
72124
|
+
name: {
|
|
72125
|
+
kind: graphql13.Kind.NAME,
|
|
72126
|
+
value: config2.dedupeDirective
|
|
72127
|
+
}
|
|
72128
|
+
}
|
|
72129
|
+
]
|
|
72117
72130
|
};
|
|
72118
72131
|
},
|
|
72119
72132
|
FragmentDefinition(node) {
|
|
@@ -73436,6 +73449,7 @@ function artifactGenerator(stats) {
|
|
|
73436
73449
|
let rootType = "";
|
|
73437
73450
|
let selectionSet;
|
|
73438
73451
|
let originalSelectionSet = null;
|
|
73452
|
+
let dedupe;
|
|
73439
73453
|
const fragmentDefinitions = doc.document.definitions.filter(
|
|
73440
73454
|
(definition) => definition.kind === "FragmentDefinition"
|
|
73441
73455
|
).reduce(
|
|
@@ -73460,6 +73474,15 @@ function artifactGenerator(stats) {
|
|
|
73460
73474
|
message: "could not find root type for operation: " + operation.operation + ". Maybe you need to re-run the introspection query?"
|
|
73461
73475
|
});
|
|
73462
73476
|
}
|
|
73477
|
+
const dedupeDirective = operation.directives?.find(
|
|
73478
|
+
(directive2) => directive2.name.value === config2.dedupeDirective
|
|
73479
|
+
);
|
|
73480
|
+
if (dedupeDirective) {
|
|
73481
|
+
const cancelFirstArg = dedupeDirective.arguments?.find(
|
|
73482
|
+
(arg) => arg.name.value === "cancelFirst"
|
|
73483
|
+
);
|
|
73484
|
+
dedupe = cancelFirstArg && cancelFirstArg.value.kind === "BooleanValue" && cancelFirstArg.value ? "first" : "last";
|
|
73485
|
+
}
|
|
73463
73486
|
selectionSet = operation.selectionSet;
|
|
73464
73487
|
if (originalParsed.definitions[0].kind === "OperationDefinition") {
|
|
73465
73488
|
originalSelectionSet = originalParsed.definitions[0].selectionSet;
|
|
@@ -73537,6 +73560,9 @@ function artifactGenerator(stats) {
|
|
|
73537
73560
|
};
|
|
73538
73561
|
const hash_value = hashPluginBaseRaw({ config: config2, document: { ...doc, artifact } });
|
|
73539
73562
|
artifact.hash = hash_value;
|
|
73563
|
+
if (artifact.kind === "HoudiniQuery" || artifact.kind === "HoudiniMutation" && dedupe) {
|
|
73564
|
+
artifact.dedupe = dedupe;
|
|
73565
|
+
}
|
|
73540
73566
|
applyMask(
|
|
73541
73567
|
config2,
|
|
73542
73568
|
artifact.selection,
|
|
@@ -77122,6 +77148,12 @@ directive @${config2.paginateDirective}(${config2.listOrPaginateNameArg}: String
|
|
|
77122
77148
|
"""
|
|
77123
77149
|
directive @${config2.listPrependDirective} on FRAGMENT_SPREAD
|
|
77124
77150
|
|
|
77151
|
+
"""
|
|
77152
|
+
@${config2.dedupeDirective} is used to prevent an operation from running more than once at the same time.
|
|
77153
|
+
If the cancelFirst arg is set to true, the response already in flight will be canceled instead of the second one.
|
|
77154
|
+
"""
|
|
77155
|
+
directive @${config2.dedupeDirective}(cancelFirst: Boolean) on QUERY | MUTATION
|
|
77156
|
+
|
|
77125
77157
|
"""
|
|
77126
77158
|
@${config2.optimisticKeyDirective} is used to identify a field as an optimistic key
|
|
77127
77159
|
"""
|