houdini 1.3.0 → 1.4.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/build/cmd-cjs/index.js +64 -25
- package/build/cmd-esm/index.js +64 -25
- package/build/codegen-cjs/index.js +37 -4
- package/build/codegen-esm/index.js +37 -4
- package/build/lib/config.d.ts +1 -0
- package/build/lib/router/types.d.ts +3 -1
- package/build/lib-cjs/index.js +52 -15
- package/build/lib-esm/index.js +51 -15
- package/build/runtime/lib/config.d.ts +10 -1
- package/build/runtime/lib/types.d.ts +14 -2
- package/build/runtime-cjs/client/documentStore.js +27 -7
- package/build/runtime-cjs/client/plugins/fetch.js +5 -0
- package/build/runtime-cjs/lib/config.d.ts +10 -1
- package/build/runtime-cjs/lib/types.d.ts +14 -2
- package/build/runtime-cjs/lib/types.js +7 -0
- package/build/runtime-esm/client/documentStore.js +28 -8
- package/build/runtime-esm/client/plugins/fetch.js +5 -0
- package/build/runtime-esm/lib/config.d.ts +10 -1
- package/build/runtime-esm/lib/types.d.ts +14 -2
- package/build/runtime-esm/lib/types.js +6 -0
- package/build/test-cjs/index.js +43 -9
- package/build/test-esm/index.js +43 -9
- package/build/vite-cjs/index.js +50 -12
- package/build/vite-esm/index.js +50 -12
- package/package.json +3 -3
package/build/lib-cjs/index.js
CHANGED
|
@@ -58181,6 +58181,7 @@ __export(lib_exports, {
|
|
|
58181
58181
|
CompiledSubscriptionKind: () => CompiledSubscriptionKind,
|
|
58182
58182
|
Config: () => Config,
|
|
58183
58183
|
DataSource: () => DataSource,
|
|
58184
|
+
DedupeMatchMode: () => DedupeMatchMode,
|
|
58184
58185
|
DocumentStore: () => DocumentStore,
|
|
58185
58186
|
HoudiniClient: () => HoudiniClient,
|
|
58186
58187
|
HoudiniError: () => HoudiniError,
|
|
@@ -61533,6 +61534,11 @@ var CachePolicy = {
|
|
|
61533
61534
|
CacheAndNetwork: "CacheAndNetwork",
|
|
61534
61535
|
NoCache: "NoCache"
|
|
61535
61536
|
};
|
|
61537
|
+
var DedupeMatchMode = {
|
|
61538
|
+
Variables: "Variables",
|
|
61539
|
+
Operation: "Operation",
|
|
61540
|
+
None: "None"
|
|
61541
|
+
};
|
|
61536
61542
|
var PaginateMode = {
|
|
61537
61543
|
Infinite: "Infinite",
|
|
61538
61544
|
SinglePage: "SinglePage"
|
|
@@ -63420,7 +63426,7 @@ async function pullSchema(url, fetchTimeout, schemaPath, headers, skipWriting) {
|
|
|
63420
63426
|
content = await resp.text();
|
|
63421
63427
|
const jsonSchema = JSON.parse(content).data;
|
|
63422
63428
|
let fileData = "";
|
|
63423
|
-
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql")) {
|
|
63429
|
+
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql") || schemaPath.endsWith("graphqls")) {
|
|
63424
63430
|
const schema = graphql.buildClientSchema(jsonSchema);
|
|
63425
63431
|
fileData = graphql.printSchema(graphql.lexicographicSortSchema(schema));
|
|
63426
63432
|
} else {
|
|
@@ -66232,6 +66238,11 @@ var defaultFetch = (url, params) => {
|
|
|
66232
66238
|
...params?.headers
|
|
66233
66239
|
}
|
|
66234
66240
|
});
|
|
66241
|
+
if (!result.ok && result.headers.get("content-type") !== "application/json" && result.headers.get("content-type") !== "application/graphql+json") {
|
|
66242
|
+
throw new Error(
|
|
66243
|
+
`Failed to fetch: server returned invalid response with error ${result.status}: ${result.statusText}`
|
|
66244
|
+
);
|
|
66245
|
+
}
|
|
66235
66246
|
return await result.json();
|
|
66236
66247
|
};
|
|
66237
66248
|
};
|
|
@@ -67052,7 +67063,8 @@ var DocumentStore = class extends Writable {
|
|
|
67052
67063
|
pendingPromise = null;
|
|
67053
67064
|
serverSideFallback;
|
|
67054
67065
|
controllerKey(variables) {
|
|
67055
|
-
|
|
67066
|
+
const usedVariables = "dedupe" in this.artifact && this.artifact.dedupe?.match !== DedupeMatchMode.Variables ? {} : variables;
|
|
67067
|
+
return `${this.artifact.name}@${stableStringify(usedVariables)}`;
|
|
67056
67068
|
}
|
|
67057
67069
|
constructor({
|
|
67058
67070
|
artifact,
|
|
@@ -67114,16 +67126,20 @@ var DocumentStore = class extends Writable {
|
|
|
67114
67126
|
silenceEcho = false,
|
|
67115
67127
|
abortController = new AbortController()
|
|
67116
67128
|
} = {}) {
|
|
67117
|
-
if ("dedupe" in this.artifact) {
|
|
67118
|
-
|
|
67119
|
-
|
|
67120
|
-
|
|
67121
|
-
inflightRequests[
|
|
67129
|
+
if ("dedupe" in this.artifact && this.artifact.dedupe && this.artifact.dedupe.match !== "None") {
|
|
67130
|
+
const dedupeKey = this.controllerKey(variables);
|
|
67131
|
+
if (inflightRequests[dedupeKey]) {
|
|
67132
|
+
if (this.artifact.dedupe.cancel === "first") {
|
|
67133
|
+
inflightRequests[dedupeKey].controller.abort();
|
|
67134
|
+
inflightRequests[dedupeKey].controller = abortController;
|
|
67122
67135
|
} else {
|
|
67123
67136
|
abortController.abort();
|
|
67124
67137
|
}
|
|
67125
67138
|
} else {
|
|
67126
|
-
inflightRequests[
|
|
67139
|
+
inflightRequests[dedupeKey] = {
|
|
67140
|
+
variables,
|
|
67141
|
+
controller: abortController
|
|
67142
|
+
};
|
|
67127
67143
|
}
|
|
67128
67144
|
}
|
|
67129
67145
|
let context = new ClientPluginContextWrapper({
|
|
@@ -67445,6 +67461,21 @@ function marshalVariables(ctx) {
|
|
|
67445
67461
|
function variablesChanged(ctx) {
|
|
67446
67462
|
return ctx.stuff.inputs?.changed;
|
|
67447
67463
|
}
|
|
67464
|
+
function stableStringify(obj) {
|
|
67465
|
+
return JSON.stringify(sortObject(obj));
|
|
67466
|
+
}
|
|
67467
|
+
function sortObject(obj) {
|
|
67468
|
+
if (obj === null || typeof obj !== "object") {
|
|
67469
|
+
return obj;
|
|
67470
|
+
}
|
|
67471
|
+
if (Array.isArray(obj)) {
|
|
67472
|
+
return obj.map(sortObject);
|
|
67473
|
+
}
|
|
67474
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
67475
|
+
result[key] = sortObject(obj[key]);
|
|
67476
|
+
return result;
|
|
67477
|
+
}, {});
|
|
67478
|
+
}
|
|
67448
67479
|
|
|
67449
67480
|
// src/runtime/client/plugins/injectedPlugins.ts
|
|
67450
67481
|
var plugins = [];
|
|
@@ -67882,8 +67913,9 @@ var Config = class {
|
|
|
67882
67913
|
localSchema;
|
|
67883
67914
|
projectRoot;
|
|
67884
67915
|
schema;
|
|
67916
|
+
runtimeDir;
|
|
67885
67917
|
schemaPath;
|
|
67886
|
-
persistedQueriesPath
|
|
67918
|
+
persistedQueriesPath;
|
|
67887
67919
|
exclude;
|
|
67888
67920
|
scalars;
|
|
67889
67921
|
module = "esm";
|
|
@@ -67924,6 +67956,7 @@ var Config = class {
|
|
|
67924
67956
|
let {
|
|
67925
67957
|
schema,
|
|
67926
67958
|
schemaPath = "./schema.graphql",
|
|
67959
|
+
runtimeDir = "$houdini",
|
|
67927
67960
|
exclude = [],
|
|
67928
67961
|
module: module2 = "esm",
|
|
67929
67962
|
scalars,
|
|
@@ -67962,6 +67995,7 @@ var Config = class {
|
|
|
67962
67995
|
this.projectRoot = dirname(
|
|
67963
67996
|
projectDir ? join2(process.cwd(), projectDir) : filepath
|
|
67964
67997
|
);
|
|
67998
|
+
this.runtimeDir = runtimeDir;
|
|
67965
67999
|
this.scalars = scalars;
|
|
67966
68000
|
this.cacheBufferSize = cacheBufferSize;
|
|
67967
68001
|
this.defaultCachePolicy = defaultCachePolicy;
|
|
@@ -67976,11 +68010,9 @@ var Config = class {
|
|
|
67976
68010
|
this.schemaPollInterval = watchSchema?.interval === void 0 ? 2e3 : watchSchema.interval;
|
|
67977
68011
|
this.schemaPollTimeout = watchSchema?.timeout ?? 3e4;
|
|
67978
68012
|
this.schemaPollHeaders = watchSchema?.headers ?? {};
|
|
67979
|
-
this.rootDir = join2(this.projectRoot,
|
|
68013
|
+
this.rootDir = join2(this.projectRoot, this.runtimeDir);
|
|
68014
|
+
this.persistedQueriesPath = persistedQueriesPath ?? join2(this.rootDir, "persisted_queries.json");
|
|
67980
68015
|
this.#fragmentVariableMaps = {};
|
|
67981
|
-
if (persistedQueriesPath) {
|
|
67982
|
-
this.persistedQueriesPath = persistedQueriesPath;
|
|
67983
|
-
}
|
|
67984
68016
|
if (defaultKeys) {
|
|
67985
68017
|
this.defaultKeys = defaultKeys;
|
|
67986
68018
|
}
|
|
@@ -68633,7 +68665,11 @@ async function getConfig({
|
|
|
68633
68665
|
}
|
|
68634
68666
|
}
|
|
68635
68667
|
if (schemaOk && !noSchema) {
|
|
68636
|
-
|
|
68668
|
+
try {
|
|
68669
|
+
_config.schema = await loadSchemaFile(_config.schemaPath);
|
|
68670
|
+
} catch (e2) {
|
|
68671
|
+
console.error(`\u26A0\uFE0F Your schema file could not be loaded: ${e2}`);
|
|
68672
|
+
}
|
|
68637
68673
|
}
|
|
68638
68674
|
}
|
|
68639
68675
|
_config.plugins = orderedPlugins(plugins2);
|
|
@@ -68764,7 +68800,7 @@ async function loadSchemaFile(schemaPath) {
|
|
|
68764
68800
|
});
|
|
68765
68801
|
}
|
|
68766
68802
|
const contents = await readFile(schemaPath);
|
|
68767
|
-
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql")) {
|
|
68803
|
+
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql") || schemaPath.endsWith("graphqls")) {
|
|
68768
68804
|
return graphql3.buildSchema(contents);
|
|
68769
68805
|
}
|
|
68770
68806
|
const jsonContents = JSON.parse(contents);
|
|
@@ -69816,6 +69852,7 @@ function extractAnonymousQuery(config, raw, expr, propName) {
|
|
|
69816
69852
|
CompiledSubscriptionKind,
|
|
69817
69853
|
Config,
|
|
69818
69854
|
DataSource,
|
|
69855
|
+
DedupeMatchMode,
|
|
69819
69856
|
DocumentStore,
|
|
69820
69857
|
HoudiniClient,
|
|
69821
69858
|
HoudiniError,
|
package/build/lib-esm/index.js
CHANGED
|
@@ -61448,6 +61448,11 @@ var CachePolicy = {
|
|
|
61448
61448
|
CacheAndNetwork: "CacheAndNetwork",
|
|
61449
61449
|
NoCache: "NoCache"
|
|
61450
61450
|
};
|
|
61451
|
+
var DedupeMatchMode = {
|
|
61452
|
+
Variables: "Variables",
|
|
61453
|
+
Operation: "Operation",
|
|
61454
|
+
None: "None"
|
|
61455
|
+
};
|
|
61451
61456
|
var PaginateMode = {
|
|
61452
61457
|
Infinite: "Infinite",
|
|
61453
61458
|
SinglePage: "SinglePage"
|
|
@@ -63335,7 +63340,7 @@ async function pullSchema(url, fetchTimeout, schemaPath, headers, skipWriting) {
|
|
|
63335
63340
|
content = await resp.text();
|
|
63336
63341
|
const jsonSchema = JSON.parse(content).data;
|
|
63337
63342
|
let fileData = "";
|
|
63338
|
-
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql")) {
|
|
63343
|
+
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql") || schemaPath.endsWith("graphqls")) {
|
|
63339
63344
|
const schema = graphql.buildClientSchema(jsonSchema);
|
|
63340
63345
|
fileData = graphql.printSchema(graphql.lexicographicSortSchema(schema));
|
|
63341
63346
|
} else {
|
|
@@ -66147,6 +66152,11 @@ var defaultFetch = (url, params) => {
|
|
|
66147
66152
|
...params?.headers
|
|
66148
66153
|
}
|
|
66149
66154
|
});
|
|
66155
|
+
if (!result.ok && result.headers.get("content-type") !== "application/json" && result.headers.get("content-type") !== "application/graphql+json") {
|
|
66156
|
+
throw new Error(
|
|
66157
|
+
`Failed to fetch: server returned invalid response with error ${result.status}: ${result.statusText}`
|
|
66158
|
+
);
|
|
66159
|
+
}
|
|
66150
66160
|
return await result.json();
|
|
66151
66161
|
};
|
|
66152
66162
|
};
|
|
@@ -66967,7 +66977,8 @@ var DocumentStore = class extends Writable {
|
|
|
66967
66977
|
pendingPromise = null;
|
|
66968
66978
|
serverSideFallback;
|
|
66969
66979
|
controllerKey(variables) {
|
|
66970
|
-
|
|
66980
|
+
const usedVariables = "dedupe" in this.artifact && this.artifact.dedupe?.match !== DedupeMatchMode.Variables ? {} : variables;
|
|
66981
|
+
return `${this.artifact.name}@${stableStringify(usedVariables)}`;
|
|
66971
66982
|
}
|
|
66972
66983
|
constructor({
|
|
66973
66984
|
artifact,
|
|
@@ -67029,16 +67040,20 @@ var DocumentStore = class extends Writable {
|
|
|
67029
67040
|
silenceEcho = false,
|
|
67030
67041
|
abortController = new AbortController()
|
|
67031
67042
|
} = {}) {
|
|
67032
|
-
if ("dedupe" in this.artifact) {
|
|
67033
|
-
|
|
67034
|
-
|
|
67035
|
-
|
|
67036
|
-
inflightRequests[
|
|
67043
|
+
if ("dedupe" in this.artifact && this.artifact.dedupe && this.artifact.dedupe.match !== "None") {
|
|
67044
|
+
const dedupeKey = this.controllerKey(variables);
|
|
67045
|
+
if (inflightRequests[dedupeKey]) {
|
|
67046
|
+
if (this.artifact.dedupe.cancel === "first") {
|
|
67047
|
+
inflightRequests[dedupeKey].controller.abort();
|
|
67048
|
+
inflightRequests[dedupeKey].controller = abortController;
|
|
67037
67049
|
} else {
|
|
67038
67050
|
abortController.abort();
|
|
67039
67051
|
}
|
|
67040
67052
|
} else {
|
|
67041
|
-
inflightRequests[
|
|
67053
|
+
inflightRequests[dedupeKey] = {
|
|
67054
|
+
variables,
|
|
67055
|
+
controller: abortController
|
|
67056
|
+
};
|
|
67042
67057
|
}
|
|
67043
67058
|
}
|
|
67044
67059
|
let context = new ClientPluginContextWrapper({
|
|
@@ -67360,6 +67375,21 @@ function marshalVariables(ctx) {
|
|
|
67360
67375
|
function variablesChanged(ctx) {
|
|
67361
67376
|
return ctx.stuff.inputs?.changed;
|
|
67362
67377
|
}
|
|
67378
|
+
function stableStringify(obj) {
|
|
67379
|
+
return JSON.stringify(sortObject(obj));
|
|
67380
|
+
}
|
|
67381
|
+
function sortObject(obj) {
|
|
67382
|
+
if (obj === null || typeof obj !== "object") {
|
|
67383
|
+
return obj;
|
|
67384
|
+
}
|
|
67385
|
+
if (Array.isArray(obj)) {
|
|
67386
|
+
return obj.map(sortObject);
|
|
67387
|
+
}
|
|
67388
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
67389
|
+
result[key] = sortObject(obj[key]);
|
|
67390
|
+
return result;
|
|
67391
|
+
}, {});
|
|
67392
|
+
}
|
|
67363
67393
|
|
|
67364
67394
|
// src/runtime/client/plugins/injectedPlugins.ts
|
|
67365
67395
|
var plugins = [];
|
|
@@ -67796,8 +67826,9 @@ var Config = class {
|
|
|
67796
67826
|
localSchema;
|
|
67797
67827
|
projectRoot;
|
|
67798
67828
|
schema;
|
|
67829
|
+
runtimeDir;
|
|
67799
67830
|
schemaPath;
|
|
67800
|
-
persistedQueriesPath
|
|
67831
|
+
persistedQueriesPath;
|
|
67801
67832
|
exclude;
|
|
67802
67833
|
scalars;
|
|
67803
67834
|
module = "esm";
|
|
@@ -67838,6 +67869,7 @@ var Config = class {
|
|
|
67838
67869
|
let {
|
|
67839
67870
|
schema,
|
|
67840
67871
|
schemaPath = "./schema.graphql",
|
|
67872
|
+
runtimeDir = "$houdini",
|
|
67841
67873
|
exclude = [],
|
|
67842
67874
|
module = "esm",
|
|
67843
67875
|
scalars,
|
|
@@ -67876,6 +67908,7 @@ var Config = class {
|
|
|
67876
67908
|
this.projectRoot = dirname(
|
|
67877
67909
|
projectDir ? join2(process.cwd(), projectDir) : filepath
|
|
67878
67910
|
);
|
|
67911
|
+
this.runtimeDir = runtimeDir;
|
|
67879
67912
|
this.scalars = scalars;
|
|
67880
67913
|
this.cacheBufferSize = cacheBufferSize;
|
|
67881
67914
|
this.defaultCachePolicy = defaultCachePolicy;
|
|
@@ -67890,11 +67923,9 @@ var Config = class {
|
|
|
67890
67923
|
this.schemaPollInterval = watchSchema?.interval === void 0 ? 2e3 : watchSchema.interval;
|
|
67891
67924
|
this.schemaPollTimeout = watchSchema?.timeout ?? 3e4;
|
|
67892
67925
|
this.schemaPollHeaders = watchSchema?.headers ?? {};
|
|
67893
|
-
this.rootDir = join2(this.projectRoot,
|
|
67926
|
+
this.rootDir = join2(this.projectRoot, this.runtimeDir);
|
|
67927
|
+
this.persistedQueriesPath = persistedQueriesPath ?? join2(this.rootDir, "persisted_queries.json");
|
|
67894
67928
|
this.#fragmentVariableMaps = {};
|
|
67895
|
-
if (persistedQueriesPath) {
|
|
67896
|
-
this.persistedQueriesPath = persistedQueriesPath;
|
|
67897
|
-
}
|
|
67898
67929
|
if (defaultKeys) {
|
|
67899
67930
|
this.defaultKeys = defaultKeys;
|
|
67900
67931
|
}
|
|
@@ -68547,7 +68578,11 @@ async function getConfig({
|
|
|
68547
68578
|
}
|
|
68548
68579
|
}
|
|
68549
68580
|
if (schemaOk && !noSchema) {
|
|
68550
|
-
|
|
68581
|
+
try {
|
|
68582
|
+
_config.schema = await loadSchemaFile(_config.schemaPath);
|
|
68583
|
+
} catch (e2) {
|
|
68584
|
+
console.error(`\u26A0\uFE0F Your schema file could not be loaded: ${e2}`);
|
|
68585
|
+
}
|
|
68551
68586
|
}
|
|
68552
68587
|
}
|
|
68553
68588
|
_config.plugins = orderedPlugins(plugins2);
|
|
@@ -68678,7 +68713,7 @@ async function loadSchemaFile(schemaPath) {
|
|
|
68678
68713
|
});
|
|
68679
68714
|
}
|
|
68680
68715
|
const contents = await readFile(schemaPath);
|
|
68681
|
-
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql")) {
|
|
68716
|
+
if (schemaPath.endsWith("gql") || schemaPath.endsWith("graphql") || schemaPath.endsWith("graphqls")) {
|
|
68682
68717
|
return graphql3.buildSchema(contents);
|
|
68683
68718
|
}
|
|
68684
68719
|
const jsonContents = JSON.parse(contents);
|
|
@@ -69729,6 +69764,7 @@ export {
|
|
|
69729
69764
|
CompiledSubscriptionKind,
|
|
69730
69765
|
Config,
|
|
69731
69766
|
DataSource,
|
|
69767
|
+
DedupeMatchMode,
|
|
69732
69768
|
DocumentStore,
|
|
69733
69769
|
HoudiniClient,
|
|
69734
69770
|
HoudiniError,
|
|
@@ -73,6 +73,10 @@ export type ConfigFile = {
|
|
|
73
73
|
* Specifies whether the default paginate mode is Infinite or SinglePage. (default: `Infinite`)
|
|
74
74
|
*/
|
|
75
75
|
defaultPaginateMode?: PaginateModes;
|
|
76
|
+
/**
|
|
77
|
+
* Prevents the runtime from deduplicating pagination requests
|
|
78
|
+
*/
|
|
79
|
+
supressPaginationDeduplication?: boolean;
|
|
76
80
|
/**
|
|
77
81
|
* A list of fields to use when computing a record’s id. The default value is ['id']. For more information: https://www.houdinigraphql.com/guides/caching-data#custom-ids
|
|
78
82
|
*/
|
|
@@ -95,7 +99,7 @@ export type ConfigFile = {
|
|
|
95
99
|
*/
|
|
96
100
|
watchSchema?: WatchSchemaConfig;
|
|
97
101
|
/**
|
|
98
|
-
* Specifies the the persisted queries path and file. (default:
|
|
102
|
+
* Specifies the the persisted queries path and file. (default: `<rootDir>/persisted_queries.json`)
|
|
99
103
|
*/
|
|
100
104
|
persistedQueriesPath?: string;
|
|
101
105
|
/**
|
|
@@ -107,6 +111,11 @@ export type ConfigFile = {
|
|
|
107
111
|
* @default process.cwd()
|
|
108
112
|
*/
|
|
109
113
|
projectDir?: string;
|
|
114
|
+
/**
|
|
115
|
+
* The relative path from your project directory pointing to your output directory.
|
|
116
|
+
* @default `$houdini`
|
|
117
|
+
*/
|
|
118
|
+
runtimeDir?: string;
|
|
110
119
|
/**
|
|
111
120
|
* For now, the cache's imperative API is considered unstable. In order to suppress the warning,
|
|
112
121
|
* you must enable this flag.
|
|
@@ -7,6 +7,12 @@ export declare const CachePolicy: {
|
|
|
7
7
|
readonly NoCache: "NoCache";
|
|
8
8
|
};
|
|
9
9
|
export type CachePolicies = ValuesOf<typeof CachePolicy>;
|
|
10
|
+
export declare const DedupeMatchMode: {
|
|
11
|
+
readonly Variables: "Variables";
|
|
12
|
+
readonly Operation: "Operation";
|
|
13
|
+
readonly None: "None";
|
|
14
|
+
};
|
|
15
|
+
export type DedupeMatchModes = ValuesOf<typeof DedupeMatchMode>;
|
|
10
16
|
export declare const PaginateMode: {
|
|
11
17
|
readonly Infinite: "Infinite";
|
|
12
18
|
readonly SinglePage: "SinglePage";
|
|
@@ -60,11 +66,17 @@ export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
|
60
66
|
policy?: CachePolicies;
|
|
61
67
|
partial?: boolean;
|
|
62
68
|
enableLoadingState?: 'global' | 'local';
|
|
63
|
-
dedupe?:
|
|
69
|
+
dedupe?: {
|
|
70
|
+
cancel: 'first' | 'last';
|
|
71
|
+
match: DedupeMatchModes;
|
|
72
|
+
};
|
|
64
73
|
};
|
|
65
74
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
|
|
66
75
|
optimisticKeys?: boolean;
|
|
67
|
-
dedupe?:
|
|
76
|
+
dedupe?: {
|
|
77
|
+
cancel: 'first' | 'last';
|
|
78
|
+
match: DedupeMatchModes;
|
|
79
|
+
};
|
|
68
80
|
};
|
|
69
81
|
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
70
82
|
enableLoadingState?: 'global' | 'local';
|
|
@@ -42,7 +42,8 @@ class DocumentStore extends import_store.Writable {
|
|
|
42
42
|
pendingPromise = null;
|
|
43
43
|
serverSideFallback;
|
|
44
44
|
controllerKey(variables) {
|
|
45
|
-
|
|
45
|
+
const usedVariables = "dedupe" in this.artifact && this.artifact.dedupe?.match !== import_types.DedupeMatchMode.Variables ? {} : variables;
|
|
46
|
+
return `${this.artifact.name}@${stableStringify(usedVariables)}`;
|
|
46
47
|
}
|
|
47
48
|
constructor({
|
|
48
49
|
artifact,
|
|
@@ -104,16 +105,20 @@ class DocumentStore extends import_store.Writable {
|
|
|
104
105
|
silenceEcho = false,
|
|
105
106
|
abortController = new AbortController()
|
|
106
107
|
} = {}) {
|
|
107
|
-
if ("dedupe" in this.artifact) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
inflightRequests[
|
|
108
|
+
if ("dedupe" in this.artifact && this.artifact.dedupe && this.artifact.dedupe.match !== "None") {
|
|
109
|
+
const dedupeKey = this.controllerKey(variables);
|
|
110
|
+
if (inflightRequests[dedupeKey]) {
|
|
111
|
+
if (this.artifact.dedupe.cancel === "first") {
|
|
112
|
+
inflightRequests[dedupeKey].controller.abort();
|
|
113
|
+
inflightRequests[dedupeKey].controller = abortController;
|
|
112
114
|
} else {
|
|
113
115
|
abortController.abort();
|
|
114
116
|
}
|
|
115
117
|
} else {
|
|
116
|
-
inflightRequests[
|
|
118
|
+
inflightRequests[dedupeKey] = {
|
|
119
|
+
variables,
|
|
120
|
+
controller: abortController
|
|
121
|
+
};
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
let context = new ClientPluginContextWrapper({
|
|
@@ -435,6 +440,21 @@ function marshalVariables(ctx) {
|
|
|
435
440
|
function variablesChanged(ctx) {
|
|
436
441
|
return ctx.stuff.inputs?.changed;
|
|
437
442
|
}
|
|
443
|
+
function stableStringify(obj) {
|
|
444
|
+
return JSON.stringify(sortObject(obj));
|
|
445
|
+
}
|
|
446
|
+
function sortObject(obj) {
|
|
447
|
+
if (obj === null || typeof obj !== "object") {
|
|
448
|
+
return obj;
|
|
449
|
+
}
|
|
450
|
+
if (Array.isArray(obj)) {
|
|
451
|
+
return obj.map(sortObject);
|
|
452
|
+
}
|
|
453
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
454
|
+
result[key] = sortObject(obj[key]);
|
|
455
|
+
return result;
|
|
456
|
+
}, {});
|
|
457
|
+
}
|
|
438
458
|
// Annotate the CommonJS export names for ESM import in node:
|
|
439
459
|
0 && (module.exports = {
|
|
440
460
|
DocumentStore
|
|
@@ -91,6 +91,11 @@ const defaultFetch = (url, params) => {
|
|
|
91
91
|
...params?.headers
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
|
+
if (!result.ok && result.headers.get("content-type") !== "application/json" && result.headers.get("content-type") !== "application/graphql+json") {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Failed to fetch: server returned invalid response with error ${result.status}: ${result.statusText}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
94
99
|
return await result.json();
|
|
95
100
|
};
|
|
96
101
|
};
|
|
@@ -73,6 +73,10 @@ export type ConfigFile = {
|
|
|
73
73
|
* Specifies whether the default paginate mode is Infinite or SinglePage. (default: `Infinite`)
|
|
74
74
|
*/
|
|
75
75
|
defaultPaginateMode?: PaginateModes;
|
|
76
|
+
/**
|
|
77
|
+
* Prevents the runtime from deduplicating pagination requests
|
|
78
|
+
*/
|
|
79
|
+
supressPaginationDeduplication?: boolean;
|
|
76
80
|
/**
|
|
77
81
|
* A list of fields to use when computing a record’s id. The default value is ['id']. For more information: https://www.houdinigraphql.com/guides/caching-data#custom-ids
|
|
78
82
|
*/
|
|
@@ -95,7 +99,7 @@ export type ConfigFile = {
|
|
|
95
99
|
*/
|
|
96
100
|
watchSchema?: WatchSchemaConfig;
|
|
97
101
|
/**
|
|
98
|
-
* Specifies the the persisted queries path and file. (default:
|
|
102
|
+
* Specifies the the persisted queries path and file. (default: `<rootDir>/persisted_queries.json`)
|
|
99
103
|
*/
|
|
100
104
|
persistedQueriesPath?: string;
|
|
101
105
|
/**
|
|
@@ -107,6 +111,11 @@ export type ConfigFile = {
|
|
|
107
111
|
* @default process.cwd()
|
|
108
112
|
*/
|
|
109
113
|
projectDir?: string;
|
|
114
|
+
/**
|
|
115
|
+
* The relative path from your project directory pointing to your output directory.
|
|
116
|
+
* @default `$houdini`
|
|
117
|
+
*/
|
|
118
|
+
runtimeDir?: string;
|
|
110
119
|
/**
|
|
111
120
|
* For now, the cache's imperative API is considered unstable. In order to suppress the warning,
|
|
112
121
|
* you must enable this flag.
|
|
@@ -7,6 +7,12 @@ export declare const CachePolicy: {
|
|
|
7
7
|
readonly NoCache: "NoCache";
|
|
8
8
|
};
|
|
9
9
|
export type CachePolicies = ValuesOf<typeof CachePolicy>;
|
|
10
|
+
export declare const DedupeMatchMode: {
|
|
11
|
+
readonly Variables: "Variables";
|
|
12
|
+
readonly Operation: "Operation";
|
|
13
|
+
readonly None: "None";
|
|
14
|
+
};
|
|
15
|
+
export type DedupeMatchModes = ValuesOf<typeof DedupeMatchMode>;
|
|
10
16
|
export declare const PaginateMode: {
|
|
11
17
|
readonly Infinite: "Infinite";
|
|
12
18
|
readonly SinglePage: "SinglePage";
|
|
@@ -60,11 +66,17 @@ export type QueryArtifact = BaseCompiledDocument<'HoudiniQuery'> & {
|
|
|
60
66
|
policy?: CachePolicies;
|
|
61
67
|
partial?: boolean;
|
|
62
68
|
enableLoadingState?: 'global' | 'local';
|
|
63
|
-
dedupe?:
|
|
69
|
+
dedupe?: {
|
|
70
|
+
cancel: 'first' | 'last';
|
|
71
|
+
match: DedupeMatchModes;
|
|
72
|
+
};
|
|
64
73
|
};
|
|
65
74
|
export type MutationArtifact = BaseCompiledDocument<'HoudiniMutation'> & {
|
|
66
75
|
optimisticKeys?: boolean;
|
|
67
|
-
dedupe?:
|
|
76
|
+
dedupe?: {
|
|
77
|
+
cancel: 'first' | 'last';
|
|
78
|
+
match: DedupeMatchModes;
|
|
79
|
+
};
|
|
68
80
|
};
|
|
69
81
|
export type FragmentArtifact = BaseCompiledDocument<'HoudiniFragment'> & {
|
|
70
82
|
enableLoadingState?: 'global' | 'local';
|
|
@@ -26,6 +26,7 @@ __export(types_exports, {
|
|
|
26
26
|
CompiledQueryKind: () => CompiledQueryKind,
|
|
27
27
|
CompiledSubscriptionKind: () => CompiledSubscriptionKind,
|
|
28
28
|
DataSource: () => DataSource,
|
|
29
|
+
DedupeMatchMode: () => DedupeMatchMode,
|
|
29
30
|
PaginateMode: () => PaginateMode,
|
|
30
31
|
PendingValue: () => PendingValue,
|
|
31
32
|
RefetchUpdateMode: () => RefetchUpdateMode,
|
|
@@ -41,6 +42,11 @@ const CachePolicy = {
|
|
|
41
42
|
CacheAndNetwork: "CacheAndNetwork",
|
|
42
43
|
NoCache: "NoCache"
|
|
43
44
|
};
|
|
45
|
+
const DedupeMatchMode = {
|
|
46
|
+
Variables: "Variables",
|
|
47
|
+
Operation: "Operation",
|
|
48
|
+
None: "None"
|
|
49
|
+
};
|
|
44
50
|
const PaginateMode = {
|
|
45
51
|
Infinite: "Infinite",
|
|
46
52
|
SinglePage: "SinglePage"
|
|
@@ -79,6 +85,7 @@ function isPending(value) {
|
|
|
79
85
|
CompiledQueryKind,
|
|
80
86
|
CompiledSubscriptionKind,
|
|
81
87
|
DataSource,
|
|
88
|
+
DedupeMatchMode,
|
|
82
89
|
PaginateMode,
|
|
83
90
|
PendingValue,
|
|
84
91
|
RefetchUpdateMode,
|
|
@@ -2,7 +2,7 @@ import { getCurrentConfig } from "../lib/config";
|
|
|
2
2
|
import { deepEquals } from "../lib/deepEquals";
|
|
3
3
|
import { marshalInputs } from "../lib/scalars";
|
|
4
4
|
import { Writable } from "../lib/store";
|
|
5
|
-
import { ArtifactKind } from "../lib/types";
|
|
5
|
+
import { ArtifactKind, DedupeMatchMode } from "../lib/types";
|
|
6
6
|
import { cachePolicy } from "./plugins";
|
|
7
7
|
const steps = {
|
|
8
8
|
forward: ["start", "beforeNetwork", "network"],
|
|
@@ -19,7 +19,8 @@ class DocumentStore extends Writable {
|
|
|
19
19
|
pendingPromise = null;
|
|
20
20
|
serverSideFallback;
|
|
21
21
|
controllerKey(variables) {
|
|
22
|
-
|
|
22
|
+
const usedVariables = "dedupe" in this.artifact && this.artifact.dedupe?.match !== DedupeMatchMode.Variables ? {} : variables;
|
|
23
|
+
return `${this.artifact.name}@${stableStringify(usedVariables)}`;
|
|
23
24
|
}
|
|
24
25
|
constructor({
|
|
25
26
|
artifact,
|
|
@@ -81,16 +82,20 @@ class DocumentStore extends Writable {
|
|
|
81
82
|
silenceEcho = false,
|
|
82
83
|
abortController = new AbortController()
|
|
83
84
|
} = {}) {
|
|
84
|
-
if ("dedupe" in this.artifact) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
inflightRequests[
|
|
85
|
+
if ("dedupe" in this.artifact && this.artifact.dedupe && this.artifact.dedupe.match !== "None") {
|
|
86
|
+
const dedupeKey = this.controllerKey(variables);
|
|
87
|
+
if (inflightRequests[dedupeKey]) {
|
|
88
|
+
if (this.artifact.dedupe.cancel === "first") {
|
|
89
|
+
inflightRequests[dedupeKey].controller.abort();
|
|
90
|
+
inflightRequests[dedupeKey].controller = abortController;
|
|
89
91
|
} else {
|
|
90
92
|
abortController.abort();
|
|
91
93
|
}
|
|
92
94
|
} else {
|
|
93
|
-
inflightRequests[
|
|
95
|
+
inflightRequests[dedupeKey] = {
|
|
96
|
+
variables,
|
|
97
|
+
controller: abortController
|
|
98
|
+
};
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
let context = new ClientPluginContextWrapper({
|
|
@@ -412,6 +417,21 @@ function marshalVariables(ctx) {
|
|
|
412
417
|
function variablesChanged(ctx) {
|
|
413
418
|
return ctx.stuff.inputs?.changed;
|
|
414
419
|
}
|
|
420
|
+
function stableStringify(obj) {
|
|
421
|
+
return JSON.stringify(sortObject(obj));
|
|
422
|
+
}
|
|
423
|
+
function sortObject(obj) {
|
|
424
|
+
if (obj === null || typeof obj !== "object") {
|
|
425
|
+
return obj;
|
|
426
|
+
}
|
|
427
|
+
if (Array.isArray(obj)) {
|
|
428
|
+
return obj.map(sortObject);
|
|
429
|
+
}
|
|
430
|
+
return Object.keys(obj).sort().reduce((result, key) => {
|
|
431
|
+
result[key] = sortObject(obj[key]);
|
|
432
|
+
return result;
|
|
433
|
+
}, {});
|
|
434
|
+
}
|
|
415
435
|
export {
|
|
416
436
|
DocumentStore
|
|
417
437
|
};
|
|
@@ -66,6 +66,11 @@ const defaultFetch = (url, params) => {
|
|
|
66
66
|
...params?.headers
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
|
+
if (!result.ok && result.headers.get("content-type") !== "application/json" && result.headers.get("content-type") !== "application/graphql+json") {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Failed to fetch: server returned invalid response with error ${result.status}: ${result.statusText}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
69
74
|
return await result.json();
|
|
70
75
|
};
|
|
71
76
|
};
|
|
@@ -73,6 +73,10 @@ export type ConfigFile = {
|
|
|
73
73
|
* Specifies whether the default paginate mode is Infinite or SinglePage. (default: `Infinite`)
|
|
74
74
|
*/
|
|
75
75
|
defaultPaginateMode?: PaginateModes;
|
|
76
|
+
/**
|
|
77
|
+
* Prevents the runtime from deduplicating pagination requests
|
|
78
|
+
*/
|
|
79
|
+
supressPaginationDeduplication?: boolean;
|
|
76
80
|
/**
|
|
77
81
|
* A list of fields to use when computing a record’s id. The default value is ['id']. For more information: https://www.houdinigraphql.com/guides/caching-data#custom-ids
|
|
78
82
|
*/
|
|
@@ -95,7 +99,7 @@ export type ConfigFile = {
|
|
|
95
99
|
*/
|
|
96
100
|
watchSchema?: WatchSchemaConfig;
|
|
97
101
|
/**
|
|
98
|
-
* Specifies the the persisted queries path and file. (default:
|
|
102
|
+
* Specifies the the persisted queries path and file. (default: `<rootDir>/persisted_queries.json`)
|
|
99
103
|
*/
|
|
100
104
|
persistedQueriesPath?: string;
|
|
101
105
|
/**
|
|
@@ -107,6 +111,11 @@ export type ConfigFile = {
|
|
|
107
111
|
* @default process.cwd()
|
|
108
112
|
*/
|
|
109
113
|
projectDir?: string;
|
|
114
|
+
/**
|
|
115
|
+
* The relative path from your project directory pointing to your output directory.
|
|
116
|
+
* @default `$houdini`
|
|
117
|
+
*/
|
|
118
|
+
runtimeDir?: string;
|
|
110
119
|
/**
|
|
111
120
|
* For now, the cache's imperative API is considered unstable. In order to suppress the warning,
|
|
112
121
|
* you must enable this flag.
|