jason-rails 0.4.0 → 0.6.1
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.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.ruby-version +1 -0
- data/Gemfile.lock +152 -2
- data/README.md +117 -5
- data/app/controllers/jason/api/pusher_controller.rb +15 -0
- data/app/controllers/jason/api_controller.rb +44 -2
- data/client/lib/JasonContext.d.ts +6 -1
- data/client/lib/JasonProvider.d.ts +2 -2
- data/client/lib/JasonProvider.js +5 -124
- data/client/lib/createJasonReducers.js +48 -3
- data/client/lib/createOptDis.js +0 -2
- data/client/lib/createPayloadHandler.d.ts +9 -1
- data/client/lib/createPayloadHandler.js +47 -55
- data/client/lib/createServerActionQueue.d.ts +10 -0
- data/client/lib/createServerActionQueue.js +48 -0
- data/client/lib/createServerActionQueue.test.d.ts +1 -0
- data/client/lib/createServerActionQueue.test.js +37 -0
- data/client/lib/createTransportAdapter.d.ts +5 -0
- data/client/lib/createTransportAdapter.js +20 -0
- data/client/lib/index.d.ts +3 -2
- data/client/lib/pruneIdsMiddleware.d.ts +2 -0
- data/client/lib/pruneIdsMiddleware.js +24 -0
- data/client/lib/restClient.d.ts +2 -0
- data/client/lib/restClient.js +17 -0
- data/client/lib/transportAdapters/actionCableAdapter.d.ts +5 -0
- data/client/lib/transportAdapters/actionCableAdapter.js +35 -0
- data/client/lib/transportAdapters/pusherAdapter.d.ts +5 -0
- data/client/lib/transportAdapters/pusherAdapter.js +68 -0
- data/client/lib/useJason.d.ts +5 -0
- data/client/lib/useJason.js +94 -0
- data/client/lib/useJason.test.d.ts +1 -0
- data/client/lib/useJason.test.js +85 -0
- data/client/lib/useSub.d.ts +1 -1
- data/client/lib/useSub.js +6 -3
- data/client/package.json +5 -3
- data/client/src/JasonProvider.tsx +5 -123
- data/client/src/createJasonReducers.ts +56 -3
- data/client/src/createOptDis.ts +0 -2
- data/client/src/createPayloadHandler.ts +53 -64
- data/client/src/createServerActionQueue.test.ts +42 -0
- data/client/src/createServerActionQueue.ts +47 -0
- data/client/src/createTransportAdapter.ts +13 -0
- data/client/src/pruneIdsMiddleware.ts +24 -0
- data/client/src/restClient.ts +14 -0
- data/client/src/transportAdapters/actionCableAdapter.ts +38 -0
- data/client/src/transportAdapters/pusherAdapter.ts +72 -0
- data/client/src/useJason.test.ts +87 -0
- data/client/src/useJason.ts +110 -0
- data/client/src/useSub.ts +6 -3
- data/client/yarn.lock +71 -3
- data/config/routes.rb +5 -1
- data/jason-rails.gemspec +4 -0
- data/lib/jason.rb +61 -1
- data/lib/jason/api_model.rb +2 -12
- data/lib/jason/broadcaster.rb +19 -0
- data/lib/jason/channel.rb +50 -21
- data/lib/jason/graph_helper.rb +165 -0
- data/lib/jason/includes_helper.rb +108 -0
- data/lib/jason/lua_generator.rb +71 -0
- data/lib/jason/publisher.rb +82 -37
- data/lib/jason/publisher_old.rb +112 -0
- data/lib/jason/subscription.rb +349 -97
- data/lib/jason/subscription_old.rb +171 -0
- data/lib/jason/version.rb +1 -1
- metadata +80 -11
- data/app/assets/config/jason_engine_manifest.js +0 -1
- data/app/assets/images/jason/engine/.keep +0 -0
- data/app/assets/stylesheets/jason/engine/application.css +0 -15
- data/app/helpers/jason/engine/application_helper.rb +0 -6
- data/app/jobs/jason/engine/application_job.rb +0 -6
- data/app/mailers/jason/engine/application_mailer.rb +0 -8
- data/app/models/jason/engine/application_record.rb +0 -7
- data/app/views/layouts/jason/engine/application.html.erb +0 -15
@@ -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;
|
data/client/lib/index.d.ts
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
/// <reference types="react" />
|
1
2
|
import _useAct from './useAct';
|
2
3
|
import _useSub from './useSub';
|
3
4
|
export declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
|
4
5
|
reducers?: any;
|
5
6
|
middleware?: any;
|
6
7
|
extraActions?: any;
|
7
|
-
children?:
|
8
|
-
}) =>
|
8
|
+
children?: import("react").FC<{}> | undefined;
|
9
|
+
}) => JSX.Element;
|
9
10
|
export declare const useAct: typeof _useAct;
|
10
11
|
export declare const useSub: typeof _useSub;
|
@@ -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,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,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,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,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
|
+
}));
|
data/client/lib/useSub.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export default function useSub(config: any): void;
|
1
|
+
export default function useSub(config: any, options?: {}): void;
|
data/client/lib/useSub.js
CHANGED
@@ -5,10 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const JasonContext_1 = __importDefault(require("./JasonContext"));
|
7
7
|
const react_1 = require("react");
|
8
|
-
function useSub(config) {
|
8
|
+
function useSub(config, options = {}) {
|
9
|
+
// useEffect uses strict equality
|
10
|
+
const configJson = JSON.stringify(config);
|
9
11
|
const subscribe = react_1.useContext(JasonContext_1.default).subscribe;
|
10
12
|
react_1.useEffect(() => {
|
11
|
-
|
12
|
-
|
13
|
+
// @ts-ignore
|
14
|
+
return subscribe(config, options).remove;
|
15
|
+
}, [configJson]);
|
13
16
|
}
|
14
17
|
exports.default = useSub;
|
data/client/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@jamesr2323/jason",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.6.1",
|
4
4
|
"module": "./lib/index.js",
|
5
5
|
"types": "./lib/index.d.ts",
|
6
6
|
"scripts": {
|
@@ -16,6 +16,7 @@
|
|
16
16
|
"jsonpatch": "^3.0.1",
|
17
17
|
"lodash": "^4.17.20",
|
18
18
|
"pluralize": "^8.0.0",
|
19
|
+
"pusher-js": "^7.0.3",
|
19
20
|
"uuid": "^8.3.1"
|
20
21
|
},
|
21
22
|
"devDependencies": {
|
@@ -23,11 +24,12 @@
|
|
23
24
|
"@babel/preset-env": "^7.12.11",
|
24
25
|
"@babel/preset-typescript": "^7.12.7",
|
25
26
|
"@reduxjs/toolkit": "^1.5.0",
|
27
|
+
"@testing-library/react-hooks": "^5.0.3",
|
26
28
|
"@types/jest": "^26.0.19",
|
27
29
|
"babel-jest": "^26.6.3",
|
28
30
|
"jest": "^26.6.3",
|
29
|
-
"react": "^16.
|
30
|
-
"react-dom": "^16.
|
31
|
+
"react": "^16.9.x",
|
32
|
+
"react-dom": "^16.9.x",
|
31
33
|
"react-redux": "^7.2.2",
|
32
34
|
"typescript": "^4.1.2"
|
33
35
|
},
|