jason-rails 0.3.0 → 0.6.0
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 +184 -0
- data/README.md +118 -10
- data/app/controllers/jason/api/pusher_controller.rb +15 -0
- data/app/controllers/jason/api_controller.rb +78 -0
- data/client/babel.config.js +13 -0
- data/client/lib/JasonContext.d.ts +6 -1
- data/client/lib/JasonProvider.d.ts +6 -5
- data/client/lib/JasonProvider.js +5 -97
- data/client/lib/actionFactory.js +1 -1
- data/client/lib/createActions.d.ts +1 -1
- data/client/lib/createActions.js +2 -27
- data/client/lib/createJasonReducers.js +49 -3
- data/client/lib/createOptDis.d.ts +1 -0
- data/client/lib/createOptDis.js +43 -0
- data/client/lib/createPayloadHandler.d.ts +9 -1
- data/client/lib/createPayloadHandler.js +52 -43
- 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/deepCamelizeKeys.d.ts +1 -0
- data/client/lib/deepCamelizeKeys.js +23 -0
- data/client/lib/deepCamelizeKeys.test.d.ts +1 -0
- data/client/lib/deepCamelizeKeys.test.js +106 -0
- data/client/lib/index.d.ts +6 -5
- 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 +19 -4
- data/client/src/JasonProvider.tsx +6 -96
- data/client/src/actionFactory.ts +1 -1
- data/client/src/createActions.ts +2 -33
- data/client/src/createJasonReducers.ts +57 -3
- data/client/src/createOptDis.ts +45 -0
- data/client/src/createPayloadHandler.ts +58 -47
- 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/deepCamelizeKeys.test.ts +113 -0
- data/client/src/deepCamelizeKeys.ts +17 -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 +4607 -81
- data/config/routes.rb +8 -0
- data/jason-rails.gemspec +9 -0
- data/lib/jason.rb +40 -1
- data/lib/jason/api_model.rb +15 -9
- data/lib/jason/broadcaster.rb +19 -0
- data/lib/jason/channel.rb +50 -21
- data/lib/jason/engine.rb +5 -0
- 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 +103 -30
- data/lib/jason/publisher_old.rb +112 -0
- data/lib/jason/subscription.rb +352 -101
- data/lib/jason/subscription_old.rb +171 -0
- data/lib/jason/version.rb +1 -1
- metadata +151 -4
@@ -1,7 +1,8 @@
|
|
1
|
+
import React from 'react';
|
1
2
|
declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
|
2
|
-
reducers
|
3
|
-
middleware
|
4
|
-
extraActions
|
5
|
-
children
|
6
|
-
}) =>
|
3
|
+
reducers?: any;
|
4
|
+
middleware?: any;
|
5
|
+
extraActions?: any;
|
6
|
+
children?: React.FC<{}> | undefined;
|
7
|
+
}) => JSX.Element;
|
7
8
|
export default JasonProvider;
|
data/client/lib/JasonProvider.js
CHANGED
@@ -1,107 +1,15 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
-
if (k2 === undefined) k2 = k;
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5
|
-
}) : (function(o, m, k, k2) {
|
6
|
-
if (k2 === undefined) k2 = k;
|
7
|
-
o[k2] = m[k];
|
8
|
-
}));
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11
|
-
}) : function(o, v) {
|
12
|
-
o["default"] = v;
|
13
|
-
});
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
15
|
-
if (mod && mod.__esModule) return mod;
|
16
|
-
var result = {};
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18
|
-
__setModuleDefault(result, mod);
|
19
|
-
return result;
|
20
|
-
};
|
21
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
22
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
23
4
|
};
|
24
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
25
|
-
const
|
26
|
-
const
|
27
|
-
const JasonContext_1 = __importDefault(require("./JasonContext"));
|
28
|
-
const axios_1 = __importDefault(require("axios"));
|
29
|
-
const axios_case_converter_1 = __importDefault(require("axios-case-converter"));
|
6
|
+
const react_1 = __importDefault(require("react"));
|
7
|
+
const useJason_1 = __importDefault(require("./useJason"));
|
30
8
|
const react_redux_1 = require("react-redux");
|
31
|
-
const
|
32
|
-
const createJasonReducers_1 = __importDefault(require("./createJasonReducers"));
|
33
|
-
const createPayloadHandler_1 = __importDefault(require("./createPayloadHandler"));
|
34
|
-
const makeEager_1 = __importDefault(require("./makeEager"));
|
35
|
-
const humps_1 = require("humps");
|
36
|
-
const blueimp_md5_1 = __importDefault(require("blueimp-md5"));
|
37
|
-
const lodash_1 = __importDefault(require("lodash"));
|
38
|
-
const react_1 = __importStar(require("react"));
|
9
|
+
const JasonContext_1 = __importDefault(require("./JasonContext"));
|
39
10
|
const JasonProvider = ({ reducers, middleware, extraActions, children }) => {
|
40
|
-
const [store,
|
41
|
-
|
42
|
-
const [connected, setConnected] = react_1.useState(false);
|
43
|
-
const csrfToken = document.querySelector("meta[name=csrf-token]").content;
|
44
|
-
axios_1.default.defaults.headers.common['X-CSRF-Token'] = csrfToken;
|
45
|
-
const restClient = axios_case_converter_1.default(axios_1.default.create());
|
46
|
-
react_1.useEffect(() => {
|
47
|
-
restClient.get('/jason/api/schema')
|
48
|
-
.then(({ data: snakey_schema }) => {
|
49
|
-
const schema = humps_1.camelizeKeys(snakey_schema);
|
50
|
-
const consumer = actioncable_1.createConsumer();
|
51
|
-
const allReducers = Object.assign(Object.assign({}, reducers), createJasonReducers_1.default(schema));
|
52
|
-
console.log({ schema, allReducers });
|
53
|
-
const store = toolkit_1.configureStore({ reducer: allReducers, middleware });
|
54
|
-
let payloadHandlers = {};
|
55
|
-
function handlePayload(payload) {
|
56
|
-
const { model, md5Hash } = payload;
|
57
|
-
console.log({ md5Hash, fn: `${model}:${md5Hash}`, payloadHandlers, model: lodash_1.default.camelCase(model), payload });
|
58
|
-
const handler = payloadHandlers[`${lodash_1.default.camelCase(model)}:${md5Hash}`];
|
59
|
-
if (handler) {
|
60
|
-
handler(Object.assign(Object.assign({}, payload), { model: lodash_1.default.camelCase(model) }));
|
61
|
-
}
|
62
|
-
}
|
63
|
-
const subscription = (consumer.subscriptions.create({
|
64
|
-
channel: 'Jason::Channel'
|
65
|
-
}, {
|
66
|
-
connected: () => {
|
67
|
-
setConnected(true);
|
68
|
-
},
|
69
|
-
received: payload => {
|
70
|
-
console.log("Payload received", payload);
|
71
|
-
handlePayload(payload);
|
72
|
-
},
|
73
|
-
disconnected: () => console.warn('Disconnected from ActionCable')
|
74
|
-
}));
|
75
|
-
console.log('sending message');
|
76
|
-
subscription.send({ message: 'test' });
|
77
|
-
function createSubscription(config) {
|
78
|
-
const md5Hash = blueimp_md5_1.default(JSON.stringify(config));
|
79
|
-
console.log('Subscribe with', config, md5Hash);
|
80
|
-
lodash_1.default.map(config, (v, model) => {
|
81
|
-
payloadHandlers[`${model}:${md5Hash}`] = createPayloadHandler_1.default(store.dispatch, subscription, model, schema[model]);
|
82
|
-
});
|
83
|
-
subscription.send({ createSubscription: config });
|
84
|
-
return () => removeSubscription(config);
|
85
|
-
}
|
86
|
-
function removeSubscription(config) {
|
87
|
-
subscription.send({ removeSubscription: config });
|
88
|
-
const md5Hash = blueimp_md5_1.default(JSON.stringify(config));
|
89
|
-
lodash_1.default.map(config, (v, model) => {
|
90
|
-
delete payloadHandlers[`${model}:${md5Hash}`];
|
91
|
-
});
|
92
|
-
}
|
93
|
-
const actions = createActions_1.default(schema, store, restClient, extraActions);
|
94
|
-
const eager = makeEager_1.default(schema);
|
95
|
-
console.log({ actions });
|
96
|
-
setValue({
|
97
|
-
actions: actions,
|
98
|
-
subscribe: (config) => createSubscription(config),
|
99
|
-
eager
|
100
|
-
});
|
101
|
-
setStore(store);
|
102
|
-
});
|
103
|
-
}, []);
|
104
|
-
if (!(store && value && connected))
|
11
|
+
const [store, value] = useJason_1.default({ reducers, middleware, extraActions });
|
12
|
+
if (!(store && value))
|
105
13
|
return react_1.default.createElement("div", null); // Wait for async fetch of schema to complete
|
106
14
|
return react_1.default.createElement(react_redux_1.Provider, { store: store },
|
107
15
|
react_1.default.createElement(JasonContext_1.default.Provider, { value: value }, children));
|
data/client/lib/actionFactory.js
CHANGED
@@ -23,7 +23,7 @@ exports.default = (dis, store, entity, { extraActions = {}, hasPriority = false
|
|
23
23
|
function remove(id) {
|
24
24
|
return dis({ type: `${pluralize_1.default(entity)}/remove`, payload: id });
|
25
25
|
}
|
26
|
-
const extraActionsResolved = lodash_1.default.mapValues(extraActions, v => v(dis, store, entity));
|
26
|
+
const extraActionsResolved = extraActions ? lodash_1.default.mapValues(extraActions, v => v(dis, store, entity)) : {};
|
27
27
|
if (hasPriority) {
|
28
28
|
return Object.assign({ add, upsert, setAll, remove, movePriority }, extraActionsResolved);
|
29
29
|
}
|
@@ -1,2 +1,2 @@
|
|
1
|
-
declare function createActions(schema: any, store: any, restClient: any, extraActions: any): any;
|
1
|
+
declare function createActions(schema: any, store: any, restClient: any, optDis: any, extraActions: any): any;
|
2
2
|
export default createActions;
|
data/client/lib/createActions.js
CHANGED
@@ -6,32 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const actionFactory_1 = __importDefault(require("./actionFactory"));
|
7
7
|
const pluralize_1 = __importDefault(require("pluralize"));
|
8
8
|
const lodash_1 = __importDefault(require("lodash"));
|
9
|
-
|
10
|
-
function enrich(type, payload) {
|
11
|
-
if (type.split('/')[1] === 'upsert' && !(type.split('/')[0] === 'session')) {
|
12
|
-
if (!payload.id) {
|
13
|
-
return Object.assign(Object.assign({}, payload), { id: uuid_1.v4() });
|
14
|
-
}
|
15
|
-
}
|
16
|
-
return payload;
|
17
|
-
}
|
18
|
-
function makeOptDis(schema, dispatch, restClient) {
|
19
|
-
const plurals = lodash_1.default.keys(schema).map(k => pluralize_1.default(k));
|
20
|
-
return function (action) {
|
21
|
-
const { type, payload } = action;
|
22
|
-
const data = enrich(type, payload);
|
23
|
-
dispatch(action);
|
24
|
-
if (plurals.indexOf(type.split('/')[0]) > -1) {
|
25
|
-
return restClient.post('/jason/api/action', { type, payload: data })
|
26
|
-
.catch(e => {
|
27
|
-
dispatch({ type: 'upsertLocalUi', data: { error: JSON.stringify(e) } });
|
28
|
-
});
|
29
|
-
}
|
30
|
-
};
|
31
|
-
}
|
32
|
-
function createActions(schema, store, restClient, extraActions) {
|
33
|
-
const dis = store.dispatch;
|
34
|
-
const optDis = makeOptDis(schema, dis, restClient);
|
9
|
+
function createActions(schema, store, restClient, optDis, extraActions) {
|
35
10
|
const actions = lodash_1.default.fromPairs(lodash_1.default.map(schema, (config, model) => {
|
36
11
|
if (config.priorityScope) {
|
37
12
|
return [pluralize_1.default(model), actionFactory_1.default(optDis, store, model, { hasPriority: true })];
|
@@ -40,7 +15,7 @@ function createActions(schema, store, restClient, extraActions) {
|
|
40
15
|
return [pluralize_1.default(model), actionFactory_1.default(optDis, store, model)];
|
41
16
|
}
|
42
17
|
}));
|
43
|
-
const extraActionsResolved = extraActions(optDis, store, restClient);
|
18
|
+
const extraActionsResolved = extraActions ? extraActions(optDis, store, restClient, actions) : {};
|
44
19
|
return lodash_1.default.merge(actions, extraActionsResolved);
|
45
20
|
}
|
46
21
|
exports.default = createActions;
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const toolkit_1 = require("@reduxjs/toolkit");
|
7
7
|
const pluralize_1 = __importDefault(require("pluralize"));
|
8
8
|
const lodash_1 = __importDefault(require("lodash"));
|
9
|
-
function generateSlices(
|
10
|
-
const sliceNames =
|
9
|
+
function generateSlices(models) {
|
10
|
+
const sliceNames = models.map(k => pluralize_1.default(k));
|
11
11
|
const adapter = toolkit_1.createEntityAdapter();
|
12
12
|
return lodash_1.default.fromPairs(lodash_1.default.map(sliceNames, name => {
|
13
13
|
return [name, toolkit_1.createSlice({
|
@@ -19,6 +19,7 @@ function generateSlices(schema) {
|
|
19
19
|
add: adapter.addOne,
|
20
20
|
setAll: adapter.setAll,
|
21
21
|
remove: adapter.removeOne,
|
22
|
+
removeMany: adapter.removeMany,
|
22
23
|
movePriority: (s, { payload: { id, priority, parentFilter } }) => {
|
23
24
|
// Get IDs and insert our item at the new index
|
24
25
|
var affectedIds = lodash_1.default.orderBy(lodash_1.default.filter(lodash_1.default.values(s.entities), parentFilter).filter(e => e.id !== id), 'priority').map(e => e.id);
|
@@ -30,7 +31,52 @@ function generateSlices(schema) {
|
|
30
31
|
}).reducer];
|
31
32
|
}));
|
32
33
|
}
|
34
|
+
function generateJasonSlices(models) {
|
35
|
+
const initialState = lodash_1.default.fromPairs(lodash_1.default.map(models, (model_name) => {
|
36
|
+
return [model_name, {}];
|
37
|
+
}));
|
38
|
+
const modelSliceReducer = toolkit_1.createSlice({
|
39
|
+
name: 'jasonModels',
|
40
|
+
initialState,
|
41
|
+
reducers: {
|
42
|
+
setSubscriptionIds(s, a) {
|
43
|
+
const { payload } = a;
|
44
|
+
const { subscriptionId, model, ids } = payload;
|
45
|
+
console.log({ initialState });
|
46
|
+
s[model][subscriptionId] = ids;
|
47
|
+
},
|
48
|
+
addSubscriptionId(s, a) {
|
49
|
+
const { payload } = a;
|
50
|
+
const { subscriptionId, model, id } = payload;
|
51
|
+
s[model][subscriptionId] = lodash_1.default.union(s[model][subscriptionId] || [], [id]);
|
52
|
+
},
|
53
|
+
removeSubscriptionId(s, a) {
|
54
|
+
const { payload } = a;
|
55
|
+
const { subscriptionId, model, id } = payload;
|
56
|
+
s[model][subscriptionId] = lodash_1.default.remove(s[model][subscriptionId] || [], id);
|
57
|
+
},
|
58
|
+
removeSubscription(s, a) {
|
59
|
+
const { payload: { subscriptionId } } = a;
|
60
|
+
lodash_1.default.map(models, model => {
|
61
|
+
delete s[model][subscriptionId];
|
62
|
+
});
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}).reducer;
|
66
|
+
const jasonSliceReducer = toolkit_1.createSlice({
|
67
|
+
name: 'jason',
|
68
|
+
initialState: {
|
69
|
+
connected: false,
|
70
|
+
queueSize: 0
|
71
|
+
},
|
72
|
+
reducers: {
|
73
|
+
upsert: (s, a) => (Object.assign(Object.assign({}, s), a.payload))
|
74
|
+
}
|
75
|
+
}).reducer;
|
76
|
+
return { jason: jasonSliceReducer, jasonModels: modelSliceReducer };
|
77
|
+
}
|
33
78
|
function createJasonReducers(schema) {
|
34
|
-
|
79
|
+
const models = lodash_1.default.keys(schema);
|
80
|
+
return Object.assign(Object.assign({}, generateSlices(models)), generateJasonSlices(models));
|
35
81
|
}
|
36
82
|
exports.default = createJasonReducers;
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function createOptDis(schema: any, dispatch: any, restClient: any, serverActionQueue: any): (action: any) => void;
|
@@ -0,0 +1,43 @@
|
|
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 uuid_1 = require("uuid");
|
9
|
+
function enrich(type, payload) {
|
10
|
+
if (type.split('/')[1] === 'upsert' && !(type.split('/')[0] === 'session')) {
|
11
|
+
if (!payload.id) {
|
12
|
+
return Object.assign(Object.assign({}, payload), { id: uuid_1.v4() });
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return payload;
|
16
|
+
}
|
17
|
+
function createOptDis(schema, dispatch, restClient, serverActionQueue) {
|
18
|
+
const plurals = lodash_1.default.keys(schema).map(k => pluralize_1.default(k));
|
19
|
+
function enqueueServerAction(action) {
|
20
|
+
serverActionQueue.addItem(action);
|
21
|
+
}
|
22
|
+
function dispatchServerAction() {
|
23
|
+
const action = serverActionQueue.getItem();
|
24
|
+
if (!action)
|
25
|
+
return;
|
26
|
+
restClient.post('/jason/api/action', action)
|
27
|
+
.then(serverActionQueue.itemProcessed)
|
28
|
+
.catch(e => {
|
29
|
+
dispatch({ type: 'upsertLocalUi', data: { error: JSON.stringify(e) } });
|
30
|
+
serverActionQueue.itemProcessed();
|
31
|
+
});
|
32
|
+
}
|
33
|
+
setInterval(dispatchServerAction, 10);
|
34
|
+
return function (action) {
|
35
|
+
const { type, payload } = action;
|
36
|
+
const data = enrich(type, payload);
|
37
|
+
dispatch({ type, payload: data });
|
38
|
+
if (plurals.indexOf(type.split('/')[0]) > -1) {
|
39
|
+
enqueueServerAction({ type, payload: data });
|
40
|
+
}
|
41
|
+
};
|
42
|
+
}
|
43
|
+
exports.default = createOptDis;
|
@@ -1 +1,9 @@
|
|
1
|
-
export default function createPayloadHandler(dispatch
|
1
|
+
export default function createPayloadHandler({ dispatch, serverActionQueue, transportAdapter, config }: {
|
2
|
+
dispatch: any;
|
3
|
+
serverActionQueue: any;
|
4
|
+
transportAdapter: any;
|
5
|
+
config: any;
|
6
|
+
}): {
|
7
|
+
handlePayload: (data: any) => void;
|
8
|
+
tearDown: () => void;
|
9
|
+
};
|
@@ -3,85 +3,94 @@ 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
|
-
const
|
7
|
-
const humps_1 = require("humps");
|
6
|
+
const deepCamelizeKeys_1 = __importDefault(require("./deepCamelizeKeys"));
|
8
7
|
const pluralize_1 = __importDefault(require("pluralize"));
|
9
8
|
const lodash_1 = __importDefault(require("lodash"));
|
9
|
+
const uuid_1 = require("uuid");
|
10
10
|
function diffSeconds(dt2, dt1) {
|
11
11
|
var diff = (dt2.getTime() - dt1.getTime()) / 1000;
|
12
12
|
return Math.abs(Math.round(diff));
|
13
13
|
}
|
14
|
-
function createPayloadHandler(dispatch,
|
15
|
-
|
16
|
-
let
|
17
|
-
let idx = 0;
|
14
|
+
function createPayloadHandler({ dispatch, serverActionQueue, transportAdapter, config }) {
|
15
|
+
const subscriptionId = uuid_1.v4();
|
16
|
+
let idx = {};
|
18
17
|
let patchQueue = {};
|
19
18
|
let lastCheckAt = new Date();
|
20
19
|
let updateDeadline = null;
|
21
20
|
let checkInterval;
|
22
21
|
function getPayload() {
|
23
|
-
|
24
|
-
subscription.send({ getPayload: { model, config } });
|
22
|
+
setTimeout(() => transportAdapter.getPayload(config), 1000);
|
25
23
|
}
|
26
|
-
|
27
|
-
|
28
|
-
const includeModels = (config.includeModels || []).map(m => lodash_1.default.camelCase(m));
|
29
|
-
console.log("Dispatching", { payload, includeModels });
|
30
|
-
includeModels.forEach(m => {
|
31
|
-
const subPayload = lodash_1.default.flatten(lodash_1.default.compact(humps_1.camelizeKeys(payload).map(instance => instance[m])));
|
32
|
-
console.log({ type: `${pluralize_1.default(m)}/upsertMany`, payload: subPayload });
|
33
|
-
dispatch({ type: `${pluralize_1.default(m)}/upsertMany`, payload: subPayload });
|
34
|
-
});
|
35
|
-
dispatch({ type: `${pluralize_1.default(model)}/upsertMany`, payload: humps_1.camelizeKeys(payload) });
|
24
|
+
function camelizeKeys(item) {
|
25
|
+
return deepCamelizeKeys_1.default(item, key => uuid_1.validate(key));
|
36
26
|
}
|
37
|
-
|
38
|
-
|
27
|
+
const tGetPayload = lodash_1.default.throttle(getPayload, 10000);
|
28
|
+
function processQueue(model) {
|
29
|
+
console.debug("processQueue", model, idx[model], patchQueue[model]);
|
39
30
|
lastCheckAt = new Date();
|
40
|
-
if (patchQueue[idx]) {
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
if (patchQueue[model][idx[model]]) {
|
32
|
+
if (!serverActionQueue.fullySynced()) {
|
33
|
+
console.debug(serverActionQueue.getData());
|
34
|
+
setTimeout(() => processQueue(model), 100);
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
const { payload, destroy, id, type } = patchQueue[model][idx[model]];
|
38
|
+
if (type === 'payload') {
|
39
|
+
dispatch({ type: `${pluralize_1.default(model)}/upsertMany`, payload });
|
40
|
+
const ids = payload.map(instance => instance.id);
|
41
|
+
dispatch({ type: `jasonModels/setSubscriptionIds`, payload: { model, subscriptionId, ids } });
|
44
42
|
}
|
45
|
-
|
46
|
-
|
43
|
+
else if (destroy) {
|
44
|
+
// Middleware will determine if this model should be removed if it isn't in any other subscriptions
|
45
|
+
dispatch({ type: `jasonModels/removeSubscriptionId`, payload: { model, subscriptionId, id } });
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
dispatch({ type: `${pluralize_1.default(model)}/upsert`, payload });
|
49
|
+
dispatch({ type: `jasonModels/addSubscriptionId`, payload: { model, subscriptionId, id } });
|
50
|
+
}
|
51
|
+
delete patchQueue[model][idx[model]];
|
52
|
+
idx[model]++;
|
47
53
|
updateDeadline = null;
|
48
|
-
processQueue();
|
54
|
+
processQueue(model);
|
49
55
|
// If there are updates in the queue that are ahead of the index, some have arrived out of order
|
50
56
|
// Set a deadline for new updates before it declares the update missing and refetches.
|
51
57
|
}
|
52
|
-
else if (lodash_1.default.keys(patchQueue).length > 0 && !updateDeadline) {
|
58
|
+
else if (lodash_1.default.keys(patchQueue[model]).length > 0 && !updateDeadline) {
|
53
59
|
var t = new Date();
|
54
60
|
t.setSeconds(t.getSeconds() + 3);
|
55
61
|
updateDeadline = t;
|
56
|
-
setTimeout(processQueue, 3100);
|
62
|
+
setTimeout(() => processQueue(model), 3100);
|
57
63
|
// If more than 10 updates in queue, or deadline has passed, restart
|
58
64
|
}
|
59
|
-
else if (lodash_1.default.keys(patchQueue).length > 10 || (updateDeadline && diffSeconds(updateDeadline, new Date()) < 0)) {
|
65
|
+
else if (lodash_1.default.keys(patchQueue[model]).length > 10 || (updateDeadline && diffSeconds(updateDeadline, new Date()) < 0)) {
|
60
66
|
tGetPayload();
|
61
67
|
updateDeadline = null;
|
62
68
|
}
|
63
69
|
}
|
64
70
|
function handlePayload(data) {
|
65
|
-
const {
|
66
|
-
|
71
|
+
const { idx: newIdx, model: snake_model, type } = data;
|
72
|
+
const model = lodash_1.default.camelCase(snake_model);
|
73
|
+
idx[model] = idx[model] || 0;
|
74
|
+
patchQueue[model] = patchQueue[model] || {};
|
67
75
|
if (type === 'payload') {
|
68
|
-
|
69
|
-
return null;
|
70
|
-
payload = value;
|
71
|
-
dispatchPayload();
|
72
|
-
idx = newIdx + 1;
|
76
|
+
idx[model] = newIdx;
|
73
77
|
// Clear any old changes left in the queue
|
74
|
-
patchQueue = lodash_1.default.pick(patchQueue, lodash_1.default.keys(patchQueue).filter(k => k > newIdx + 1));
|
75
|
-
return;
|
78
|
+
patchQueue[model] = lodash_1.default.pick(patchQueue[model], lodash_1.default.keys(patchQueue[model]).filter(k => k > newIdx + 1));
|
76
79
|
}
|
77
|
-
patchQueue[newIdx] =
|
78
|
-
|
80
|
+
patchQueue[model][newIdx] = camelizeKeys(Object.assign(Object.assign({}, data), { model }));
|
81
|
+
console.debug("Added to queue", model, idx[model], camelizeKeys(Object.assign(Object.assign({}, data), { model })), serverActionQueue.getData());
|
82
|
+
processQueue(model);
|
79
83
|
if (diffSeconds((new Date()), lastCheckAt) >= 3) {
|
80
84
|
lastCheckAt = new Date();
|
81
|
-
console.
|
85
|
+
console.debug('Interval lost. Pulling from server');
|
82
86
|
tGetPayload();
|
83
87
|
}
|
84
88
|
}
|
85
|
-
|
89
|
+
tGetPayload();
|
90
|
+
// Clean up after ourselves
|
91
|
+
function tearDown() {
|
92
|
+
dispatch({ type: `jasonModels/removeSubscription`, payload: { subscriptionId } });
|
93
|
+
}
|
94
|
+
return { handlePayload, tearDown };
|
86
95
|
}
|
87
96
|
exports.default = createPayloadHandler;
|