houdini 1.0.0-next.4 → 1.0.0-next.5

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.
Files changed (78) hide show
  1. package/build/cmd-cjs/index.js +1217 -1021
  2. package/build/cmd-esm/index.js +1217 -1021
  3. package/build/codegen/generators/artifacts/utils.d.ts +0 -1
  4. package/build/codegen-cjs/index.js +810 -676
  5. package/build/codegen-esm/index.js +810 -676
  6. package/build/lib/config.d.ts +10 -90
  7. package/build/lib/deepMerge.d.ts +1 -0
  8. package/build/lib/graphql.d.ts +5 -2
  9. package/build/lib/index.d.ts +2 -0
  10. package/build/lib/pipeline.d.ts +1 -1
  11. package/build/lib/plugin.d.ts +2 -0
  12. package/build/lib/types.d.ts +250 -2
  13. package/build/lib-cjs/index.js +351 -162
  14. package/build/lib-esm/index.js +349 -162
  15. package/build/runtime/cache/cache.d.ts +20 -3
  16. package/build/runtime/cache/staleManager.d.ts +30 -0
  17. package/build/runtime/cache/subscription.d.ts +2 -1
  18. package/build/runtime/client/plugins/subscription.d.ts +1 -2
  19. package/build/runtime/lib/config.d.ts +4 -0
  20. package/build/runtime/lib/index.d.ts +1 -0
  21. package/build/runtime/lib/key.d.ts +6 -0
  22. package/build/runtime/lib/types.d.ts +2 -2
  23. package/build/runtime/public/cache.d.ts +8 -1
  24. package/build/runtime/public/record.d.ts +11 -1
  25. package/build/runtime/public/tests/test.d.ts +9 -10
  26. package/build/runtime-cjs/cache/cache.d.ts +20 -3
  27. package/build/runtime-cjs/cache/cache.js +65 -6
  28. package/build/runtime-cjs/cache/gc.js +9 -0
  29. package/build/runtime-cjs/cache/staleManager.d.ts +30 -0
  30. package/build/runtime-cjs/cache/staleManager.js +95 -0
  31. package/build/runtime-cjs/cache/subscription.d.ts +2 -1
  32. package/build/runtime-cjs/cache/subscription.js +6 -3
  33. package/build/runtime-cjs/client/documentStore.js +1 -0
  34. package/build/runtime-cjs/client/plugins/cache.js +5 -3
  35. package/build/runtime-cjs/client/plugins/fetch.js +1 -0
  36. package/build/runtime-cjs/client/plugins/query.js +1 -0
  37. package/build/runtime-cjs/client/plugins/subscription.d.ts +1 -2
  38. package/build/runtime-cjs/client/plugins/subscription.js +2 -0
  39. package/build/runtime-cjs/lib/config.d.ts +4 -0
  40. package/build/runtime-cjs/lib/index.d.ts +1 -0
  41. package/build/runtime-cjs/lib/index.js +1 -0
  42. package/build/runtime-cjs/lib/key.d.ts +6 -0
  43. package/build/runtime-cjs/lib/key.js +41 -0
  44. package/build/runtime-cjs/lib/types.d.ts +2 -2
  45. package/build/runtime-cjs/public/cache.d.ts +8 -1
  46. package/build/runtime-cjs/public/cache.js +3 -0
  47. package/build/runtime-cjs/public/record.d.ts +11 -1
  48. package/build/runtime-cjs/public/record.js +8 -1
  49. package/build/runtime-cjs/public/tests/test.d.ts +9 -10
  50. package/build/runtime-esm/cache/cache.d.ts +20 -3
  51. package/build/runtime-esm/cache/cache.js +66 -7
  52. package/build/runtime-esm/cache/gc.js +9 -0
  53. package/build/runtime-esm/cache/staleManager.d.ts +30 -0
  54. package/build/runtime-esm/cache/staleManager.js +71 -0
  55. package/build/runtime-esm/cache/subscription.d.ts +2 -1
  56. package/build/runtime-esm/cache/subscription.js +6 -3
  57. package/build/runtime-esm/client/documentStore.js +1 -0
  58. package/build/runtime-esm/client/plugins/cache.js +5 -3
  59. package/build/runtime-esm/client/plugins/fetch.js +1 -0
  60. package/build/runtime-esm/client/plugins/query.js +1 -0
  61. package/build/runtime-esm/client/plugins/subscription.d.ts +1 -2
  62. package/build/runtime-esm/client/plugins/subscription.js +2 -0
  63. package/build/runtime-esm/lib/config.d.ts +4 -0
  64. package/build/runtime-esm/lib/index.d.ts +1 -0
  65. package/build/runtime-esm/lib/index.js +1 -0
  66. package/build/runtime-esm/lib/key.d.ts +6 -0
  67. package/build/runtime-esm/lib/key.js +17 -0
  68. package/build/runtime-esm/lib/types.d.ts +2 -2
  69. package/build/runtime-esm/public/cache.d.ts +8 -1
  70. package/build/runtime-esm/public/cache.js +3 -0
  71. package/build/runtime-esm/public/record.d.ts +11 -1
  72. package/build/runtime-esm/public/record.js +8 -1
  73. package/build/runtime-esm/public/tests/test.d.ts +9 -10
  74. package/build/test-cjs/index.js +893 -747
  75. package/build/test-esm/index.js +893 -747
  76. package/build/vite-cjs/index.js +1195 -998
  77. package/build/vite-esm/index.js +1195 -998
  78. package/package.json +3 -2
