jason-rails 0.4.1 → 0.6.2

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.ruby-version +1 -0
  4. data/Gemfile.lock +152 -2
  5. data/README.md +117 -5
  6. data/app/controllers/jason/api/pusher_controller.rb +15 -0
  7. data/app/controllers/jason/api_controller.rb +44 -2
  8. data/client/lib/JasonContext.d.ts +6 -1
  9. data/client/lib/JasonContext.js +4 -1
  10. data/client/lib/JasonProvider.d.ts +2 -2
  11. data/client/lib/JasonProvider.js +5 -124
  12. data/client/lib/createJasonReducers.js +48 -3
  13. data/client/lib/createOptDis.js +0 -2
  14. data/client/lib/createPayloadHandler.d.ts +9 -1
  15. data/client/lib/createPayloadHandler.js +47 -55
  16. data/client/lib/createServerActionQueue.d.ts +10 -0
  17. data/client/lib/createServerActionQueue.js +48 -0
  18. data/client/lib/createServerActionQueue.test.d.ts +1 -0
  19. data/client/lib/createServerActionQueue.test.js +37 -0
  20. data/client/lib/createTransportAdapter.d.ts +5 -0
  21. data/client/lib/createTransportAdapter.js +20 -0
  22. data/client/lib/index.d.ts +5 -2
  23. data/client/lib/index.js +3 -1
  24. data/client/lib/makeEager.js +2 -2
  25. data/client/lib/pruneIdsMiddleware.d.ts +2 -0
  26. data/client/lib/pruneIdsMiddleware.js +24 -0
  27. data/client/lib/restClient.d.ts +2 -0
  28. data/client/lib/restClient.js +17 -0
  29. data/client/lib/transportAdapters/actionCableAdapter.d.ts +5 -0
  30. data/client/lib/transportAdapters/actionCableAdapter.js +35 -0
  31. data/client/lib/transportAdapters/pusherAdapter.d.ts +5 -0
  32. data/client/lib/transportAdapters/pusherAdapter.js +68 -0
  33. data/client/lib/useJason.d.ts +5 -0
  34. data/client/lib/useJason.js +94 -0
  35. data/client/lib/useJason.test.d.ts +1 -0
  36. data/client/lib/useJason.test.js +85 -0
  37. data/client/lib/useSub.d.ts +1 -1
  38. data/client/lib/useSub.js +6 -3
  39. data/client/package.json +5 -3
  40. data/client/src/JasonContext.ts +4 -1
  41. data/client/src/JasonProvider.tsx +5 -123
  42. data/client/src/createJasonReducers.ts +56 -3
  43. data/client/src/createOptDis.ts +0 -2
  44. data/client/src/createPayloadHandler.ts +53 -64
  45. data/client/src/createServerActionQueue.test.ts +42 -0
  46. data/client/src/createServerActionQueue.ts +47 -0
  47. data/client/src/createTransportAdapter.ts +13 -0
  48. data/client/src/index.ts +3 -1
  49. data/client/src/makeEager.ts +2 -2
  50. data/client/src/pruneIdsMiddleware.ts +24 -0
  51. data/client/src/restClient.ts +14 -0
  52. data/client/src/transportAdapters/actionCableAdapter.ts +38 -0
  53. data/client/src/transportAdapters/pusherAdapter.ts +72 -0
  54. data/client/src/useJason.test.ts +87 -0
  55. data/client/src/useJason.ts +110 -0
  56. data/client/src/useSub.ts +6 -3
  57. data/client/yarn.lock +71 -3
  58. data/config/routes.rb +5 -1
  59. data/jason-rails.gemspec +4 -0
  60. data/lib/jason.rb +61 -1
  61. data/lib/jason/api_model.rb +2 -12
  62. data/lib/jason/broadcaster.rb +19 -0
  63. data/lib/jason/channel.rb +50 -21
  64. data/lib/jason/graph_helper.rb +165 -0
  65. data/lib/jason/includes_helper.rb +108 -0
  66. data/lib/jason/lua_generator.rb +71 -0
  67. data/lib/jason/publisher.rb +82 -37
  68. data/lib/jason/publisher_old.rb +112 -0
  69. data/lib/jason/subscription.rb +349 -97
  70. data/lib/jason/subscription_old.rb +171 -0
  71. data/lib/jason/version.rb +1 -1
  72. metadata +80 -3
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const createServerActionQueue_1 = __importDefault(require("./createServerActionQueue"));
7
+ test('Adding items', () => {
8
+ const serverActionQueue = createServerActionQueue_1.default();
9
+ serverActionQueue.addItem({ type: 'entity/add', payload: { id: 'abc', attribute: 1 } });
10
+ const item = serverActionQueue.getItem();
11
+ expect(item).toStrictEqual({ type: 'entity/add', payload: { id: 'abc', attribute: 1 } });
12
+ });
13
+ test('Deduping of items that will overwrite each other', () => {
14
+ const serverActionQueue = createServerActionQueue_1.default();
15
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 1 } });
16
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 2 } });
17
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 3 } });
18
+ const item = serverActionQueue.getItem();
19
+ expect(item).toStrictEqual({ type: 'entity/upsert', payload: { id: 'abc', attribute: 3 } });
20
+ });
21
+ test('Deduping of items with a superset', () => {
22
+ const serverActionQueue = createServerActionQueue_1.default();
23
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 1 } });
24
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 2, attribute2: 'test' } });
25
+ const item = serverActionQueue.getItem();
26
+ expect(item).toStrictEqual({ type: 'entity/upsert', payload: { id: 'abc', attribute: 2, attribute2: 'test' } });
27
+ });
28
+ test("doesn't dedupe items with some attributes missing", () => {
29
+ const serverActionQueue = createServerActionQueue_1.default();
30
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute: 1 } });
31
+ serverActionQueue.addItem({ type: 'entity/upsert', payload: { id: 'abc', attribute2: 'test' } });
32
+ const item = serverActionQueue.getItem();
33
+ serverActionQueue.itemProcessed();
34
+ const item2 = serverActionQueue.getItem();
35
+ expect(item).toStrictEqual({ type: 'entity/upsert', payload: { id: 'abc', attribute: 1 } });
36
+ expect(item2).toStrictEqual({ type: 'entity/upsert', payload: { id: 'abc', attribute2: 'test' } });
37
+ });
@@ -0,0 +1,5 @@
1
+ export default function createTransportAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnect: any): {
2
+ getPayload: (config: any, options: any) => void;
3
+ createSubscription: (config: any) => void;
4
+ removeSubscription: (config: any) => void;
5
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const actionCableAdapter_1 = __importDefault(require("./transportAdapters/actionCableAdapter"));
7
+ const pusherAdapter_1 = __importDefault(require("./transportAdapters/pusherAdapter"));
8
+ function createTransportAdapter(jasonConfig, handlePayload, dispatch, onConnect) {
9
+ const { transportService } = jasonConfig;
10
+ if (transportService === 'action_cable') {
11
+ return actionCableAdapter_1.default(jasonConfig, handlePayload, dispatch, onConnect);
12
+ }
13
+ else if (transportService === 'pusher') {
14
+ return pusherAdapter_1.default(jasonConfig, handlePayload, dispatch);
15
+ }
16
+ else {
17
+ throw (`Transport adapter does not exist for ${transportService}`);
18
+ }
19
+ }
20
+ exports.default = createTransportAdapter;
@@ -1,10 +1,13 @@
1
+ /// <reference types="react" />
1
2
  import _useAct from './useAct';
2
3
  import _useSub from './useSub';
4
+ import _useEager from './useEager';
3
5
  export declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
4
6
  reducers?: any;
5
7
  middleware?: any;
6
8
  extraActions?: any;
7
- children?: any;
8
- }) => any;
9
+ children?: import("react").FC<{}> | undefined;
10
+ }) => JSX.Element;
9
11
  export declare const useAct: typeof _useAct;
