@isograph/react 0.0.0-main-fbe23de7 → 0.0.0-main-c6a74674
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/dist/core/FragmentReference.d.ts +1 -0
- package/dist/core/FragmentReference.js +15 -0
- package/dist/core/read.js +45 -25
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/react/useReadAndSubscribe.d.ts +6 -2
- package/dist/react/useReadAndSubscribe.js +25 -2
- package/package.json +3 -3
- package/src/core/FragmentReference.ts +16 -0
- package/src/core/read.ts +59 -37
- package/src/index.ts +1 -0
- package/src/react/useReadAndSubscribe.ts +41 -3
@@ -14,3 +14,4 @@ export type FragmentReference<TReadFromStore extends Object, TClientFieldValue>
|
|
14
14
|
readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
|
15
15
|
readonly networkRequest: PromiseWrapper<void, any>;
|
16
16
|
};
|
17
|
+
export declare function stableIdForFragmentReference(fragmentReference: FragmentReference<any, any>): string;
|
@@ -1,2 +1,17 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.stableIdForFragmentReference = void 0;
|
4
|
+
function stableIdForFragmentReference(fragmentReference) {
|
5
|
+
var _a;
|
6
|
+
return `${fragmentReference.root}/TODO_FRAGMENT_NAME/${serializeVariables((_a = fragmentReference.variables) !== null && _a !== void 0 ? _a : {})}`;
|
7
|
+
}
|
8
|
+
exports.stableIdForFragmentReference = stableIdForFragmentReference;
|
9
|
+
function serializeVariables(variables) {
|
10
|
+
let s = '';
|
11
|
+
const keys = Object.keys(variables);
|
12
|
+
keys.sort();
|
13
|
+
for (const key of keys) {
|
14
|
+
s += `${key}:${variables[key]},`;
|
15
|
+
}
|
16
|
+
return s;
|
17
|
+
}
|
package/dist/core/read.js
CHANGED
@@ -228,31 +228,37 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
|
|
228
228
|
};
|
229
229
|
}
|
230
230
|
else {
|
231
|
-
target[field.alias] = (args) =>
|
232
|
-
//
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
231
|
+
target[field.alias] = (args) => {
|
232
|
+
// TODO we should use the reader AST for this
|
233
|
+
const includeReadOutData = (variables, readOutData) => {
|
234
|
+
variables.id = readOutData.id;
|
235
|
+
return variables;
|
236
|
+
};
|
237
|
+
const localVariables = includeReadOutData(args !== null && args !== void 0 ? args : {}, refetchReaderParams.data);
|
238
|
+
writeQueryArgsToVariables(localVariables, field.queryArguments, variables);
|
239
|
+
return [
|
240
|
+
// Stable id
|
241
|
+
root +
|
242
|
+
'/' +
|
243
|
+
field.name +
|
244
|
+
'/' +
|
245
|
+
stableStringifyArgs(localVariables),
|
246
|
+
// Fetcher
|
247
|
+
() => {
|
248
|
+
const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.makeNetworkRequest)(environment, field.entrypoint, localVariables);
|
249
|
+
const fragmentReference = {
|
250
|
+
kind: 'FragmentReference',
|
251
|
+
readerArtifact: field.entrypoint.readerArtifact,
|
252
|
+
// TODO localVariables is not guaranteed to have an id field
|
253
|
+
root: localVariables.id,
|
254
|
+
variables: localVariables,
|
255
|
+
nestedRefetchQueries: field.entrypoint.nestedRefetchQueries,
|
256
|
+
networkRequest,
|
257
|
+
};
|
258
|
+
return [fragmentReference, disposeNetworkRequest];
|
259
|
+
},
|
260
|
+
];
|
261
|
+
};
|
256
262
|
}
|
257
263
|
break;
|
258
264
|
}
|
@@ -323,3 +329,17 @@ function writeQueryArgsToVariables(targetVariables, queryArgs, variables) {
|
|
323
329
|
}
|
324
330
|
}
|
325
331
|
}
|
332
|
+
// TODO use a description of the params for this?
|
333
|
+
// TODO call stableStringifyArgs on the variable values, as well.
|
334
|
+
// This doesn't matter for now, since we are just using primitive values
|
335
|
+
// in the demo.
|
336
|
+
function stableStringifyArgs(args) {
|
337
|
+
const keys = Object.keys(args);
|
338
|
+
keys.sort();
|
339
|
+
let s = '';
|
340
|
+
for (const key of keys) {
|
341
|
+
// @ts-expect-error
|
342
|
+
s += `${key}=${JSON.stringify(args[key])};`;
|
343
|
+
}
|
344
|
+
return s;
|
345
|
+
}
|
package/dist/index.d.ts
CHANGED
@@ -7,7 +7,7 @@ export { type EagerReaderArtifact, type ComponentReaderArtifact, type RefetchRea
|
|
7
7
|
export { type NormalizationAst, type NormalizationAstNode, type NormalizationLinkedField, type NormalizationScalarField, type IsographEntrypoint, assertIsEntrypoint, type RefetchQueryNormalizationArtifact, type RefetchQueryNormalizationArtifactWrapper, type ExtractProps, type ExtractReadFromStore, type ExtractResolverResult, } from './core/entrypoint';
|
8
8
|
export { readButDoNotEvaluate } from './core/read';
|
9
9
|
export { type ExtractSecondParam, type Argument, type ArgumentName, type ArgumentValue, type Arguments, } from './core/util';
|
10
|
-
export { type FragmentReference, type Variables, } from './core/FragmentReference';
|
10
|
+
export { type FragmentReference, type Variables, stableIdForFragmentReference, } from './core/FragmentReference';
|
11
11
|
export { IsographEnvironmentProvider, useIsographEnvironment, type IsographEnvironmentProviderProps, } from './react/IsographEnvironmentProvider';
|
12
12
|
export { useImperativeReference } from './react/useImperativeReference';
|
13
13
|
export { FragmentReader } from './react/FragmentReader';
|
package/dist/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.useClientSideDefer = exports.useRerenderOnChange = exports.useLazyReference = exports.useResult = exports.FragmentReader = exports.useImperativeReference = exports.useIsographEnvironment = exports.IsographEnvironmentProvider = exports.readButDoNotEvaluate = exports.assertIsEntrypoint = exports.defaultMissingFieldHandler = exports.createIsographStore = exports.createIsographEnvironment = exports.ROOT_ID = exports.makeNetworkRequest = exports.normalizeData = exports.subscribe = exports.getPromiseState = exports.readPromise = exports.garbageCollectEnvironment = exports.unretainQuery = exports.retainQuery = void 0;
|
3
|
+
exports.useClientSideDefer = exports.useRerenderOnChange = exports.useLazyReference = exports.useResult = exports.FragmentReader = exports.useImperativeReference = exports.useIsographEnvironment = exports.IsographEnvironmentProvider = exports.stableIdForFragmentReference = exports.readButDoNotEvaluate = exports.assertIsEntrypoint = exports.defaultMissingFieldHandler = exports.createIsographStore = exports.createIsographEnvironment = exports.ROOT_ID = exports.makeNetworkRequest = exports.normalizeData = exports.subscribe = exports.getPromiseState = exports.readPromise = exports.garbageCollectEnvironment = exports.unretainQuery = exports.retainQuery = void 0;
|
4
4
|
var garbageCollection_1 = require("./core/garbageCollection");
|
5
5
|
Object.defineProperty(exports, "retainQuery", { enumerable: true, get: function () { return garbageCollection_1.retainQuery; } });
|
6
6
|
Object.defineProperty(exports, "unretainQuery", { enumerable: true, get: function () { return garbageCollection_1.unretainQuery; } });
|
@@ -22,6 +22,8 @@ var entrypoint_1 = require("./core/entrypoint");
|
|
22
22
|
Object.defineProperty(exports, "assertIsEntrypoint", { enumerable: true, get: function () { return entrypoint_1.assertIsEntrypoint; } });
|
23
23
|
var read_1 = require("./core/read");
|
24
24
|
Object.defineProperty(exports, "readButDoNotEvaluate", { enumerable: true, get: function () { return read_1.readButDoNotEvaluate; } });
|
25
|
+
var FragmentReference_1 = require("./core/FragmentReference");
|
26
|
+
Object.defineProperty(exports, "stableIdForFragmentReference", { enumerable: true, get: function () { return FragmentReference_1.stableIdForFragmentReference; } });
|
25
27
|
var IsographEnvironmentProvider_1 = require("./react/IsographEnvironmentProvider");
|
26
28
|
Object.defineProperty(exports, "IsographEnvironmentProvider", { enumerable: true, get: function () { return IsographEnvironmentProvider_1.IsographEnvironmentProvider; } });
|
27
29
|
Object.defineProperty(exports, "useIsographEnvironment", { enumerable: true, get: function () { return IsographEnvironmentProvider_1.useIsographEnvironment; } });
|
@@ -1,7 +1,11 @@
|
|
1
1
|
import { FragmentReference } from '../core/FragmentReference';
|
2
|
-
import { NetworkRequestReaderOptions } from '../core/read';
|
2
|
+
import { NetworkRequestReaderOptions, WithEncounteredRecords } from '../core/read';
|
3
3
|
/**
|
4
4
|
* Read the data from a fragment reference and subscribe to updates.
|
5
|
-
* Does not pass the data to the fragment reference's resolver function.
|
6
5
|
*/
|
7
6
|
export declare function useReadAndSubscribe<TReadFromStore extends Object>(fragmentReference: FragmentReference<TReadFromStore, any>, networkRequestOptions: NetworkRequestReaderOptions): TReadFromStore;
|
7
|
+
export declare function useSubscribeToMultiple<TReadFromStore extends Object>(items: ReadonlyArray<{
|
8
|
+
records: WithEncounteredRecords<TReadFromStore>;
|
9
|
+
callback: (updatedRecords: WithEncounteredRecords<TReadFromStore>) => void;
|
10
|
+
fragmentReference: FragmentReference<TReadFromStore, any>;
|
11
|
+
}>): void;
|
@@ -1,13 +1,14 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.useReadAndSubscribe = void 0;
|
3
|
+
exports.useSubscribeToMultiple = exports.useReadAndSubscribe = void 0;
|
4
4
|
const react_1 = require("react");
|
5
|
+
const FragmentReference_1 = require("../core/FragmentReference");
|
5
6
|
const read_1 = require("../core/read");
|
6
7
|
const useRerenderOnChange_1 = require("./useRerenderOnChange");
|
7
8
|
const IsographEnvironmentProvider_1 = require("./IsographEnvironmentProvider");
|
9
|
+
const cache_1 = require("../core/cache");
|
8
10
|
/**
|
9
11
|
* Read the data from a fragment reference and subscribe to updates.
|
10
|
-
* Does not pass the data to the fragment reference's resolver function.
|
11
12
|
*/
|
12
13
|
function useReadAndSubscribe(fragmentReference, networkRequestOptions) {
|
13
14
|
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
@@ -16,3 +17,25 @@ function useReadAndSubscribe(fragmentReference, networkRequestOptions) {
|
|
16
17
|
return readOutDataAndRecords.item;
|
17
18
|
}
|
18
19
|
exports.useReadAndSubscribe = useReadAndSubscribe;
|
20
|
+
function useSubscribeToMultiple(items) {
|
21
|
+
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
22
|
+
(0, react_1.useEffect)(() => {
|
23
|
+
const cleanupFns = items.map(({ records, callback, fragmentReference }) => {
|
24
|
+
return (0, cache_1.subscribe)(environment, records, fragmentReference, callback);
|
25
|
+
});
|
26
|
+
return () => {
|
27
|
+
cleanupFns.forEach((loader) => {
|
28
|
+
loader();
|
29
|
+
});
|
30
|
+
};
|
31
|
+
},
|
32
|
+
// By analogy to useReadAndSubscribe, we can have an empty dependency array?
|
33
|
+
// Maybe callback has to be depended on. I don't know!
|
34
|
+
// TODO find out
|
35
|
+
[
|
36
|
+
items
|
37
|
+
.map(({ fragmentReference }) => (0, FragmentReference_1.stableIdForFragmentReference)(fragmentReference))
|
38
|
+
.join('.'),
|
39
|
+
]);
|
40
|
+
}
|
41
|
+
exports.useSubscribeToMultiple = useSubscribeToMultiple;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@isograph/react",
|
3
|
-
"version": "0.0.0-main-
|
3
|
+
"version": "0.0.0-main-c6a74674",
|
4
4
|
"description": "Use Isograph with React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -17,8 +17,8 @@
|
|
17
17
|
"tsc": "tsc"
|
18
18
|
},
|
19
19
|
"dependencies": {
|
20
|
-
"@isograph/disposable-types": "0.0.0-main-
|
21
|
-
"@isograph/react-disposable-state": "0.0.0-main-
|
20
|
+
"@isograph/disposable-types": "0.0.0-main-c6a74674",
|
21
|
+
"@isograph/react-disposable-state": "0.0.0-main-c6a74674",
|
22
22
|
"react": "^18.2.0"
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
@@ -24,3 +24,19 @@ export type FragmentReference<
|
|
24
24
|
readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
|
25
25
|
readonly networkRequest: PromiseWrapper<void, any>;
|
26
26
|
};
|
27
|
+
|
28
|
+
export function stableIdForFragmentReference(
|
29
|
+
fragmentReference: FragmentReference<any, any>,
|
30
|
+
): string {
|
31
|
+
return `${fragmentReference.root}/TODO_FRAGMENT_NAME/${serializeVariables(fragmentReference.variables ?? {})}`;
|
32
|
+
}
|
33
|
+
|
34
|
+
function serializeVariables(variables: Variables) {
|
35
|
+
let s = '';
|
36
|
+
const keys = Object.keys(variables);
|
37
|
+
keys.sort();
|
38
|
+
for (const key of keys) {
|
39
|
+
s += `${key}:${variables[key]},`;
|
40
|
+
}
|
41
|
+
return s;
|
42
|
+
}
|
package/src/core/read.ts
CHANGED
@@ -338,43 +338,50 @@ function readData<TReadFromStore>(
|
|
338
338
|
nestedReason: refetchReaderParams,
|
339
339
|
};
|
340
340
|
} else {
|
341
|
-
target[field.alias] = (args: any) =>
|
342
|
-
//
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
341
|
+
target[field.alias] = (args: any) => {
|
342
|
+
// TODO we should use the reader AST for this
|
343
|
+
const includeReadOutData = (variables: any, readOutData: any) => {
|
344
|
+
variables.id = readOutData.id;
|
345
|
+
return variables;
|
346
|
+
};
|
347
|
+
const localVariables = includeReadOutData(
|
348
|
+
args ?? {},
|
349
|
+
refetchReaderParams.data,
|
350
|
+
);
|
351
|
+
writeQueryArgsToVariables(
|
352
|
+
localVariables,
|
353
|
+
field.queryArguments,
|
354
|
+
variables,
|
355
|
+
);
|
356
|
+
|
357
|
+
return [
|
358
|
+
// Stable id
|
359
|
+
root +
|
360
|
+
'/' +
|
361
|
+
field.name +
|
362
|
+
'/' +
|
363
|
+
stableStringifyArgs(localVariables),
|
364
|
+
// Fetcher
|
365
|
+
() => {
|
366
|
+
const [networkRequest, disposeNetworkRequest] =
|
367
|
+
makeNetworkRequest(
|
368
|
+
environment,
|
369
|
+
field.entrypoint,
|
370
|
+
localVariables,
|
371
|
+
);
|
372
|
+
const fragmentReference = {
|
373
|
+
kind: 'FragmentReference',
|
374
|
+
readerArtifact: field.entrypoint.readerArtifact,
|
375
|
+
// TODO localVariables is not guaranteed to have an id field
|
376
|
+
root: localVariables.id,
|
377
|
+
variables: localVariables,
|
378
|
+
nestedRefetchQueries: field.entrypoint.nestedRefetchQueries,
|
379
|
+
networkRequest,
|
380
|
+
} as FragmentReference<any, any>;
|
381
|
+
return [fragmentReference, disposeNetworkRequest];
|
382
|
+
},
|
383
|
+
];
|
384
|
+
};
|
378
385
|
}
|
379
386
|
break;
|
380
387
|
}
|
@@ -464,3 +471,18 @@ export type NetworkRequestReaderOptions = {
|
|
464
471
|
suspendIfInFlight?: boolean;
|
465
472
|
throwOnNetworkError?: boolean;
|
466
473
|
};
|
474
|
+
|
475
|
+
// TODO use a description of the params for this?
|
476
|
+
// TODO call stableStringifyArgs on the variable values, as well.
|
477
|
+
// This doesn't matter for now, since we are just using primitive values
|
478
|
+
// in the demo.
|
479
|
+
function stableStringifyArgs(args: Object) {
|
480
|
+
const keys = Object.keys(args);
|
481
|
+
keys.sort();
|
482
|
+
let s = '';
|
483
|
+
for (const key of keys) {
|
484
|
+
// @ts-expect-error
|
485
|
+
s += `${key}=${JSON.stringify(args[key])};`;
|
486
|
+
}
|
487
|
+
return s;
|
488
|
+
}
|
package/src/index.ts
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
import { useState } from 'react';
|
2
|
-
import {
|
1
|
+
import { useEffect, useState } from 'react';
|
2
|
+
import {
|
3
|
+
FragmentReference,
|
4
|
+
stableIdForFragmentReference,
|
5
|
+
} from '../core/FragmentReference';
|
3
6
|
import {
|
4
7
|
NetworkRequestReaderOptions,
|
5
8
|
readButDoNotEvaluate,
|
9
|
+
WithEncounteredRecords,
|
6
10
|
} from '../core/read';
|
7
11
|
import { useRerenderOnChange } from './useRerenderOnChange';
|
8
12
|
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
13
|
+
import { subscribe } from '../core/cache';
|
9
14
|
|
10
15
|
/**
|
11
16
|
* Read the data from a fragment reference and subscribe to updates.
|
12
|
-
* Does not pass the data to the fragment reference's resolver function.
|
13
17
|
*/
|
14
18
|
export function useReadAndSubscribe<TReadFromStore extends Object>(
|
15
19
|
fragmentReference: FragmentReference<TReadFromStore, any>,
|
@@ -26,3 +30,37 @@ export function useReadAndSubscribe<TReadFromStore extends Object>(
|
|
26
30
|
);
|
27
31
|
return readOutDataAndRecords.item;
|
28
32
|
}
|
33
|
+
|
34
|
+
export function useSubscribeToMultiple<TReadFromStore extends Object>(
|
35
|
+
items: ReadonlyArray<{
|
36
|
+
records: WithEncounteredRecords<TReadFromStore>;
|
37
|
+
callback: (updatedRecords: WithEncounteredRecords<TReadFromStore>) => void;
|
38
|
+
fragmentReference: FragmentReference<TReadFromStore, any>;
|
39
|
+
}>,
|
40
|
+
) {
|
41
|
+
const environment = useIsographEnvironment();
|
42
|
+
useEffect(
|
43
|
+
() => {
|
44
|
+
const cleanupFns = items.map(
|
45
|
+
({ records, callback, fragmentReference }) => {
|
46
|
+
return subscribe(environment, records, fragmentReference, callback);
|
47
|
+
},
|
48
|
+
);
|
49
|
+
return () => {
|
50
|
+
cleanupFns.forEach((loader) => {
|
51
|
+
loader();
|
52
|
+
});
|
53
|
+
};
|
54
|
+
},
|
55
|
+
// By analogy to useReadAndSubscribe, we can have an empty dependency array?
|
56
|
+
// Maybe callback has to be depended on. I don't know!
|
57
|
+
// TODO find out
|
58
|
+
[
|
59
|
+
items
|
60
|
+
.map(({ fragmentReference }) =>
|
61
|
+
stableIdForFragmentReference(fragmentReference),
|
62
|
+
)
|
63
|
+
.join('.'),
|
64
|
+
],
|
65
|
+
);
|
66
|
+
}
|