@@ -4,9 +4,10 @@ import { GarbageCollector } from './gc';
4
4
  import type { ListCollection } from './lists';
5
5
  import { ListManager } from './lists';
6
6
  import { SchemaManager } from './schema';
7
+ import { StaleManager } from './staleManager';
7
8
  import type { Layer, LayerID } from './storage';
8
9
  import { InMemoryStorage } from './storage';
9
- import { type FieldSelection, InMemorySubscriptions } from './subscription';
10
+ import { InMemorySubscriptions, type FieldSelection } from './subscription';
10
11
  export declare class Cache {
11
12
  _internal_unstable: CacheInternal;
12
13
  constructor(config?: ConfigFile);
@@ -21,16 +22,27 @@ export declare class Cache {
21
22
  applyUpdates?: string[];
22
23
  notifySubscribers?: SubscriptionSpec[];
23
24
  forceNotify?: boolean;
25
+ forceStale?: boolean;
24
26
  }): SubscriptionSpec[];
25
27
  read(...args: Parameters<CacheInternal['getSelection']>): {
26
28
  data: GraphQLObject | null;
27
29
  partial: boolean;
30
+ stale: boolean;
28
31
  };
29
32
  subscribe(spec: SubscriptionSpec, variables?: {}): void;
30
33
  unsubscribe(spec: SubscriptionSpec, variables?: {}): void;
31
34
  list(name: string, parentID?: string, allLists?: boolean): ListCollection;
32
35
  delete(id: string): void;
33
36
  setConfig(config: ConfigFile): void;
37
+ markTypeStale(type?: string, options?: {
38
+ field?: string;
39
+ when?: {};
40
+ }): void;
41
+ markRecordStale(id: string, options: {
42
+ field?: string;
43
+ when?: {};
44
+ }): void;
45
+ getFieldTime(id: string, field: string): number | null | undefined;
34
46
  }