10
12
  export declare const useSub: typeof _useSub;
13
+ export declare const useEager: typeof _useEager;
data/client/lib/index.js CHANGED
@@ -3,10 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.useSub = exports.useAct = exports.JasonProvider = void 0;
6
+ exports.useEager = exports.useSub = exports.useAct = exports.JasonProvider = void 0;
7
7
  const JasonProvider_1 = __importDefault(require("./JasonProvider"));
8
8
  const useAct_1 = __importDefault(require("./useAct"));
9
9
  const useSub_1 = __importDefault(require("./useSub"));
10
+ const useEager_1 = __importDefault(require("./useEager"));
10
11
  exports.JasonProvider = JasonProvider_1.default;
11
12
  exports.useAct = useAct_1.default;
12
13
  exports.useSub = useSub_1.default;
14
+ exports.useEager = useEager_1.default;
@@ -40,10 +40,10 @@ function default_1(schema) {
40
40
  }
41
41
  function useEager(entity, id = null, relations = []) {
42
42
  if (id) {
43
- return react_redux_1.useSelector(s => addRelations(s, Object.assign({}, s[entity].entities[String(id)]), entity, relations));
43
+ return react_redux_1.useSelector(s => addRelations(s, Object.assign({}, s[entity].entities[String(id)]), entity, relations), lodash_1.default.isEqual);
44
44
  }
45
45
  else {
46
- return react_redux_1.useSelector(s => addRelations(s, lodash_1.default.values(s[entity].entities), entity, relations));
46
+ return react_redux_1.useSelector(s => addRelations(s, lodash_1.default.values(s[entity].entities), entity, relations), lodash_1.default.isEqual);
47
47
  }
48
48
  }
