@data-client/core 0.14.24 → 0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.js +100 -97
- package/dist/index.umd.min.js +1 -1
- package/legacy/controller/Controller.js +31 -46
- package/legacy/index.js +1 -1
- package/legacy/manager/NetworkManager.js +44 -33
- package/legacy/state/GCPolicy.js +20 -12
- package/legacy/state/reducer/createReducer.js +4 -4
- package/legacy/state/reducer/setReducer.js +3 -3
- package/legacy/state/reducer/setResponseReducer.js +4 -4
- package/legacy/types.js +1 -1
- package/lib/controller/Controller.d.ts +3 -3
- package/lib/controller/Controller.d.ts.map +1 -1
- package/lib/controller/Controller.js +31 -46
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/manager/NetworkManager.d.ts +7 -12
- package/lib/manager/NetworkManager.d.ts.map +1 -1
- package/lib/manager/NetworkManager.js +44 -34
- package/lib/state/GCPolicy.d.ts.map +1 -1
- package/lib/state/GCPolicy.js +20 -12
- package/lib/state/reducer/createReducer.js +4 -4
- package/lib/state/reducer/expireReducer.d.ts +1 -1
- package/lib/state/reducer/invalidateReducer.d.ts +1 -1
- package/lib/state/reducer/setReducer.d.ts +1 -1
- package/lib/state/reducer/setReducer.js +3 -3
- package/lib/state/reducer/setResponseReducer.d.ts +1 -1
- package/lib/state/reducer/setResponseReducer.js +4 -4
- package/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/package.json +3 -3
- package/src/controller/Controller.ts +38 -80
- package/src/controller/__tests__/Controller.ts +2 -2
- package/src/controller/__tests__/__snapshots__/get.ts.snap +34 -8
- package/src/controller/__tests__/__snapshots__/getResponse.ts.snap +1 -1
- package/src/controller/__tests__/get.ts +163 -22
- package/src/controller/__tests__/getResponse.ts +1 -1
- package/src/index.ts +4 -0
- package/src/manager/NetworkManager.ts +46 -32
- package/src/manager/__tests__/__snapshots__/pollingSubscription.ts.snap +1 -1
- package/src/manager/__tests__/pollingSubscription.ts +9 -5
- package/src/state/GCPolicy.ts +12 -10
- package/src/state/__tests__/GCPolicy.test.ts +6 -6
- package/src/state/__tests__/__snapshots__/reducer.ts.snap +3 -3
- package/src/state/__tests__/reducer.ts +17 -9
- package/src/state/reducer/createReducer.ts +2 -2
- package/src/state/reducer/setReducer.ts +2 -2
- package/src/state/reducer/setResponseReducer.ts +3 -3
- package/src/types.ts +1 -1
- package/ts3.4/controller/Controller.d.ts +3 -3
- package/ts3.4/index.d.ts +2 -1
- package/ts3.4/manager/NetworkManager.d.ts +7 -12
- package/ts3.4/state/reducer/expireReducer.d.ts +1 -1
- package/ts3.4/state/reducer/invalidateReducer.d.ts +1 -1
- package/ts3.4/state/reducer/setReducer.d.ts +1 -1
- package/ts3.4/state/reducer/setResponseReducer.d.ts +1 -1
- package/ts3.4/types.d.ts +1 -1
package/lib/types.d.ts
CHANGED
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEhF,cAAc,cAAc,CAAC;AAE7B,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC;AAErD,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG;YAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAA;SAAE,GAAG,SAAS,CAAC;KACxE,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;KACzD,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG;YACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;YAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;YAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;YAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;SACpD,CAAC;KACH,CAAC;IACF,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEhF,cAAc,cAAc,CAAC;AAE7B,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,CAAC;AAErD,MAAM,MAAM,EAAE,GAAG,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG;YAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAA;SAAE,GAAG,SAAS,CAAC;KACxE,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC;KACzD,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG;YACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;YAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;YAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;YAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;SACpD,CAAC;KACH,CAAC;IACF,QAAQ,CAAC,YAAY,EAAE;QACrB,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG;YAC5B,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG;gBACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;aAC5B,CAAC;SACH,CAAC;KACH,CAAC;IACF,QAAQ,CAAC,UAAU,EAAE,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,EAAE,CAAC;IAC9D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO,CAAC,OAAO,GAAG,WAAW;IAC5C,gEAAgE;IAChE,aAAa,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IACtC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,0DAA0D;IAC1D,OAAO,IAAI,IAAI,CAAC;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CACpC;AAED,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC"}
|
package/lib/types.js
CHANGED
|
@@ -12,4 +12,4 @@ export * from './actions.js';
|
|
|
12
12
|
* @see https://dataclient.io/docs/api/Manager
|
|
13
13
|
*/
|
|
14
14
|
export {};
|
|
15
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL3R5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5vcm1hbGl6ZWRJbmRleCB9IGZyb20gJ0BkYXRhLWNsaWVudC9ub3JtYWxpenInO1xuaW1wb3J0IHR5cGUge1xuICBVcGRhdGVGdW5jdGlvbixcbiAgQWJzdHJhY3RJbnN0YW5jZVR5cGUsXG59IGZyb20gJ0BkYXRhLWNsaWVudC9ub3JtYWxpenInO1xuaW1wb3J0IHR5cGUgeyBFcnJvclR5cGVzIH0gZnJvbSAnQGRhdGEtY2xpZW50L25vcm1hbGl6cic7XG5cbmltcG9ydCB0eXBlIHtcbiAgQWN0aW9uVHlwZXMsXG4gIFNldFJlc3BvbnNlQWN0aW9uLFxuICBPcHRpbWlzdGljQWN0aW9uLFxufSBmcm9tICcuL2FjdGlvbnMuanMnO1xuaW1wb3J0IHR5cGUgeyBEaXNwYXRjaCwgTWlkZGxld2FyZSwgTWlkZGxld2FyZUFQSSB9IGZyb20gJy4vbWlkZGxld2FyZVR5cGVzLmpzJztcblxuZXhwb3J0ICogZnJvbSAnLi9hY3Rpb25zLmpzJztcblxuZXhwb3J0IHR5cGUgeyBBYnN0cmFjdEluc3RhbmNlVHlwZSwgVXBkYXRlRnVuY3Rpb24gfTtcblxuZXhwb3J0IHR5cGUgUEsgPSBzdHJpbmc7XG5cbi8qKiBOb3JtYWxpemVkIHN0YXRlIGZvciBSZWFjdGl2ZSBEYXRhIENsaWVudFxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL2RvY3MvY29uY2VwdHMvbm9ybWFsaXphdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlPFQ+
|
|
15
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vc3JjL3R5cGVzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5vcm1hbGl6ZWRJbmRleCB9IGZyb20gJ0BkYXRhLWNsaWVudC9ub3JtYWxpenInO1xuaW1wb3J0IHR5cGUge1xuICBVcGRhdGVGdW5jdGlvbixcbiAgQWJzdHJhY3RJbnN0YW5jZVR5cGUsXG59IGZyb20gJ0BkYXRhLWNsaWVudC9ub3JtYWxpenInO1xuaW1wb3J0IHR5cGUgeyBFcnJvclR5cGVzIH0gZnJvbSAnQGRhdGEtY2xpZW50L25vcm1hbGl6cic7XG5cbmltcG9ydCB0eXBlIHtcbiAgQWN0aW9uVHlwZXMsXG4gIFNldFJlc3BvbnNlQWN0aW9uLFxuICBPcHRpbWlzdGljQWN0aW9uLFxufSBmcm9tICcuL2FjdGlvbnMuanMnO1xuaW1wb3J0IHR5cGUgeyBEaXNwYXRjaCwgTWlkZGxld2FyZSwgTWlkZGxld2FyZUFQSSB9IGZyb20gJy4vbWlkZGxld2FyZVR5cGVzLmpzJztcblxuZXhwb3J0ICogZnJvbSAnLi9hY3Rpb25zLmpzJztcblxuZXhwb3J0IHR5cGUgeyBBYnN0cmFjdEluc3RhbmNlVHlwZSwgVXBkYXRlRnVuY3Rpb24gfTtcblxuZXhwb3J0IHR5cGUgUEsgPSBzdHJpbmc7XG5cbi8qKiBOb3JtYWxpemVkIHN0YXRlIGZvciBSZWFjdGl2ZSBEYXRhIENsaWVudFxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL2RvY3MvY29uY2VwdHMvbm9ybWFsaXphdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YXRlPFQ+IHtcbiAgcmVhZG9ubHkgZW50aXRpZXM6IHtcbiAgICByZWFkb25seSBbZW50aXR5S2V5OiBzdHJpbmddOiB7IHJlYWRvbmx5IFtwazogc3RyaW5nXTogVCB9IHwgdW5kZWZpbmVkO1xuICB9O1xuICByZWFkb25seSBlbmRwb2ludHM6IHtcbiAgICByZWFkb25seSBba2V5OiBzdHJpbmddOiB1bmtub3duIHwgUEtbXSB8IFBLIHwgdW5kZWZpbmVkO1xuICB9O1xuICByZWFkb25seSBpbmRleGVzOiBOb3JtYWxpemVkSW5kZXg7XG4gIHJlYWRvbmx5IG1ldGE6IHtcbiAgICByZWFkb25seSBba2V5OiBzdHJpbmddOiB7XG4gICAgICByZWFkb25seSBkYXRlOiBudW1iZXI7XG4gICAgICByZWFkb25seSBmZXRjaGVkQXQ6IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IGV4cGlyZXNBdDogbnVtYmVyO1xuICAgICAgcmVhZG9ubHkgcHJldkV4cGlyZXNBdD86IG51bWJlcjtcbiAgICAgIHJlYWRvbmx5IGVycm9yPzogRXJyb3JUeXBlcztcbiAgICAgIHJlYWRvbmx5IGludmFsaWRhdGVkPzogYm9vbGVhbjtcbiAgICAgIHJlYWRvbmx5IGVycm9yUG9saWN5PzogJ2hhcmQnIHwgJ3NvZnQnIHwgdW5kZWZpbmVkO1xuICAgIH07XG4gIH07XG4gIHJlYWRvbmx5IGVudGl0aWVzTWV0YToge1xuICAgIHJlYWRvbmx5IFtlbnRpdHlLZXk6IHN0cmluZ106IHtcbiAgICAgIHJlYWRvbmx5IFtwazogc3RyaW5nXToge1xuICAgICAgICByZWFkb25seSBmZXRjaGVkQXQ6IG51bWJlcjtcbiAgICAgICAgcmVhZG9ubHkgZGF0ZTogbnVtYmVyO1xuICAgICAgICByZWFkb25seSBleHBpcmVzQXQ6IG51bWJlcjtcbiAgICAgIH07XG4gICAgfTtcbiAgfTtcbiAgcmVhZG9ubHkgb3B0aW1pc3RpYzogKFNldFJlc3BvbnNlQWN0aW9uIHwgT3B0aW1pc3RpY0FjdGlvbilbXTtcbiAgcmVhZG9ubHkgbGFzdFJlc2V0OiBudW1iZXI7XG59XG5cbi8qKiBTaW5nbGV0b25zIHRoYXQgaGFuZGxlIGdsb2JhbCBzaWRlLWVmZmVjdHNcbiAqXG4gKiBLaW5kIG9mIGxpa2UgdXNlRWZmZWN0KCkgZm9yIHRoZSBjZW50cmFsIGRhdGEgc3RvcmVcbiAqXG4gKiBAc2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9kb2NzL2FwaS9NYW5hZ2VyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWFuYWdlcjxBY3Rpb25zID0gQWN0aW9uVHlwZXM+IHtcbiAgLyoqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL2RvY3MvYXBpL01hbmFnZXIjZ2V0bWlkZGxld2FyZSAqL1xuICBnZXRNaWRkbGV3YXJlPygpOiBNaWRkbGV3YXJlPEFjdGlvbnM+O1xuICAvKiogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vZG9jcy9hcGkvTWFuYWdlciNtaWRkbGV3YXJlICovXG4gIG1pZGRsZXdhcmU/OiBNaWRkbGV3YXJlPEFjdGlvbnM+O1xuICAvKiogQHNlZSBodHRwczovL2RhdGFjbGllbnQuaW8vZG9jcy9hcGkvTWFuYWdlciNjbGVhbnVwICovXG4gIGNsZWFudXAoKTogdm9pZDtcbiAgLyoqIEBzZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL2RvY3MvYXBpL01hbmFnZXIjaW5pdCAqL1xuICBpbml0PzogKHN0YXRlOiBTdGF0ZTxhbnk+KSA9PiB2b2lkO1xufVxuXG5leHBvcnQgdHlwZSB7IERpc3BhdGNoLCBNaWRkbGV3YXJlLCBNaWRkbGV3YXJlQVBJIH07XG4iXSwibWFwcGluZ3MiOiJBQWNBLGNBQWMsY0FBYzs7QUFNNUI7QUFDQTtBQUNBO0FBQ0E7O0FBaUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBIiwiaWdub3JlTGlzdCI6W119
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@data-client/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b",
|
|
4
4
|
"description": "Async State Management without the Management. REST, GraphQL, SSE, Websockets, Fetch",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -125,13 +125,13 @@
|
|
|
125
125
|
},
|
|
126
126
|
"dependencies": {
|
|
127
127
|
"@babel/runtime": "^7.20.0",
|
|
128
|
-
"@data-client/normalizr": "
|
|
128
|
+
"@data-client/normalizr": "0.15.0-beta-20251006024044-92bd01c4976f2921993b8c9f1e4dbb87af87ba7b",
|
|
129
129
|
"flux-standard-action": "^2.1.1"
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
132
|
"@anansi/browserslist-config": "^1.4.2",
|
|
133
133
|
"@data-client/endpoint": "workspace:*",
|
|
134
|
-
"@types/jest": "
|
|
134
|
+
"@types/jest": "30.0.0",
|
|
135
135
|
"@types/node": "^22.0.0",
|
|
136
136
|
"rollup-plugins": "workspace:*"
|
|
137
137
|
}
|
|
@@ -172,7 +172,7 @@ export default class Controller<
|
|
|
172
172
|
...args: readonly [...Parameters<E>]
|
|
173
173
|
): E['schema'] extends undefined | null ? ReturnType<E> | ResolveType<E>
|
|
174
174
|
: Promise<Denormalize<E['schema']>> | Denormalize<E['schema']> => {
|
|
175
|
-
const { data, expiresAt, expiryStatus } = this.
|
|
175
|
+
const { data, expiresAt, expiryStatus } = this.getResponseMeta(
|
|
176
176
|
endpoint,
|
|
177
177
|
...args,
|
|
178
178
|
this.getState(),
|
|
@@ -514,13 +514,7 @@ export default class Controller<
|
|
|
514
514
|
const input =
|
|
515
515
|
shouldQuery ?
|
|
516
516
|
// nothing in endpoints cache, so try querying if we have a schema to do so
|
|
517
|
-
this.memo.buildQueryKey(
|
|
518
|
-
schema,
|
|
519
|
-
args,
|
|
520
|
-
state.entities as any,
|
|
521
|
-
state.indexes,
|
|
522
|
-
key,
|
|
523
|
-
)
|
|
517
|
+
this.memo.buildQueryKey(schema, args, state, key)
|
|
524
518
|
: cacheEndpoints;
|
|
525
519
|
|
|
526
520
|
if (!isActive) {
|
|
@@ -540,17 +534,16 @@ export default class Controller<
|
|
|
540
534
|
} else if (!schema || !schemaHasEntity(schema)) {
|
|
541
535
|
return {
|
|
542
536
|
data: cacheEndpoints,
|
|
543
|
-
expiryStatus:
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
537
|
+
expiryStatus: this.getExpiryStatus(
|
|
538
|
+
!cacheEndpoints,
|
|
539
|
+
!!endpoint.invalidIfStale,
|
|
540
|
+
meta,
|
|
541
|
+
),
|
|
547
542
|
expiresAt: expiresAt || 0,
|
|
548
543
|
countRef: this.gcPolicy.createCountRef({ key }),
|
|
549
544
|
};
|
|
550
545
|
}
|
|
551
546
|
|
|
552
|
-
// second argument is false if any entities are missing
|
|
553
|
-
|
|
554
547
|
const { data, paths } = this.memo.denormalize(
|
|
555
548
|
schema,
|
|
556
549
|
input,
|
|
@@ -558,18 +551,23 @@ export default class Controller<
|
|
|
558
551
|
args,
|
|
559
552
|
) as { data: any; paths: EntityPath[] };
|
|
560
553
|
|
|
561
|
-
|
|
562
|
-
|
|
554
|
+
if (!expiresAt) {
|
|
555
|
+
// note: isInvalid can only be true if shouldQuery is true
|
|
556
|
+
if (isInvalid) expiresAt = 1;
|
|
557
|
+
// fallback to entity expiry time
|
|
558
|
+
else expiresAt = entityExpiresAt(paths, state.entitiesMeta);
|
|
559
|
+
}
|
|
563
560
|
|
|
564
|
-
return
|
|
561
|
+
return {
|
|
565
562
|
data,
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
563
|
+
expiryStatus: this.getExpiryStatus(
|
|
564
|
+
typeof data === 'symbol',
|
|
565
|
+
!!endpoint.invalidIfStale || isInvalid,
|
|
566
|
+
meta,
|
|
567
|
+
),
|
|
569
568
|
expiresAt,
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
);
|
|
569
|
+
countRef: this.gcPolicy.createCountRef({ key, paths }),
|
|
570
|
+
};
|
|
573
571
|
}
|
|
574
572
|
|
|
575
573
|
/**
|
|
@@ -580,7 +578,7 @@ export default class Controller<
|
|
|
580
578
|
schema: S,
|
|
581
579
|
...rest: readonly [
|
|
582
580
|
...SchemaArgs<S>,
|
|
583
|
-
Pick<State<unknown>, 'entities' | '
|
|
581
|
+
Pick<State<unknown>, 'entities' | 'indexes'>,
|
|
584
582
|
]
|
|
585
583
|
): DenormalizeNullable<S> | undefined {
|
|
586
584
|
const state = rest[rest.length - 1] as State<any>;
|
|
@@ -589,7 +587,8 @@ export default class Controller<
|
|
|
589
587
|
.slice(0, rest.length - 1)
|
|
590
588
|
.map(ensurePojo) as SchemaArgs<S>;
|
|
591
589
|
|
|
592
|
-
|
|
590
|
+
const { data } = this.memo.query(schema, args, state);
|
|
591
|
+
return typeof data === 'symbol' ? undefined : data;
|
|
593
592
|
}
|
|
594
593
|
|
|
595
594
|
/**
|
|
@@ -600,7 +599,7 @@ export default class Controller<
|
|
|
600
599
|
schema: S,
|
|
601
600
|
...rest: readonly [
|
|
602
601
|
...SchemaArgs<S>,
|
|
603
|
-
Pick<State<unknown>, 'entities' | '
|
|
602
|
+
Pick<State<unknown>, 'entities' | 'indexes'>,
|
|
604
603
|
]
|
|
605
604
|
): {
|
|
606
605
|
data: DenormalizeNullable<S> | undefined;
|
|
@@ -612,68 +611,27 @@ export default class Controller<
|
|
|
612
611
|
.slice(0, rest.length - 1)
|
|
613
612
|
.map(ensurePojo) as SchemaArgs<S>;
|
|
614
613
|
|
|
615
|
-
|
|
616
|
-
// this logic
|
|
617
|
-
const input = this.memo.buildQueryKey(
|
|
618
|
-
schema,
|
|
619
|
-
args,
|
|
620
|
-
state.entities as any,
|
|
621
|
-
state.indexes,
|
|
622
|
-
JSON.stringify(args),
|
|
623
|
-
);
|
|
624
|
-
|
|
625
|
-
if (!input) {
|
|
626
|
-
return { data: undefined, countRef: () => () => undefined };
|
|
627
|
-
}
|
|
614
|
+
const { data, paths } = this.memo.query(schema, args, state);
|
|
628
615
|
|
|
629
|
-
const { data, paths } = this.memo.denormalize(
|
|
630
|
-
schema,
|
|
631
|
-
input,
|
|
632
|
-
state.entities,
|
|
633
|
-
args,
|
|
634
|
-
);
|
|
635
616
|
return {
|
|
636
|
-
data: typeof data === 'symbol' ? undefined :
|
|
617
|
+
data: typeof data === 'symbol' ? undefined : data,
|
|
637
618
|
countRef: this.gcPolicy.createCountRef({ paths }),
|
|
638
619
|
};
|
|
639
620
|
}
|
|
640
621
|
|
|
641
|
-
private
|
|
642
|
-
|
|
643
|
-
key: string,
|
|
644
|
-
paths: EntityPath[],
|
|
645
|
-
entityMeta: State<unknown>['entityMeta'],
|
|
646
|
-
expiresAt: number,
|
|
622
|
+
private getExpiryStatus(
|
|
623
|
+
invalidData: boolean,
|
|
647
624
|
invalidIfStale: boolean,
|
|
648
625
|
meta: { error?: unknown; invalidated?: unknown } = {},
|
|
649
|
-
)
|
|
650
|
-
data: T;
|
|
651
|
-
expiryStatus: ExpiryStatus;
|
|
652
|
-
expiresAt: number;
|
|
653
|
-
countRef: () => () => void;
|
|
654
|
-
} {
|
|
655
|
-
const invalidDenormalize = typeof data === 'symbol';
|
|
656
|
-
|
|
657
|
-
// fallback to entity expiry time
|
|
658
|
-
if (!expiresAt) {
|
|
659
|
-
expiresAt = entityExpiresAt(paths, entityMeta);
|
|
660
|
-
}
|
|
661
|
-
|
|
626
|
+
) {
|
|
662
627
|
// https://dataclient.io/docs/concepts/expiry-policy#expiry-status
|
|
663
628
|
// we don't track the difference between stale or fresh because that is tied to triggering
|
|
664
629
|
// conditions
|
|
665
|
-
|
|
666
|
-
meta
|
|
667
|
-
|
|
668
|
-
:
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
return {
|
|
672
|
-
data,
|
|
673
|
-
expiryStatus,
|
|
674
|
-
expiresAt,
|
|
675
|
-
countRef: this.gcPolicy.createCountRef({ key, paths }),
|
|
676
|
-
};
|
|
630
|
+
return (
|
|
631
|
+
meta.invalidated || (invalidData && !meta.error) ? ExpiryStatus.Invalid
|
|
632
|
+
: invalidData || invalidIfStale ? ExpiryStatus.InvalidIfStale
|
|
633
|
+
: ExpiryStatus.Valid
|
|
634
|
+
);
|
|
677
635
|
}
|
|
678
636
|
}
|
|
679
637
|
|
|
@@ -681,7 +639,7 @@ export default class Controller<
|
|
|
681
639
|
// earliest expiry dictates age
|
|
682
640
|
function entityExpiresAt(
|
|
683
641
|
paths: EntityPath[],
|
|
684
|
-
|
|
642
|
+
entitiesMeta: {
|
|
685
643
|
readonly [entityKey: string]: {
|
|
686
644
|
readonly [pk: string]: {
|
|
687
645
|
readonly date: number;
|
|
@@ -692,8 +650,8 @@ function entityExpiresAt(
|
|
|
692
650
|
},
|
|
693
651
|
) {
|
|
694
652
|
let expiresAt = Infinity;
|
|
695
|
-
for (const {
|
|
696
|
-
const entityExpiry =
|
|
653
|
+
for (const { key, pk } of paths) {
|
|
654
|
+
const entityExpiry = entitiesMeta[key]?.[pk]?.expiresAt;
|
|
697
655
|
// expiresAt will always resolve to false with any comparison
|
|
698
656
|
if (entityExpiry < expiresAt) expiresAt = entityExpiry;
|
|
699
657
|
}
|
|
@@ -46,7 +46,7 @@ describe('Controller', () => {
|
|
|
46
46
|
endpoints: {
|
|
47
47
|
[fetchKey]: result,
|
|
48
48
|
},
|
|
49
|
-
|
|
49
|
+
entitiesMeta: createEntityMeta(entities),
|
|
50
50
|
meta: {
|
|
51
51
|
[fetchKey]: {
|
|
52
52
|
date: Date.now(),
|
|
@@ -85,7 +85,7 @@ describe('Controller', () => {
|
|
|
85
85
|
endpoints: {
|
|
86
86
|
[fetchKey]: result,
|
|
87
87
|
},
|
|
88
|
-
|
|
88
|
+
entitiesMeta: createEntityMeta(entities),
|
|
89
89
|
meta: {
|
|
90
90
|
[fetchKey]: {
|
|
91
91
|
date: 0,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://
|
|
1
|
+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
2
|
|
|
3
3
|
exports[`Controller.get() Query+All based on args 1`] = `
|
|
4
4
|
[
|
|
@@ -53,6 +53,39 @@ Group {
|
|
|
53
53
|
}
|
|
54
54
|
`;
|
|
55
55
|
|
|
56
|
+
exports[`Controller.get() Union based on args with function schemaAttribute 1`] = `
|
|
57
|
+
User {
|
|
58
|
+
"id": "1",
|
|
59
|
+
"type": "users",
|
|
60
|
+
"username": "bob",
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
exports[`Controller.get() Union based on args with function schemaAttribute 2`] = `
|
|
65
|
+
Group {
|
|
66
|
+
"groupname": "fast",
|
|
67
|
+
"id": "2",
|
|
68
|
+
"memberCount": 5,
|
|
69
|
+
"type": "groups",
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
exports[`Controller.get() indexes query Entity based on index 1`] = `
|
|
74
|
+
User {
|
|
75
|
+
"id": "1",
|
|
76
|
+
"staff": false,
|
|
77
|
+
"username": "bob",
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
exports[`Controller.get() indexes query indexes after empty state 1`] = `
|
|
82
|
+
User {
|
|
83
|
+
"id": "1",
|
|
84
|
+
"staff": false,
|
|
85
|
+
"username": "bob",
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
|
|
56
89
|
exports[`Controller.get() query All should get all entities 1`] = `
|
|
57
90
|
[
|
|
58
91
|
Tacos {
|
|
@@ -105,13 +138,6 @@ exports[`Controller.get() query Collection based on args 2`] = `
|
|
|
105
138
|
]
|
|
106
139
|
`;
|
|
107
140
|
|
|
108
|
-
exports[`Controller.get() query Entity based on index 1`] = `
|
|
109
|
-
User {
|
|
110
|
-
"id": "1",
|
|
111
|
-
"username": "bob",
|
|
112
|
-
}
|
|
113
|
-
`;
|
|
114
|
-
|
|
115
141
|
exports[`Controller.get() query Entity based on pk 1`] = `
|
|
116
142
|
Tacos {
|
|
117
143
|
"id": "1",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Entity, schema } from '@data-client/endpoint';
|
|
2
2
|
|
|
3
3
|
import { initialState } from '../../state/reducer/createReducer';
|
|
4
|
+
import { State } from '../../types';
|
|
4
5
|
import Controller from '../Controller';
|
|
5
6
|
|
|
6
7
|
class Tacos extends Entity {
|
|
@@ -46,37 +47,113 @@ describe('Controller.get()', () => {
|
|
|
46
47
|
() => controller.get(Tacos, { doesnotexist: 5 }, state);
|
|
47
48
|
});
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
describe('indexes', () => {
|
|
50
51
|
class User extends Entity {
|
|
51
52
|
id = '';
|
|
52
53
|
username = '';
|
|
54
|
+
staff = false;
|
|
53
55
|
|
|
54
56
|
static indexes = ['username'] as const;
|
|
55
57
|
}
|
|
58
|
+
it('query Entity based on index', () => {
|
|
59
|
+
const controller = new Controller();
|
|
60
|
+
const state: State<unknown> = {
|
|
61
|
+
...initialState,
|
|
62
|
+
entities: {
|
|
63
|
+
User: {
|
|
64
|
+
'1': { id: '1', username: 'bob' },
|
|
65
|
+
'2': { id: '2', username: 'george' },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
indexes: {
|
|
69
|
+
User: {
|
|
70
|
+
username: {
|
|
71
|
+
bob: '1',
|
|
72
|
+
george: '2',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
56
77
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
const bob = controller.get(User, { username: 'bob' }, state);
|
|
79
|
+
expect(bob).toBeDefined();
|
|
80
|
+
expect(bob).toBeInstanceOf(User);
|
|
81
|
+
expect(bob).toMatchSnapshot();
|
|
82
|
+
// stability
|
|
83
|
+
expect(controller.get(User, { username: 'bob' }, state)).toBe(bob);
|
|
84
|
+
// should be same as id lookup
|
|
85
|
+
expect(controller.get(User, { id: '1' }, state)).toBe(bob);
|
|
86
|
+
// update index
|
|
87
|
+
let nextState: State<unknown> = {
|
|
88
|
+
...state,
|
|
89
|
+
entities: {
|
|
90
|
+
...state.entities,
|
|
91
|
+
User: {
|
|
92
|
+
...state.entities.User,
|
|
93
|
+
'1': { id: '1', username: 'george' },
|
|
94
|
+
'2': { id: '2', username: 'bob' },
|
|
95
|
+
},
|
|
63
96
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
indexes: {
|
|
98
|
+
...state.indexes,
|
|
99
|
+
User: {
|
|
100
|
+
...state.indexes.User,
|
|
101
|
+
username: {
|
|
102
|
+
...state.indexes.User.username,
|
|
103
|
+
bob: '2',
|
|
104
|
+
george: '1',
|
|
105
|
+
},
|
|
69
106
|
},
|
|
70
107
|
},
|
|
71
|
-
}
|
|
72
|
-
|
|
108
|
+
};
|
|
109
|
+
expect(controller.get(User, { username: 'bob' }, nextState)).not.toBe(
|
|
110
|
+
bob,
|
|
111
|
+
);
|
|
112
|
+
nextState = {
|
|
113
|
+
...state,
|
|
114
|
+
entities: {
|
|
115
|
+
...state.entities,
|
|
116
|
+
User: {
|
|
117
|
+
...state.entities.User,
|
|
118
|
+
'1': { id: '1', username: 'bob', staff: true },
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
// update entity keep index
|
|
123
|
+
const nextBob = controller.get(User, { username: 'bob' }, nextState);
|
|
124
|
+
expect(nextBob).not.toBe(bob);
|
|
125
|
+
expect(nextBob).toBeDefined();
|
|
126
|
+
expect(nextBob).toBeInstanceOf(User);
|
|
127
|
+
expect(nextBob?.staff).toBe(true);
|
|
128
|
+
});
|
|
73
129
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
130
|
+
it('query indexes after empty state', () => {
|
|
131
|
+
const controller = new Controller();
|
|
132
|
+
expect(
|
|
133
|
+
controller.get(User, { username: 'bob' }, initialState),
|
|
134
|
+
).toBeUndefined();
|
|
135
|
+
const state: State<unknown> = {
|
|
136
|
+
...initialState,
|
|
137
|
+
entities: {
|
|
138
|
+
User: {
|
|
139
|
+
'1': { id: '1', username: 'bob' },
|
|
140
|
+
'2': { id: '2', username: 'george' },
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
indexes: {
|
|
144
|
+
User: {
|
|
145
|
+
username: {
|
|
146
|
+
bob: '1',
|
|
147
|
+
george: '2',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
const bob = controller.get(User, { username: 'bob' }, state);
|
|
153
|
+
expect(bob).toBeDefined();
|
|
154
|
+
expect(bob).toBeInstanceOf(User);
|
|
155
|
+
expect(bob).toMatchSnapshot();
|
|
156
|
+
});
|
|
80
157
|
});
|
|
81
158
|
|
|
82
159
|
it('query Collection based on args', () => {
|
|
@@ -218,11 +295,11 @@ describe('Controller.get()', () => {
|
|
|
218
295
|
id: string = '';
|
|
219
296
|
}
|
|
220
297
|
class User extends IDEntity {
|
|
221
|
-
type = '
|
|
298
|
+
type = 'users';
|
|
222
299
|
username: string = '';
|
|
223
300
|
}
|
|
224
301
|
class Group extends IDEntity {
|
|
225
|
-
type = '
|
|
302
|
+
type = 'groups';
|
|
226
303
|
groupname: string = '';
|
|
227
304
|
memberCount = 0;
|
|
228
305
|
}
|
|
@@ -272,6 +349,70 @@ describe('Controller.get()', () => {
|
|
|
272
349
|
// @ts-expect-error
|
|
273
350
|
() => controller.get(queryPerson, { id: '1', doesnotexist: 5 }, state);
|
|
274
351
|
});
|
|
352
|
+
|
|
353
|
+
it('Union based on args with function schemaAttribute', () => {
|
|
354
|
+
class IDEntity extends Entity {
|
|
355
|
+
id: string = '';
|
|
356
|
+
}
|
|
357
|
+
class User extends IDEntity {
|
|
358
|
+
type = 'user';
|
|
359
|
+
username: string = '';
|
|
360
|
+
}
|
|
361
|
+
class Group extends IDEntity {
|
|
362
|
+
type = 'group';
|
|
363
|
+
groupname: string = '';
|
|
364
|
+
memberCount = 0;
|
|
365
|
+
}
|
|
366
|
+
const queryPerson = new schema.Union(
|
|
367
|
+
{
|
|
368
|
+
users: User,
|
|
369
|
+
groups: Group,
|
|
370
|
+
},
|
|
371
|
+
(value: { type: 'users' | 'groups' }) => value.type,
|
|
372
|
+
);
|
|
373
|
+
const controller = new Controller();
|
|
374
|
+
const state = {
|
|
375
|
+
...initialState,
|
|
376
|
+
entities: {
|
|
377
|
+
User: {
|
|
378
|
+
'1': { id: '1', type: 'users', username: 'bob' },
|
|
379
|
+
},
|
|
380
|
+
Group: {
|
|
381
|
+
'2': { id: '2', type: 'groups', groupname: 'fast', memberCount: 5 },
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
const user = controller.get(queryPerson, { id: '1', type: 'users' }, state);
|
|
386
|
+
expect(user).toBeDefined();
|
|
387
|
+
expect(user).toBeInstanceOf(User);
|
|
388
|
+
expect(user).toMatchSnapshot();
|
|
389
|
+
const group = controller.get(
|
|
390
|
+
queryPerson,
|
|
391
|
+
{ id: '2', type: 'groups' },
|
|
392
|
+
state,
|
|
393
|
+
);
|
|
394
|
+
expect(group).toBeDefined();
|
|
395
|
+
expect(group).toBeInstanceOf(Group);
|
|
396
|
+
expect(group).toMatchSnapshot();
|
|
397
|
+
|
|
398
|
+
// should maintain referential equality
|
|
399
|
+
expect(user).toBe(
|
|
400
|
+
controller.get(queryPerson, { id: '1', type: 'users' }, state),
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// these are the 'fallback case' where it cannot determine type discriminator, so just enumerates
|
|
404
|
+
() => controller.get(queryPerson, { id: '1' }, state);
|
|
405
|
+
// @ts-expect-error
|
|
406
|
+
() => controller.get(queryPerson, { id: '1', type: 'notrealtype' }, state);
|
|
407
|
+
// @ts-expect-error
|
|
408
|
+
() => controller.get(queryPerson, { id: { bob: 5 }, type: 'users' }, state);
|
|
409
|
+
// @ts-expect-error
|
|
410
|
+
expect(controller.get(queryPerson, 5, state)).toBeUndefined();
|
|
411
|
+
// @ts-expect-error
|
|
412
|
+
() => controller.get(queryPerson, { doesnotexist: 5 }, state);
|
|
413
|
+
// @ts-expect-error
|
|
414
|
+
() => controller.get(queryPerson, { id: '1', doesnotexist: 5 }, state);
|
|
415
|
+
});
|
|
275
416
|
});
|
|
276
417
|
|
|
277
418
|
describe('Snapshot.getQueryMeta()', () => {
|
|
@@ -152,7 +152,7 @@ describe('Controller.getResponse()', () => {
|
|
|
152
152
|
const state = {
|
|
153
153
|
...initialState,
|
|
154
154
|
entities,
|
|
155
|
-
|
|
155
|
+
entitiesMeta: {
|
|
156
156
|
Tacos: {
|
|
157
157
|
1: { date: 1000000, expiresAt: 1100000, fetchedAt: 1000000 },
|
|
158
158
|
2: { date: 2000000, expiresAt: 2100000, fetchedAt: 2000000 },
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,9 @@ export type {
|
|
|
16
16
|
EndpointExtraOptions,
|
|
17
17
|
Queryable,
|
|
18
18
|
SchemaArgs,
|
|
19
|
+
Mergeable,
|
|
20
|
+
IQueryDelegate,
|
|
21
|
+
INormalizeDelegate,
|
|
19
22
|
NI,
|
|
20
23
|
} from '@data-client/normalizr';
|
|
21
24
|
export { ExpiryStatus } from '@data-client/normalizr';
|
|
@@ -23,6 +26,7 @@ export {
|
|
|
23
26
|
default as NetworkManager,
|
|
24
27
|
ResetError,
|
|
25
28
|
} from './manager/NetworkManager.js';
|
|
29
|
+
export type { FetchingMeta } from './manager/NetworkManager.js';
|
|
26
30
|
export * from './state/GCPolicy.js';
|
|
27
31
|
export {
|
|
28
32
|
default as createReducer,
|