35
47
  declare class CacheInternal {
36
48
  private _disabled;
@@ -40,17 +52,19 @@ declare class CacheInternal {
40
52
  lists: ListManager;
41
53
  cache: Cache;
42
54
  lifetimes: GarbageCollector;
55
+ staleManager: StaleManager;
43
56
  schema: SchemaManager;
44
- constructor({ storage, subscriptions, lists, cache, lifetimes, schema, }: {
57
+ constructor({ storage, subscriptions, lists, cache, lifetimes, staleManager, schema, }: {
45
58
  storage: InMemoryStorage;
46
59
  subscriptions: InMemorySubscriptions;
47
60
  lists: ListManager;
48
61
  cache: Cache;
49
62
  lifetimes: GarbageCollector;
63
+ staleManager: StaleManager;
50
64
  schema: SchemaManager;
51
65
  });
52
66
  setConfig(config: ConfigFile): void;
53
- writeSelection({ data, selection, variables, parent, applyUpdates, layer, toNotify, forceNotify, }: {
67
+ writeSelection({ data, selection, variables, parent, applyUpdates, layer, toNotify, forceNotify, forceStale, }: {
54
68
  data: {
55
69
  [key: string]: GraphQLValue;
56
70
  };
@@ -64,6 +78,7 @@ declare class CacheInternal {
64
78
  toNotify?: FieldSelection[];
65
79
  applyUpdates?: string[];
66
80
  forceNotify?: boolean;
81
+ forceStale?: boolean;
67
82
  }): FieldSelection[];
68
83
  getSelection({ selection, parent, variables, stepsFromConnection, }: {
69
84
  selection: SubscriptionSelection;
@@ -73,6 +88,7 @@ declare class CacheInternal {
73
88
  }): {
74
89
  data: GraphQLObject | null;
75
90
  partial: boolean;
91
+ stale: boolean;
76
92
  hasData: boolean;
77
93
  };
78
94
  id(type: string, data: {} | null): string | null;
@@ -87,6 +103,7 @@ declare class CacheInternal {
87
103
  }): {
88
104
  data: LinkedList<GraphQLValue>;
89
105
  partial: boolean;
106
+ stale: boolean;
90
107
  hasData: boolean;
91
108
  };
92
109
  extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, forceNotify, }: {
@@ -0,0 +1,30 @@
1
+ import type { Cache } from './cache';
2
+ export declare class StaleManager {
3
+ #private;
4
+ cache: Cache;
5
+ private fieldsTime;
6
+ constructor(cache: Cache);
7
+ /**
8
+ * get the FieldTime info
9
+ * @param id User:1
10
+ * @param field firstName
11
+ */
12
+ getFieldTime(id: string, field: string): number | undefined | null;
13
+ /**
14
+ * set the date to a field
15
+ * @param id User:1
16
+ * @param field firstName
17
+ */
18
+ setFieldTimeToNow(id: string, field: string): void;
19
+ /**
20
+ * set null to a field (stale)
21
+ * @param id User:1
22
+ * @param field firstName
23
+ */
24
+ markFieldStale(id: string, field: string): void;
25
+ markAllStale(): void;
26
+ markRecordStale(id: string): void;
27
+ markTypeStale(type: string): void;
28
+ markTypeFieldStale(type: string, field: string, when?: {}): void;
29
+ delete(id: string, field: string): void;
30
+ }
@@ -19,10 +19,11 @@ export declare class InMemorySubscriptions {
19
19
  [key: string]: GraphQLValue;
20
20
  };
21
21
  }): void;
22
- addFieldSubscription({ id, key, selection, }: {
22
+ addFieldSubscription({ id, key, selection, type, }: {
23
23
  id: string;
24
24
  key: string;
25
25
  selection: FieldSelection;
26
+ type: string;
26
27
  }): void;
27
28
  registerList({ list, id, key, parentType, selection, filters, variables, }: {
28
29
  list: Required<Required<SubscriptionSelection>['fields'][string]>['list'];
@@ -1,4 +1,3 @@
1
- import type { GraphQLObject } from '../../lib/types';
2
1
  import type { ClientPluginContext } from '../documentStore';
3
2
  export declare function subscriptionPlugin(factory: SubscriptionHandler): import("../documentStore").ClientPlugin;
4
3
  export type SubscriptionHandler = (ctx: ClientPluginContext) => {
@@ -7,7 +6,7 @@ export type SubscriptionHandler = (ctx: ClientPluginContext) => {
7
6
  variables?: {};
8
7
  }, handlers: {
9
8
  next: (payload: {
10
- data?: GraphQLObject;
9
+ data?: {} | null;
11
10
  errors?: readonly {
12
11
  message: string;
13
12
  }[];
@@ -55,6 +55,10 @@ export type ConfigFile = {
55
55
  * Specifies whether or not the cache should always use partial data. For more information: https://www.houdinigraphql.com/guides/caching-data#partial-data
56
56
  */
57
57
  defaultPartial?: boolean;
58
+ /**
59
+ * Specifies after how long a data goes stale in miliseconds. (default: `undefined`)
60
+ */
61
+ defaultLifetime?: number;
58
62
  /**
59
63
  * Specifies whether mutations should append or prepend list. For more information: https://www.houdinigraphql.com/api/graphql (default: `append`)
60
64
  */
@@ -5,3 +5,4 @@ export * from './log';
5
5
  export * from './scalars';
6
6
  export * from './types';
7
7
  export * from './store';
8
+ export * from './key';
@@ -0,0 +1,6 @@
1
+ export declare const computeKey: ({ field, args }: {
2
+ field: string;
3
+ args?: {
4
+ [key: string]: any;
5
+ } | undefined;
6
+ }) => string;
@@ -80,7 +80,7 @@ export type BaseCompiledDocument = {
80
80
  paginated: boolean;
81
81
  direction: 'forward' | 'backward' | 'both';
82
82
  };
83
- pluginsData?: Record<string, any>;
83
+ plugin_data?: Record<string, any>;
84
84
  };
85
85
  export type HoudiniFetchContext = {
86
86
  variables: () => {};
@@ -164,7 +164,6 @@ export type SubscriptionSpec = {
164
164
  export type FetchQueryResult<_Data> = {
165
165
  result: RequestPayload<_Data | null>;
166
166
  source: DataSource | null;
167
- partial: boolean;
168
167
  };
169
168
  export type QueryResult<_Data = GraphQLObject, _Input = Record<string, any>> = {
170
169
  data: _Data | null;
@@ -173,6 +172,7 @@ export type QueryResult<_Data = GraphQLObject, _Input = Record<string, any>> = {
173
172
  }[] | null;
174
173
  fetching: boolean;
175
174
  partial: boolean;
175
+ stale: boolean;
176
176
  source: DataSource | null;
177
177
  variables: _Input | null;
178
178
  };
@@ -2,7 +2,7 @@ import type { Cache as _Cache } from '../cache/cache';
2
2
  import { type QueryArtifact } from '../lib';
3
3
  import { ListCollection } from './list';
4
4
  import { Record } from './record';
5
- import type { CacheTypeDef, IDFields, QueryInput, QueryList, QueryValue, TypeNames, ValidLists } from './types';
5
+ import type { ArgType, CacheTypeDef, IDFields, QueryInput, QueryList, QueryValue, TypeFieldNames, TypeNames, ValidLists } from './types';
6
6
  export declare class Cache<Def extends CacheTypeDef> {
7
7
  _internal_unstable: _Cache;
8
8
  constructor(cache: _Cache);
@@ -29,4 +29,11 @@ export declare class Cache<Def extends CacheTypeDef> {
29
29
  data: QueryValue<QueryList<Def>, _Query>;
30
30
  variables?: QueryInput<QueryList<Def>, _Query>;
31
31
  }): void;
32
+ /**
33
+ * Mark some elements of the cache stale.
34
+ */
35
+ markStale<_Type extends TypeNames<Def>, _Field extends TypeFieldNames<Def, _Type>>(type?: _Type, options?: {
36
+ field?: _Field;
37
+ when?: ArgType<Def, _Type, _Field>;
38
+ }): void;
32
39
  }
@@ -1,6 +1,6 @@
1
1
  import type { FragmentArtifact } from '../lib/types';
2
2
  import type { Cache } from './cache';
3
- import type { CacheTypeDef, FragmentList, FragmentValue, FragmentVariables, ValidTypes } from './types';
3
+ import type { ArgType, CacheTypeDef, FragmentList, FragmentValue, FragmentVariables, TypeFieldNames, ValidTypes } from './types';
4
4
  export declare class Record<Def extends CacheTypeDef, Type extends ValidTypes<Def>> {
5
5
  #private;
6
6
  type: string;
@@ -26,6 +26,16 @@ export declare class Record<Def extends CacheTypeDef, Type extends ValidTypes<De
26
26
  fragment: _Fragment;
27
27
  data: FragmentValue<FragmentList<Def, Type>, _Fragment>;
28
28
  variables?: FragmentVariables<FragmentList<Def, Type>, _Fragment>;
29
+ forceStale?: boolean;
29
30
  }): void;
30
31
  delete(): void;
32
+ /**
33
+ * Mark some elements of the record stale in the cache.
34
+ * @param field
35
+ * @param when
36
+ */
37
+ markStale<Field extends TypeFieldNames<Def, Type>>({ field, when, }?: {
38
+ field?: Field;
39
+ when?: ArgType<Def, Type, Field>;
40
+ }): void;
31
41
  }
@@ -1,7 +1,7 @@
1
1
  import { type SubscriptionSelection, type FragmentArtifact, type QueryArtifact } from '../../lib';
2
2
  import { Cache } from '../cache';
3
3
  import type { Record } from '../record';
4
- type CacheTypeDef = {
4
+ export type CacheTypeDefTest = {
5
5
  types: {
6
6
  __ROOT__: {
7
7
  idFields: {};
@@ -16,23 +16,23 @@ type CacheTypeDef = {
16
16
  args: never;
17
17
  };
18
18
  viewer: {
19
- type: Record<CacheTypeDef, 'User'> | null;
19
+ type: Record<CacheTypeDefTest, 'User'> | null;
20
20
  args: never;
21
21
  };
22
22
  pets: {
23
- type: (Record<CacheTypeDef, 'Cat'> | Record<CacheTypeDef, 'User'>)[];
23
+ type: (Record<CacheTypeDefTest, 'Cat'> | Record<CacheTypeDefTest, 'User'>)[];
24
24
  args: never;
25
25
  };
26
26
  listOfLists: {
27
- type: ((Record<CacheTypeDef, 'Cat'> | Record<CacheTypeDef, 'User'> | null | (null | Record<CacheTypeDef, 'User'>)[])[] | Record<CacheTypeDef, 'Cat'> | Record<CacheTypeDef, 'User'> | null)[];
27
+ type: ((Record<CacheTypeDefTest, 'Cat'> | Record<CacheTypeDefTest, 'User'> | null | (null | Record<CacheTypeDefTest, 'User'>)[])[] | Record<CacheTypeDefTest, 'Cat'> | Record<CacheTypeDefTest, 'User'> | null)[];
28
28
  args: never;
29
29
  };
30
30
  users: {
31
- type: Record<CacheTypeDef, 'User'>[] | null;
31
+ type: Record<CacheTypeDefTest, 'User'>[] | null;
32
32
  args: never;
33
33
  };
34
34
  pet: {
35
- type: Record<CacheTypeDef, 'Cat'> | Record<CacheTypeDef, 'User'>;
35
+ type: Record<CacheTypeDefTest, 'Cat'> | Record<CacheTypeDefTest, 'User'>;
36
36
  args: never;
37
37
  };
38
38
  };
@@ -60,7 +60,7 @@ type CacheTypeDef = {
60
60
  args: never;
61
61
  };
62
62
  parent: {
63
- type: Record<CacheTypeDef, 'User'>;
63
+ type: Record<CacheTypeDefTest, 'User'>;
64
64
  args: never;
65
65
  };
66
66
  id: {
@@ -84,7 +84,7 @@ type CacheTypeDef = {
84
84
  args: never;
85
85
  };
86
86
  parent: {
87
- type: Record<CacheTypeDef, 'User'> | null;
87
+ type: Record<CacheTypeDefTest, 'User'> | null;
88
88
  args: never;
89
89
  };
90
90
  id: {
@@ -147,11 +147,10 @@ type CacheTypeDef = {
147
147
  };
148
148
  };
149
149
  };
150
- export declare const testCache: () => Cache<CacheTypeDef>;
150
+ export declare const testCache: () => Cache<CacheTypeDefTest>;
151
151
  export declare const testFragment: (selection: SubscriptionSelection) => {
152
152
  artifact: FragmentArtifact;
153
153
  };
154
154
  export declare const testQuery: (selection: SubscriptionSelection) => {
155
155
  artifact: QueryArtifact;
156
156
  };
157
- export {};
@@ -4,9 +4,10 @@ import { GarbageCollector } from './gc';
4
4
  import type { ListCollection } from './lists';
5
5
  import { ListManager } from './lists';
6
6
  import { SchemaManager } from './schema';
7
+ import { StaleManager } from './staleManager';
7
8
  import type { Layer, LayerID } from './storage';
8
9
  import { InMemoryStorage } from './storage';
9
- import { type FieldSelection, InMemorySubscriptions } from './subscription';
10
+ import { InMemorySubscriptions, type FieldSelection } from './subscription';
10
11
  export declare class Cache {
11
12
  _internal_unstable: CacheInternal;
12
13
  constructor(config?: ConfigFile);
@@ -21,16 +22,27 @@ export declare class Cache {
21
22
  applyUpdates?: string[];
22
23
  notifySubscribers?: SubscriptionSpec[];
23
24
  forceNotify?: boolean;
25
+ forceStale?: boolean;
24
26
  }): SubscriptionSpec[];
25
27
  read(...args: Parameters<CacheInternal['getSelection']>): {
26
28
  data: GraphQLObject | null;
27
29
  partial: boolean;
30
+ stale: boolean;
28
31
  };
29
32
  subscribe(spec: SubscriptionSpec, variables?: {}): void;
30
33
  unsubscribe(spec: SubscriptionSpec, variables?: {}): void;
31
34
  list(name: string, parentID?: string, allLists?: boolean): ListCollection;
32
35
  delete(id: string): void;
33
36
  setConfig(config: ConfigFile): void;
37
+ markTypeStale(type?: string, options?: {
38
+ field?: string;
39
+ when?: {};
40
+ }): void;
41
+ markRecordStale(id: string, options: {
42
+ field?: string;
43
+ when?: {};
44
+ }): void;
45
+ getFieldTime(id: string, field: string): number | null | undefined;
34
46
  }
35
47
  declare class CacheInternal {
36
48
  private _disabled;
@@ -40,17 +52,19 @@ declare class CacheInternal {
40
52
  lists: ListManager;
41
53
  cache: Cache;
42
54
  lifetimes: GarbageCollector;
55
+ staleManager: StaleManager;
43
56
  schema: SchemaManager;
44
- constructor({ storage, subscriptions, lists, cache, lifetimes, schema, }: {
57
+ constructor({ storage, subscriptions, lists, cache, lifetimes, staleManager, schema, }: {
45
58
  storage: InMemoryStorage;
46
59
  subscriptions: InMemorySubscriptions;
47
60
  lists: ListManager;
48
61
  cache: Cache;
49
62
  lifetimes: GarbageCollector;
63
+ staleManager: StaleManager;
50
64
  schema: SchemaManager;
51
65
  });
52
66
  setConfig(config: ConfigFile): void;
53
- writeSelection({ data, selection, variables, parent, applyUpdates, layer, toNotify, forceNotify, }: {
67
+ writeSelection({ data, selection, variables, parent, applyUpdates, layer, toNotify, forceNotify, forceStale, }: {
54
68
  data: {
55
69
  [key: string]: GraphQLValue;
56
70
  };
@@ -64,6 +78,7 @@ declare class CacheInternal {
64
78
  toNotify?: FieldSelection[];
65
79
  applyUpdates?: string[];
66
80
  forceNotify?: boolean;
81
+ forceStale?: boolean;
67
82
  }): FieldSelection[];
68
83
  getSelection({ selection, parent, variables, stepsFromConnection, }: {
69
84
  selection: SubscriptionSelection;
@@ -73,6 +88,7 @@ declare class CacheInternal {
73
88
  }): {
74
89
  data: GraphQLObject | null;
75
90
  partial: boolean;
91
+ stale: boolean;
76
92
  hasData: boolean;
77
93
  };
78
94
  id(type: string, data: {} | null): string | null;
@@ -87,6 +103,7 @@ declare class CacheInternal {
87
103
  }): {
88
104
  data: LinkedList<GraphQLValue>;
89
105
  partial: boolean;
106
+ stale: boolean;
90
107
  hasData: boolean;
91
108
  };
92
109
  extractNestedListIDs({ value, abstract, recordID, key, linkedType, fields, variables, applyUpdates, specs, layer, forceNotify, }: {
@@ -22,12 +22,14 @@ __export(cache_exports, {
22
22
  rootID: () => rootID
23
23
  });
24
24
  module.exports = __toCommonJS(cache_exports);
25
+ var import_lib = require("../lib");
25
26
  var import_config = require("../lib/config");
26
27
  var import_deepEquals = require("../lib/deepEquals");
27
28
  var import_selection = require("../lib/selection");
28
29
  var import_gc = require("./gc");
29
30
  var import_lists = require("./lists");
30
31
  var import_schema = require("./schema");
32
+ var import_staleManager = require("./staleManager");
31
33
  var import_storage = require("./storage");
32
34
  var import_stuff = require("./stuff");
33
35
  var import_subscription = require("./subscription");
@@ -40,6 +42,7 @@ class Cache {
40
42
  subscriptions: new import_subscription.InMemorySubscriptions(this),
41
43
  lists: new import_lists.ListManager(this, rootID),
42
44
  lifetimes: new import_gc.GarbageCollector(this),
45
+ staleManager: new import_staleManager.StaleManager(this),
43
46
  schema: new import_schema.SchemaManager(this)
44
47
  });
45
48
  if (config) {
@@ -69,13 +72,14 @@ class Cache {
69
72
  return subscribers;
70
73
  }
71
74
  read(...args) {
72
- const { data, partial, hasData } = this._internal_unstable.getSelection(...args);
75
+ const { data, partial, stale, hasData } = this._internal_unstable.getSelection(...args);
73
76
  if (!hasData) {
74
- return { data: null, partial: false };
77
+ return { data: null, partial: false, stale: false };
75
78
  }
76
79
  return {
77
80
  data,
78
- partial
81
+ partial,
82
+ stale
79
83
  };
80
84
  }
81
85
  subscribe(spec, variables = {}) {
@@ -111,6 +115,30 @@ class Cache {
111
115
  setConfig(config) {
112
116
  this._internal_unstable.setConfig(config);
113
117
  }
118
+ markTypeStale(type, options = {}) {
119
+ if (!type) {
120
+ this._internal_unstable.staleManager.markAllStale();
121
+ } else if (!options.field) {
122
+ this._internal_unstable.staleManager.markTypeStale(type);
123
+ } else {
124
+ this._internal_unstable.staleManager.markTypeFieldStale(
125
+ type,
126
+ options.field,
127
+ options.when
128
+ );
129
+ }
130
+ }
131
+ markRecordStale(id, options) {
132
+ if (options.field) {
133
+ const key = (0, import_lib.computeKey)({ field: options.field, args: options.when ?? {} });
134
+ this._internal_unstable.staleManager.markFieldStale(id, key);
135
+ } else {
136
+ this._internal_unstable.staleManager.markRecordStale(id);
137
+ }
138
+ }
139
+ getFieldTime(id, field) {
140
+ return this._internal_unstable.staleManager.getFieldTime(id, field);
141
+ }
114
142
  }
115
143
  class CacheInternal {
116
144
  _disabled = false;
@@ -126,6 +154,7 @@ class CacheInternal {
126
154
  lists;
127
155
  cache;
128
156
  lifetimes;
157
+ staleManager;
129
158
  schema;
130
159
  constructor({
131
160
  storage,
@@ -133,6 +162,7 @@ class CacheInternal {
133
162
  lists,
134
163
  cache,
135
164
  lifetimes,
165
+ staleManager,
136
166
  schema
137
167
  }) {
138
168
  this.storage = storage;
@@ -140,6 +170,7 @@ class CacheInternal {
140
170
  this.lists = lists;
141
171
  this.cache = cache;
142
172
  this.lifetimes = lifetimes;
173
+ this.staleManager = staleManager;
143
174
  this.schema = schema;
144
175
  this._disabled = typeof globalThis.window === "undefined";
145
176
  try {
@@ -160,7 +191,8 @@ class CacheInternal {
160
191
  applyUpdates,
161
192
  layer,
162
193
  toNotify = [],
163
- forceNotify
194
+ forceNotify,
195
+ forceStale
164
196
  }) {
165
197
  if (this._disabled) {
166
198
  return [];
@@ -195,6 +227,11 @@ class CacheInternal {
195
227
  const displayLayer = layer.isDisplayLayer(displayLayers);
196
228
  if (displayLayer) {
197
229
  this.lifetimes.resetLifetime(parent, key);
230
+ if (forceStale) {
231
+ this.staleManager.markFieldStale(parent, key);
232
+ } else {
233
+ this.staleManager.setFieldTimeToNow(parent, key);
234
+ }
198
235
  }
199
236
  if (!fieldSelection) {
200
237
  let newValue = value;
@@ -426,12 +463,13 @@ class CacheInternal {
426
463
  stepsFromConnection = null
427
464
  }) {
428
465
  if (parent === null) {
429
- return { data: null, partial: false, hasData: true };
466
+ return { data: null, partial: false, stale: false, hasData: true };
430
467
  }
431
468
  const target = {};
432
469
  let hasData = false;
433
470
  let partial = false;
434
471
  let cascadeNull = false;
472
+ let stale = false;
435
473
  const typename = this.storage.get(parent, "__typename").value;
436
474
  let targetSelection = (0, import_selection.getFieldsForType)(selection, typename);
437
475
  for (const [
@@ -440,6 +478,10 @@ class CacheInternal {
440
478
  ] of Object.entries(targetSelection)) {
441
479
  const key = (0, import_stuff.evaluateKey)(keyRaw, variables);
442
480
  const { value } = this.storage.get(parent, key);
481
+ const dt_field = this.staleManager.getFieldTime(parent, key);
482
+ if (dt_field === null) {
483
+ stale = true;
484
+ }
443
485
  let nextStep = stepsFromConnection;
444
486
  if (nextStep !== null) {
445
487
  if (nextStep >= 2) {
@@ -479,6 +521,9 @@ class CacheInternal {
479
521
  if (listValue.partial) {
480
522
  partial = true;
481
523
  }
524
+ if (listValue.stale) {
525
+ stale = true;
526
+ }
482
527
  if (listValue.hasData || value.length === 0) {
483
528
  hasData = true;
484
529
  }
@@ -493,6 +538,9 @@ class CacheInternal {
493
538
  if (objectFields.partial) {
494
539
  partial = true;
495
540
  }
541
+ if (objectFields.stale) {
542
+ stale = true;
543
+ }
496
544
  if (objectFields.hasData) {
497
545
  hasData = true;
498
546
  }
@@ -504,6 +552,7 @@ class CacheInternal {
504
552
  return {
505
553
  data: cascadeNull ? null : target,
506
554
  partial: hasData && partial,
555
+ stale: hasData && stale,
507
556
  hasData
508
557
  };
509
558
  }
@@ -531,6 +580,7 @@ class CacheInternal {
531
580
  }) {
532
581
  const result = [];
533
582
  let partialData = false;
583
+ let stale = false;
534
584
  let hasValues = false;
535
585
  for (const entry of linkedList) {
536
586
  if (Array.isArray(entry)) {
@@ -550,7 +600,12 @@ class CacheInternal {
550
600
  result.push(entry);
551
601
  continue;
552
602
  }
553
- const { data, partial, hasData } = this.getSelection({
603
+ const {
604
+ data,
605
+ partial,
606
+ stale: local_stale,
607
+ hasData
608
+ } = this.getSelection({
554
609
  parent: entry,
555
610
  selection: fields,
556
611
  variables,
@@ -560,6 +615,9 @@ class CacheInternal {
560
615
  if (partial) {
561
616
  partialData = true;
562
617
  }
618
+ if (local_stale) {
619
+ stale = true;
620
+ }
563
621
  if (hasData) {
564
622
  hasValues = true;
565
623
  }
@@ -567,6 +625,7 @@ class CacheInternal {
567
625
  return {
568
626
  data: result,
569
627
  partial: partialData,
628
+ stale,
570
629
  hasData: hasValues
571
630
  };
572
631
  }
@@ -37,6 +37,8 @@ class GarbageCollector {
37
37
  this.lifetimes.get(id).set(field, 0);
38
38
  }
39
39
  tick() {
40
+ const dt_tick = Date.now().valueOf();
41
+ const config_max_time = this.cache._internal_unstable.config.defaultLifetime;
40
42
  for (const [id, fieldMap] of this.lifetimes.entries()) {
41
43
  for (const [field, lifetime] of fieldMap.entries()) {
42
44
  if (this.cache._internal_unstable.subscriptions.get(id, field).length > 0) {
@@ -50,6 +52,13 @@ class GarbageCollector {
50
52
  if ([...fieldMap.keys()].length === 0) {
51
53
  this.lifetimes.delete(id);
52
54
  }
55
+ this.cache._internal_unstable.staleManager.delete(id, field);
56
+ }
57
+ if (config_max_time && config_max_time > 0) {
58
+ const dt_valueOf = this.cache.getFieldTime(id, field);
59
+ if (dt_valueOf && dt_tick - dt_valueOf > config_max_time) {
60
+ this.cache._internal_unstable.staleManager.markFieldStale(id, field);
61
+ }
53
62
  }
54
63
  }
55
64
  }
@@ -0,0 +1,30 @@
1
+ import type { Cache } from './cache';
2
+ export declare class StaleManager {
3
+ #private;
4
+ cache: Cache;
5
+ private fieldsTime;
6
+ constructor(cache: Cache);
7
+ /**
8
+ * get the FieldTime info
9
+ * @param id User:1
10
+ * @param field firstName
11
+ */
12
+ getFieldTime(id: string, field: string): number | undefined | null;
13
+ /**
14
+ * set the date to a field
15
+ * @param id User:1
16
+ * @param field firstName
17
+ */
18
+ setFieldTimeToNow(id: string, field: string): void;
19
+ /**
20
+ * set null to a field (stale)
21
+ * @param id User:1
22
+ * @param field firstName
23
+ */
24
+ markFieldStale(id: string, field: string): void;
25
+ markAllStale(): void;
26
+ markRecordStale(id: string): void;
27
+ markTypeStale(type: string): void;
28
+ markTypeFieldStale(type: string, field: string, when?: {}): void;
29
+ delete(id: string, field: string): void;
30
+ }