49
49
  return useEager;
@@ -0,0 +1,2 @@
1
+ declare const pruneIdsMiddleware: (schema: any) => (store: any) => (next: any) => (action: any) => any;
2
+ export default pruneIdsMiddleware;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const lodash_1 = __importDefault(require("lodash"));
7
+ const pluralize_1 = __importDefault(require("pluralize"));
8
+ const pruneIdsMiddleware = schema => store => next => action => {
9
+ const { type, payload } = action;
10
+ const result = next(action);
11
+ const state = store.getState();
12
+ if (type === 'jasonModels/setSubscriptionIds' || type === 'jasonModels/removeSubscriptionIds') {
13
+ const { model, ids } = payload;
14
+ let idsInSubs = [];
15
+ lodash_1.default.map(state.jasonModels[model], (subscribedIds, k) => {
16
+ idsInSubs = lodash_1.default.union(idsInSubs, subscribedIds);
17
+ });
18
+ // Find IDs currently in Redux that aren't in any subscription
19
+ const idsToRemove = lodash_1.default.difference(state[pluralize_1.default(model)].ids, idsInSubs);
20
+ store.dispatch({ type: `${pluralize_1.default(model)}/removeMany`, payload: idsToRemove });
21
+ }
22
+ return result;
23
+ };
24
+ exports.default = pruneIdsMiddleware;
@@ -0,0 +1,2 @@
1
+ declare const restClient: any;
2
+ export default restClient;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ var _a;
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const axios_case_converter_1 = __importDefault(require("axios-case-converter"));
9
+ const uuid_1 = require("uuid");
10
+ const csrfToken = (_a = document === null || document === void 0 ? void 0 : document.querySelector("meta[name=csrf-token]")) === null || _a === void 0 ? void 0 : _a.content;
11
+ axios_1.default.defaults.headers.common['X-CSRF-Token'] = csrfToken;
12
+ const restClient = axios_case_converter_1.default(axios_1.default.create(), {
13
+ preservedKeys: (key) => {
14
+ return uuid_1.validate(key);
15
+ }
16
+ });
17
+ exports.default = restClient;
@@ -0,0 +1,5 @@
1
+ export default function actionCableAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnected: any): {
2
+ getPayload: (config: any, options: any) => void;
3
+ createSubscription: (config: any) => void;
4
+ removeSubscription: (config: any) => void;
5
+ };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const actioncable_1 = require("@rails/actioncable");
4
+ function actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnected) {
5
+ const consumer = actioncable_1.createConsumer();
6
+ const subscription = (consumer.subscriptions.create({
7
+ channel: 'Jason::Channel'
8
+ }, {
9
+ connected: () => {
10
+ dispatch({ type: 'jason/upsert', payload: { connected: true } });
11
+ console.debug('Connected to ActionCable');
12
+ // When AC loses connection - all state is lost, so we need to re-initialize all subscriptions
13
+ onConnected();
14
+ },
15
+ received: payload => {
16
+ handlePayload(payload);
17
+ console.debug("ActionCable Payload received: ", payload);
18
+ },
19
+ disconnected: () => {
20
+ dispatch({ type: 'jason/upsert', payload: { connected: false } });
21
+ console.warn('Disconnected from ActionCable');
22
+ }
23
+ }));
24
+ function getPayload(config, options) {
25
+ subscription.send(Object.assign({ getPayload: config }, options));
26
+ }
27
+ function createSubscription(config) {
28
+ subscription.send({ createSubscription: config });
29
+ }
30
+ function removeSubscription(config) {
31
+ subscription.send({ removeSubscription: config });
32
+ }
33
+ return { getPayload, createSubscription, removeSubscription };
34
+ }
35
+ exports.default = actionCableAdapter;
@@ -0,0 +1,5 @@
1
+ export default function pusherAdapter(jasonConfig: any, handlePayload: any, dispatch: any): {
2
+ getPayload: (config: any, options: any) => void;
3
+ createSubscription: (config: any) => void;
4
+ removeSubscription: (config: any) => void;
5
+ };
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const pusher_js_1 = __importDefault(require("pusher-js"));
7
+ const restClient_1 = __importDefault(require("../restClient"));
8
+ const uuid_1 = require("uuid");
9
+ const lodash_1 = __importDefault(require("lodash"));
10
+ function pusherAdapter(jasonConfig, handlePayload, dispatch) {
11
+ let consumerId = uuid_1.v4();
12
+ const { pusherKey, pusherRegion, pusherChannelPrefix } = jasonConfig;
13
+ const pusher = new pusher_js_1.default(pusherKey, {
14
+ cluster: 'eu',
15
+ forceTLS: true,
16
+ authEndpoint: '/jason/api/pusher/auth'
17
+ });
18
+ pusher.connection.bind('state_change', ({ current }) => {
19
+ if (current === 'connected') {
20
+ dispatch({ type: 'jason/upsert', payload: { connected: true } });
21
+ }
22
+ else {
23
+ dispatch({ type: 'jason/upsert', payload: { connected: false } });
24
+ }
25
+ });
26
+ pusher.connection.bind('error', error => {
27
+ dispatch({ type: 'jason/upsert', payload: { connected: false } });
28
+ });
29
+ const configToChannel = {};
30
+ function createSubscription(config) {
31
+ restClient_1.default.post('/jason/api/create_subscription', { config, consumerId })
32
+ .then(({ data: { channelName } }) => {
33
+ configToChannel[JSON.stringify(config)] = channelName;
34
+ subscribeToChannel(channelName);
35
+ })
36
+ .catch(e => console.error(e));
37
+ }
38
+ function removeSubscription(config) {
39
+ const channelName = configToChannel[JSON.stringify(config)];
40
+ unsubscribeFromChannel(fullChannelName(channelName));
41
+ restClient_1.default.post('/jason/api/remove_subscription', { config, consumerId })
42
+ .catch(e => console.error(e));
43
+ }
44
+ function getPayload(config, options) {
45
+ restClient_1.default.post('/jason/api/get_payload', {
46
+ config,
47
+ options
48
+ })
49
+ .then(({ data }) => {
50
+ lodash_1.default.map(data, (payload, modelName) => {
51
+ handlePayload(payload);
52
+ });
53
+ })
54
+ .catch(e => console.error(e));
55
+ }
56
+ function subscribeToChannel(channelName) {
57
+ const channel = pusher.subscribe(fullChannelName(channelName));
58
+ channel.bind('changed', message => handlePayload(message));
59
+ }
60
+ function unsubscribeFromChannel(channelName) {
61
+ const channel = pusher.unsubscribe(fullChannelName(channelName));
62
+ }
63
+ function fullChannelName(channelName) {
64
+ return `private-${pusherChannelPrefix}-${channelName}`;
65
+ }
66
+ return { getPayload, createSubscription, removeSubscription };
67
+ }
68
+ exports.default = pusherAdapter;
@@ -0,0 +1,5 @@
1
+ export default function useJason({ reducers, middleware, extraActions }: {
2
+ reducers?: any;
3
+ middleware?: any[];
4
+ extraActions?: any;
5
+ }): any[];
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const createActions_1 = __importDefault(require("./createActions"));
7
+ const createJasonReducers_1 = __importDefault(require("./createJasonReducers"));
8
+ const createPayloadHandler_1 = __importDefault(require("./createPayloadHandler"));
9
+ const createOptDis_1 = __importDefault(require("./createOptDis"));
10
+ const createServerActionQueue_1 = __importDefault(require("./createServerActionQueue"));
11
+ const restClient_1 = __importDefault(require("./restClient"));
12
+ const pruneIdsMiddleware_1 = __importDefault(require("./pruneIdsMiddleware"));
13
+ const createTransportAdapter_1 = __importDefault(require("./createTransportAdapter"));
14
+ const toolkit_1 = require("@reduxjs/toolkit");
15
+ const makeEager_1 = __importDefault(require("./makeEager"));
16
+ const humps_1 = require("humps");
17
+ const blueimp_md5_1 = __importDefault(require("blueimp-md5"));
18
+ const lodash_1 = __importDefault(require("lodash"));
19
+ const react_1 = require("react");
20
+ function useJason({ reducers, middleware = [], extraActions }) {
21
+ const [store, setStore] = react_1.useState(null);
22
+ const [value, setValue] = react_1.useState(null);
23
+ react_1.useEffect(() => {
24
+ restClient_1.default.get('/jason/api/config')
25
+ .then(({ data: jasonConfig }) => {
26
+ const { schema: snakey_schema } = jasonConfig;
27
+ const schema = humps_1.camelizeKeys(snakey_schema);
28
+ console.debug({ schema });
29
+ const serverActionQueue = createServerActionQueue_1.default();
30
+ const allReducers = Object.assign(Object.assign({}, reducers), createJasonReducers_1.default(schema));
31
+ console.debug({ allReducers });
32
+ const store = toolkit_1.configureStore({ reducer: allReducers, middleware: [...middleware, pruneIdsMiddleware_1.default(schema)] });
33
+ const dispatch = store.dispatch;
34
+ const optDis = createOptDis_1.default(schema, dispatch, restClient_1.default, serverActionQueue);
35
+ const actions = createActions_1.default(schema, store, restClient_1.default, optDis, extraActions);
36
+ const eager = makeEager_1.default(schema);
37
+ let payloadHandlers = {};
38
+ let configs = {};
39
+ let subOptions = {};
40
+ function handlePayload(payload) {
41
+ const { md5Hash } = payload;
42
+ const { handlePayload } = payloadHandlers[md5Hash];
43
+ if (handlePayload) {
44
+ handlePayload(payload);
45
+ }
46
+ else {
47
+ console.warn("Payload arrived with no handler", payload, payloadHandlers);
48
+ }
49
+ }
50
+ const transportAdapter = createTransportAdapter_1.default(jasonConfig, handlePayload, dispatch, () => lodash_1.default.keys(configs).forEach(md5Hash => createSubscription(configs[md5Hash], subOptions[md5Hash])));
51
+ function createSubscription(config, options = {}) {
52
+ // We need the hash to be consistent in Ruby / Javascript
53
+ const hashableConfig = lodash_1.default(Object.assign({ conditions: {}, includes: {} }, config)).toPairs().sortBy(0).fromPairs().value();
54
+ const md5Hash = blueimp_md5_1.default(JSON.stringify(hashableConfig));
55
+ payloadHandlers[md5Hash] = createPayloadHandler_1.default({ dispatch, serverActionQueue, transportAdapter, config });
56
+ configs[md5Hash] = hashableConfig;
57
+ subOptions[md5Hash] = options;
58
+ setTimeout(() => transportAdapter.createSubscription(hashableConfig), 500);
59
+ let pollInterval = null;
60
+ // This is only for debugging / dev - not prod!
61
+ // @ts-ignore
62
+ if (options.pollInterval) {
63
+ // @ts-ignore
64
+ pollInterval = setInterval(() => transportAdapter.getPayload(hashableConfig, { forceRefresh: true }), options.pollInterval);
65
+ }
66
+ return {
67
+ remove() {
68
+ removeSubscription(hashableConfig);
69
+ if (pollInterval)
70
+ clearInterval(pollInterval);
71
+ },
72
+ md5Hash
73
+ };
74
+ }
75
+ function removeSubscription(config) {
76
+ transportAdapter.removeSubscription(config);
77
+ const md5Hash = blueimp_md5_1.default(JSON.stringify(config));
78
+ payloadHandlers[md5Hash].tearDown();
79
+ delete payloadHandlers[md5Hash];
80
+ delete configs[md5Hash];
81
+ delete subOptions[md5Hash];
82
+ }
83
+ setValue({
84
+ actions: actions,
85
+ subscribe: createSubscription,
86
+ eager,
87
+ handlePayload
88
+ });
89
+ setStore(store);
90
+ });
91
+ }, []);
92
+ return [store, value];
93
+ }
94
+ exports.default = useJason;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const react_hooks_1 = require("@testing-library/react-hooks");
16
+ const useJason_1 = __importDefault(require("./useJason"));
17
+ const restClient_1 = __importDefault(require("./restClient"));
18
+ jest.mock('./restClient');
19
+ test('it works', () => __awaiter(void 0, void 0, void 0, function* () {
20
+ const resp = { data: {
21
+ schema: { post: {} },
22
+ transportService: 'action_cable'
23
+ } };
24
+ // @ts-ignore
25
+ restClient_1.default.get.mockResolvedValue(resp);
26
+ const { result, waitForNextUpdate } = react_hooks_1.renderHook(() => useJason_1.default({ reducers: {
27
+ test: (s, a) => s || {}
28
+ } }));
29
+ yield waitForNextUpdate();
30
+ const [store, value, connected] = result.current;
31
+ const { handlePayload, subscribe } = value;
32
+ const subscription = subscribe({ post: {} });
33
+ handlePayload({
34
+ type: 'payload',
35
+ model: 'post',
36
+ payload: [{ id: 4, name: 'test' }],
37
+ md5Hash: subscription.md5Hash,
38
+ idx: 1
39
+ });
40
+ handlePayload({
41
+ id: 4,
42
+ model: 'post',
43
+ destroy: true,
44
+ md5Hash: subscription.md5Hash,
45
+ idx: 2
46
+ });
47
+ handlePayload({
48
+ id: 5,
49
+ model: 'post',
50
+ payload: { id: 5, name: 'test2' },
51
+ md5Hash: subscription.md5Hash,
52
+ idx: 3
53
+ });
54
+ }));
55
+ test('pruning IDs', () => __awaiter(void 0, void 0, void 0, function* () {
56
+ const resp = { data: {
57
+ schema: { post: {} },
58
+ transportService: 'action_cable'
59
+ } };
60
+ // @ts-ignore
61
+ restClient_1.default.get.mockResolvedValue(resp);
62
+ const { result, waitForNextUpdate } = react_hooks_1.renderHook(() => useJason_1.default({ reducers: {
63
+ test: (s, a) => s || {}
64
+ } }));
65
+ yield waitForNextUpdate();
66
+ const [store, value, connected] = result.current;
67
+ const { handlePayload, subscribe } = value;
68
+ const subscription = subscribe({ post: {} });
69
+ handlePayload({
70
+ type: 'payload',
71
+ model: 'post',
72
+ payload: [{ id: 4, name: 'test' }],
73
+ md5Hash: subscription.md5Hash,
74
+ idx: 1
75
+ });
76
+ handlePayload({
77
+ type: 'payload',
78
+ model: 'post',
79
+ payload: [{ id: 5, name: 'test it out' }],
80
+ md5Hash: subscription.md5Hash,
81
+ idx: 2
82
+ });
83
+ // The ID 4 should have been pruned
84
+ expect(store.getState().posts.ids).toStrictEqual([5]);
85
+ }));