@thoughtbot/superglue 1.0.1 → 2.0.0-alpha.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.
- package/.tool-versions +1 -1
- package/dist/action_creators.d.mts +1 -1
- package/dist/action_creators.mjs +1 -1
- package/dist/{chunk-LGUVOEZ3.mjs → chunk-YS477OKK.mjs} +341 -137
- package/dist/chunk-YS477OKK.mjs.map +1 -0
- package/dist/cjs/action_creators.cjs +287 -126
- package/dist/cjs/action_creators.cjs.map +1 -1
- package/dist/cjs/superglue.cjs +6242 -168
- package/dist/cjs/superglue.cjs.map +1 -1
- package/dist/{index-BYr1PoYr.d.mts → index-MyfFLe4E.d.mts} +55 -16
- package/dist/superglue.d.mts +55 -14
- package/dist/superglue.mjs +5949 -40
- package/dist/superglue.mjs.map +1 -1
- package/package.json +12 -7
- package/thoughtbot-superglue-2.0.0-alpha.1.tgz +0 -0
- package/dist/chunk-LGUVOEZ3.mjs.map +0 -1
- package/thoughtbot-superglue-1.0.0.tgz +0 -0
- package/thoughtbot-superglue-1.0.0a.tgz +0 -0
- package/thoughtbot-superglue-1.0.0b.tgz +0 -0
- package/thoughtbot-superglue-1.0.0d.tgz +0 -0
- package/thoughtbot-superglue-1.0.1.tgz +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// lib/action_creators/index.ts
|
|
@@ -38,52 +28,39 @@ __export(action_creators_exports, {
|
|
|
38
28
|
module.exports = __toCommonJS(action_creators_exports);
|
|
39
29
|
|
|
40
30
|
// lib/utils/url.ts
|
|
41
|
-
var
|
|
31
|
+
var FAKE_ORIGIN = "https://example.com";
|
|
42
32
|
function pathQuery(url) {
|
|
43
|
-
const { pathname, query } = new
|
|
33
|
+
const { pathname, search: query } = new URL(url, FAKE_ORIGIN);
|
|
44
34
|
return pathname + query;
|
|
45
35
|
}
|
|
46
36
|
function hasPropsAt(url) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
return !!query["props_at"];
|
|
37
|
+
const { searchParams } = new URL(url, FAKE_ORIGIN);
|
|
38
|
+
return searchParams.has("props_at");
|
|
50
39
|
}
|
|
51
40
|
function propsAtParam(url) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
return query["props_at"];
|
|
41
|
+
const { searchParams } = new URL(url, FAKE_ORIGIN);
|
|
42
|
+
return searchParams.get("props_at");
|
|
55
43
|
}
|
|
56
44
|
function withFormatJson(url) {
|
|
57
|
-
const parsed = new
|
|
58
|
-
parsed.
|
|
59
|
-
return parsed.
|
|
45
|
+
const parsed = new URL(url, FAKE_ORIGIN);
|
|
46
|
+
parsed.searchParams.set("format", "json");
|
|
47
|
+
return parsed.href.replace(parsed.origin, "");
|
|
60
48
|
}
|
|
61
49
|
function removePropsAt(url) {
|
|
62
|
-
const parsed = new
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
parsed.set("query", query);
|
|
66
|
-
return parsed.toString();
|
|
50
|
+
const parsed = new URL(url, FAKE_ORIGIN);
|
|
51
|
+
parsed.searchParams.delete("props_at");
|
|
52
|
+
return parsed.href.replace(parsed.origin, "");
|
|
67
53
|
}
|
|
68
54
|
function urlToPageKey(url) {
|
|
69
|
-
const parsed = new
|
|
70
|
-
|
|
71
|
-
delete
|
|
72
|
-
delete query["format"];
|
|
73
|
-
parsed.set("query", query);
|
|
55
|
+
const parsed = new URL(url, FAKE_ORIGIN);
|
|
56
|
+
parsed.searchParams.delete("props_at");
|
|
57
|
+
parsed.searchParams.delete("format");
|
|
74
58
|
return pathQuery(parsed.toString());
|
|
75
59
|
}
|
|
76
60
|
function withoutHash(url) {
|
|
77
|
-
const parsed = new
|
|
78
|
-
parsed.
|
|
79
|
-
return parsed.
|
|
80
|
-
}
|
|
81
|
-
function withoutBusters(url) {
|
|
82
|
-
const parsed = new import_url_parse.default(url, {}, true);
|
|
83
|
-
const query = parsed.query;
|
|
84
|
-
delete query["format"];
|
|
85
|
-
parsed.set("query", query);
|
|
86
|
-
return pathQuery(parsed.toString());
|
|
61
|
+
const parsed = new URL(url, FAKE_ORIGIN);
|
|
62
|
+
parsed.hash = "";
|
|
63
|
+
return parsed.href.replace(parsed.origin, "");
|
|
87
64
|
}
|
|
88
65
|
function formatForXHR(url) {
|
|
89
66
|
const formats = [withoutHash, withFormatJson];
|
|
@@ -123,6 +100,9 @@ function getIn(node, path) {
|
|
|
123
100
|
return void 0;
|
|
124
101
|
}
|
|
125
102
|
}
|
|
103
|
+
function clone(node) {
|
|
104
|
+
return Array.isArray(node) ? [].slice.call(node) : { ...node };
|
|
105
|
+
}
|
|
126
106
|
function getKey(node, key) {
|
|
127
107
|
if (Array.isArray(node) && Number.isNaN(Number(key))) {
|
|
128
108
|
const key_parts = Array.from(key.split("="));
|
|
@@ -171,9 +151,34 @@ function normalizeKeyPath(path) {
|
|
|
171
151
|
return path;
|
|
172
152
|
}
|
|
173
153
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
154
|
+
function setIn(object, path, value) {
|
|
155
|
+
const keypath = normalizeKeyPath(path);
|
|
156
|
+
const results = { 0: object };
|
|
157
|
+
const parents = { 0: object };
|
|
158
|
+
let i;
|
|
159
|
+
for (i = 0; i < keypath.length; i++) {
|
|
160
|
+
const parent = parents[i];
|
|
161
|
+
if (!(typeof parent === "object" && parent !== null)) {
|
|
162
|
+
throw new KeyPathError(
|
|
163
|
+
`Expected to traverse an Array or Obj, got ${JSON.stringify(parent)}`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
const child = atKey(parent, keypath[i]);
|
|
167
|
+
parents[i + 1] = child;
|
|
168
|
+
}
|
|
169
|
+
results[keypath.length] = value;
|
|
170
|
+
for (i = keypath.length - 1; i >= 0; i--) {
|
|
171
|
+
const target = clone(parents[i]);
|
|
172
|
+
results[i] = target;
|
|
173
|
+
const key = getKey(results[i], keypath[i]);
|
|
174
|
+
if (Array.isArray(target)) {
|
|
175
|
+
target[key] = results[i + 1];
|
|
176
|
+
} else {
|
|
177
|
+
target[key] = results[i + 1];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return results[0];
|
|
181
|
+
}
|
|
177
182
|
|
|
178
183
|
// lib/config.ts
|
|
179
184
|
var config = {
|
|
@@ -181,7 +186,26 @@ var config = {
|
|
|
181
186
|
maxPages: 20
|
|
182
187
|
};
|
|
183
188
|
|
|
189
|
+
// lib/utils/limited_set.ts
|
|
190
|
+
var LimitedSet = class extends Set {
|
|
191
|
+
constructor(maxSize) {
|
|
192
|
+
super();
|
|
193
|
+
this.maxSize = maxSize;
|
|
194
|
+
}
|
|
195
|
+
add(value) {
|
|
196
|
+
if (this.size >= this.maxSize) {
|
|
197
|
+
const iterator = this.values();
|
|
198
|
+
const oldestValue = iterator.next().value;
|
|
199
|
+
this.delete(oldestValue);
|
|
200
|
+
}
|
|
201
|
+
super.add(value);
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
184
206
|
// lib/utils/request.ts
|
|
207
|
+
var import_uuid = require("uuid");
|
|
208
|
+
var lastRequestIds = new LimitedSet(20);
|
|
185
209
|
function isValidResponse(xhr) {
|
|
186
210
|
return isValidContent(xhr) && !downloadingFile(xhr);
|
|
187
211
|
}
|
|
@@ -237,6 +261,9 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
237
261
|
nextHeaders["x-requested-with"] = "XMLHttpRequest";
|
|
238
262
|
nextHeaders["accept"] = "application/json";
|
|
239
263
|
nextHeaders["x-superglue-request"] = "true";
|
|
264
|
+
const requestId = (0, import_uuid.v4)();
|
|
265
|
+
lastRequestIds.add(requestId);
|
|
266
|
+
nextHeaders["X-Superglue-Request-Id"] = requestId;
|
|
240
267
|
if (method != "GET" && method != "HEAD") {
|
|
241
268
|
nextHeaders["content-type"] = "application/json";
|
|
242
269
|
}
|
|
@@ -246,11 +273,7 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
246
273
|
if (currentState.csrfToken) {
|
|
247
274
|
nextHeaders["x-csrf-token"] = currentState.csrfToken;
|
|
248
275
|
}
|
|
249
|
-
const fetchPath = new
|
|
250
|
-
formatForXHR(pathQuery2),
|
|
251
|
-
config.baseUrl || {},
|
|
252
|
-
true
|
|
253
|
-
);
|
|
276
|
+
const fetchPath = new URL(formatForXHR(pathQuery2), config.baseUrl);
|
|
254
277
|
const credentials = "same-origin";
|
|
255
278
|
if (!(method == "GET" || method == "HEAD")) {
|
|
256
279
|
nextHeaders["x-http-method-override"] = method;
|
|
@@ -264,20 +287,16 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
264
287
|
signal
|
|
265
288
|
};
|
|
266
289
|
if (currentState.currentPageKey) {
|
|
267
|
-
const referrer = new
|
|
268
|
-
|
|
269
|
-
config.baseUrl || {},
|
|
270
|
-
false
|
|
271
|
-
).href;
|
|
272
|
-
options.referrer = referrer;
|
|
290
|
+
const referrer = new URL(currentState.currentPageKey, config.baseUrl);
|
|
291
|
+
options.referrer = referrer.toString();
|
|
273
292
|
}
|
|
274
293
|
if (method == "GET" || method == "HEAD") {
|
|
275
294
|
if (options.body instanceof FormData) {
|
|
276
295
|
const allData = new URLSearchParams(
|
|
277
296
|
options.body
|
|
278
297
|
);
|
|
279
|
-
|
|
280
|
-
fetchPath.
|
|
298
|
+
allData.forEach((value, key) => fetchPath.searchParams.delete(key));
|
|
299
|
+
allData.forEach((value, key) => fetchPath.searchParams.append(key, value));
|
|
281
300
|
}
|
|
282
301
|
delete options.body;
|
|
283
302
|
}
|
|
@@ -305,9 +324,6 @@ function needsRefresh(prevAssets, newAssets) {
|
|
|
305
324
|
}
|
|
306
325
|
}
|
|
307
326
|
|
|
308
|
-
// lib/action_creators/index.ts
|
|
309
|
-
var import_url_parse3 = __toESM(require("url-parse"));
|
|
310
|
-
|
|
311
327
|
// lib/actions.ts
|
|
312
328
|
var import_toolkit = require("@reduxjs/toolkit");
|
|
313
329
|
var GRAFTING_ERROR = "@@superglue/GRAFTING_ERROR";
|
|
@@ -339,7 +355,6 @@ var handleGraft = (0, import_toolkit.createAction)(
|
|
|
339
355
|
var superglueError = (0, import_toolkit.createAction)(
|
|
340
356
|
"@@superglue/ERROR"
|
|
341
357
|
);
|
|
342
|
-
var updateFragments = (0, import_toolkit.createAction)("@@superglue/UPDATE_FRAGMENTS");
|
|
343
358
|
var copyPage = (0, import_toolkit.createAction)(
|
|
344
359
|
"@@superglue/COPY_PAGE"
|
|
345
360
|
);
|
|
@@ -354,6 +369,53 @@ var beforeRemote = (0, import_toolkit.createAction)("@@superglue/BEFORE_REMOTE")
|
|
|
354
369
|
var setCSRFToken = (0, import_toolkit.createAction)("@@superglue/SET_CSRF_TOKEN");
|
|
355
370
|
var historyChange = (0, import_toolkit.createAction)("@@superglue/HISTORY_CHANGE");
|
|
356
371
|
var setActivePage = (0, import_toolkit.createAction)("@@superglue/SET_ACTIVE_PAGE");
|
|
372
|
+
var handleFragmentGraft = (0, import_toolkit.createAction)(
|
|
373
|
+
"@@superglue/HANDLE_FRAGMENT_GRAFT",
|
|
374
|
+
({
|
|
375
|
+
fragmentId,
|
|
376
|
+
response
|
|
377
|
+
}) => {
|
|
378
|
+
return {
|
|
379
|
+
payload: {
|
|
380
|
+
response,
|
|
381
|
+
fragmentId
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
var saveFragment = (0, import_toolkit.createAction)(
|
|
387
|
+
"@@superglue/SAVE_FRAGMENT",
|
|
388
|
+
({ fragmentId, data }) => {
|
|
389
|
+
return {
|
|
390
|
+
payload: {
|
|
391
|
+
fragmentId,
|
|
392
|
+
data
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
var appendToFragment = (0, import_toolkit.createAction)(
|
|
398
|
+
"@@superglue/APPEND_TO_FRAGMENT",
|
|
399
|
+
({ data, fragmentId }) => {
|
|
400
|
+
return {
|
|
401
|
+
payload: {
|
|
402
|
+
data,
|
|
403
|
+
fragmentId
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
var prependToFragment = (0, import_toolkit.createAction)(
|
|
409
|
+
"@@superglue/PREPEND_TO_FRAGMENT",
|
|
410
|
+
({ data, fragmentId }) => {
|
|
411
|
+
return {
|
|
412
|
+
payload: {
|
|
413
|
+
data,
|
|
414
|
+
fragmentId
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
);
|
|
357
419
|
|
|
358
420
|
// lib/action_creators/requests.ts
|
|
359
421
|
function handleFetchErr(err, fetchArgs, dispatch) {
|
|
@@ -363,15 +425,18 @@ function handleFetchErr(err, fetchArgs, dispatch) {
|
|
|
363
425
|
function buildMeta(pageKey, page, state, rsp, fetchArgs) {
|
|
364
426
|
const { assets: prevAssets } = state;
|
|
365
427
|
const { assets: nextAssets } = page;
|
|
366
|
-
|
|
428
|
+
const meta = {
|
|
367
429
|
pageKey,
|
|
368
430
|
page,
|
|
369
431
|
redirected: rsp.redirected,
|
|
370
432
|
rsp,
|
|
371
433
|
fetchArgs,
|
|
372
|
-
componentIdentifier: page.componentIdentifier,
|
|
373
434
|
needsRefresh: needsRefresh(prevAssets, nextAssets)
|
|
374
435
|
};
|
|
436
|
+
if (page.action !== "handleStreamResponse") {
|
|
437
|
+
meta.componentIdentifier = page.componentIdentifier;
|
|
438
|
+
}
|
|
439
|
+
return meta;
|
|
375
440
|
}
|
|
376
441
|
var MismatchedComponentError = class extends Error {
|
|
377
442
|
constructor(message) {
|
|
@@ -379,13 +444,13 @@ var MismatchedComponentError = class extends Error {
|
|
|
379
444
|
this.name = "MismatchedComponentError";
|
|
380
445
|
}
|
|
381
446
|
};
|
|
447
|
+
var defaultBeforeSave = (prevPage, receivedPage) => receivedPage;
|
|
382
448
|
var remote = (path, {
|
|
383
449
|
pageKey: targetPageKey,
|
|
384
450
|
force = false,
|
|
385
|
-
beforeSave =
|
|
451
|
+
beforeSave = defaultBeforeSave,
|
|
386
452
|
...rest
|
|
387
453
|
} = {}) => {
|
|
388
|
-
path = withoutBusters(path);
|
|
389
454
|
targetPageKey = targetPageKey && urlToPageKey(targetPageKey);
|
|
390
455
|
return (dispatch, getState) => {
|
|
391
456
|
const fetchArgs = argsForFetch(getState, path, rest);
|
|
@@ -402,10 +467,11 @@ var remote = (path, {
|
|
|
402
467
|
pageKey = targetPageKey;
|
|
403
468
|
}
|
|
404
469
|
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
470
|
+
if (json.action !== "handleStreamResponse") {
|
|
471
|
+
const existingId = pages[pageKey]?.componentIdentifier;
|
|
472
|
+
const receivedId = json.componentIdentifier;
|
|
473
|
+
if (!!existingId && existingId != receivedId && !force) {
|
|
474
|
+
const message = `You cannot replace or update an existing page
|
|
409
475
|
located at pages["${currentPageKey}"] that has a componentIdentifier
|
|
410
476
|
of "${existingId}" with the contents of a page response that has a
|
|
411
477
|
componentIdentifier of "${receivedId}".
|
|
@@ -421,7 +487,8 @@ compatible with the page component associated with "${existingId}".
|
|
|
421
487
|
Consider using data-sg-visit, the visit function, or redirect_back to
|
|
422
488
|
the same page. Or if you're sure you want to proceed, use force: true.
|
|
423
489
|
`;
|
|
424
|
-
|
|
490
|
+
throw new MismatchedComponentError(message);
|
|
491
|
+
}
|
|
425
492
|
}
|
|
426
493
|
const page = beforeSave(pages[pageKey], json);
|
|
427
494
|
return dispatch(saveAndProcessPage(pageKey, page)).then(() => meta);
|
|
@@ -439,7 +506,6 @@ var visit = (path, {
|
|
|
439
506
|
revisit = false,
|
|
440
507
|
...rest
|
|
441
508
|
} = {}) => {
|
|
442
|
-
path = withoutBusters(path);
|
|
443
509
|
return (dispatch, getState) => {
|
|
444
510
|
const currentPageKey = getState().superglue.currentPageKey;
|
|
445
511
|
placeholderKey = placeholderKey && urlToPageKey(placeholderKey) || currentPageKey;
|
|
@@ -466,11 +532,13 @@ var visit = (path, {
|
|
|
466
532
|
const { superglue, pages = {} } = getState();
|
|
467
533
|
const isGet = fetchArgs[1].method === "GET";
|
|
468
534
|
const pageKey = calculatePageKey(rsp, isGet, currentPageKey);
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
const
|
|
535
|
+
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
536
|
+
if (json.action !== "handleStreamResponse") {
|
|
537
|
+
if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
|
|
538
|
+
const existingId = pages[placeholderKey]?.componentIdentifier;
|
|
539
|
+
const receivedId = json.componentIdentifier;
|
|
540
|
+
if (!!existingId && existingId != receivedId) {
|
|
541
|
+
const message = `You received a page response with a
|
|
474
542
|
componentIdentifier "${receivedId}" that is different than the
|
|
475
543
|
componentIdentifier "${existingId}" located at ${placeholderKey}.
|
|
476
544
|
|
|
@@ -486,16 +554,17 @@ Check that you're rendering a page with a matching
|
|
|
486
554
|
componentIdentifier, or consider using redirect_back_with_props_at
|
|
487
555
|
to the same page.
|
|
488
556
|
`;
|
|
489
|
-
|
|
557
|
+
throw new MismatchedComponentError(message);
|
|
558
|
+
}
|
|
559
|
+
dispatch(copyPage({ from: placeholderKey, to: pageKey }));
|
|
490
560
|
}
|
|
491
|
-
dispatch(copyPage({ from: placeholderKey, to: pageKey }));
|
|
492
561
|
}
|
|
493
|
-
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
494
562
|
const visitMeta = {
|
|
495
563
|
...meta,
|
|
496
564
|
navigationAction: calculateNavAction(
|
|
497
565
|
meta,
|
|
498
566
|
rsp,
|
|
567
|
+
json,
|
|
499
568
|
isGet,
|
|
500
569
|
pageKey,
|
|
501
570
|
currentPageKey,
|
|
@@ -507,8 +576,11 @@ to the same page.
|
|
|
507
576
|
}).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
|
|
508
577
|
};
|
|
509
578
|
};
|
|
510
|
-
function calculateNavAction(meta, rsp, isGet, pageKey, currentPageKey, revisit) {
|
|
579
|
+
function calculateNavAction(meta, rsp, json, isGet, pageKey, currentPageKey, revisit) {
|
|
511
580
|
let navigationAction = "push";
|
|
581
|
+
if (json.action === "handleStreamResponse") {
|
|
582
|
+
return "none";
|
|
583
|
+
}
|
|
512
584
|
if (!rsp.redirected && !isGet) {
|
|
513
585
|
navigationAction = "replace";
|
|
514
586
|
}
|
|
@@ -537,6 +609,113 @@ function calculatePageKey(rsp, isGet, currentPageKey) {
|
|
|
537
609
|
return pageKey;
|
|
538
610
|
}
|
|
539
611
|
|
|
612
|
+
// lib/action_creators/stream.ts
|
|
613
|
+
var streamPrepend = (fragments, data, options = {}) => {
|
|
614
|
+
return (dispatch) => {
|
|
615
|
+
if (options.saveAs) {
|
|
616
|
+
const { saveAs } = options;
|
|
617
|
+
dispatch(
|
|
618
|
+
saveFragment({
|
|
619
|
+
fragmentId: saveAs,
|
|
620
|
+
data
|
|
621
|
+
})
|
|
622
|
+
);
|
|
623
|
+
fragments.forEach((fragmentId) => {
|
|
624
|
+
dispatch(
|
|
625
|
+
prependToFragment({
|
|
626
|
+
fragmentId,
|
|
627
|
+
data: {
|
|
628
|
+
__id: saveAs
|
|
629
|
+
}
|
|
630
|
+
})
|
|
631
|
+
);
|
|
632
|
+
});
|
|
633
|
+
} else {
|
|
634
|
+
fragments.forEach((fragmentId) => {
|
|
635
|
+
dispatch(
|
|
636
|
+
prependToFragment({
|
|
637
|
+
fragmentId,
|
|
638
|
+
data
|
|
639
|
+
})
|
|
640
|
+
);
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
};
|
|
645
|
+
var streamAppend = (fragments, data, options = {}) => {
|
|
646
|
+
return (dispatch) => {
|
|
647
|
+
if (options.saveAs) {
|
|
648
|
+
const { saveAs } = options;
|
|
649
|
+
dispatch(
|
|
650
|
+
saveFragment({
|
|
651
|
+
fragmentId: saveAs,
|
|
652
|
+
data
|
|
653
|
+
})
|
|
654
|
+
);
|
|
655
|
+
fragments.forEach((fragmentId) => {
|
|
656
|
+
dispatch(
|
|
657
|
+
appendToFragment({
|
|
658
|
+
fragmentId,
|
|
659
|
+
data: {
|
|
660
|
+
__id: saveAs
|
|
661
|
+
}
|
|
662
|
+
})
|
|
663
|
+
);
|
|
664
|
+
});
|
|
665
|
+
} else {
|
|
666
|
+
fragments.forEach((fragmentId) => {
|
|
667
|
+
dispatch(
|
|
668
|
+
appendToFragment({
|
|
669
|
+
fragmentId,
|
|
670
|
+
data
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
};
|
|
677
|
+
var streamSave = (fragment, data) => {
|
|
678
|
+
return (dispatch) => {
|
|
679
|
+
dispatch(
|
|
680
|
+
saveFragment({
|
|
681
|
+
fragmentId: fragment,
|
|
682
|
+
data
|
|
683
|
+
})
|
|
684
|
+
);
|
|
685
|
+
};
|
|
686
|
+
};
|
|
687
|
+
var handleStreamResponse = (response) => {
|
|
688
|
+
return (dispatch) => {
|
|
689
|
+
let nextResponse = response;
|
|
690
|
+
nextResponse.fragments.reverse().forEach((fragment) => {
|
|
691
|
+
const { id, path } = fragment;
|
|
692
|
+
const node = getIn(nextResponse, path);
|
|
693
|
+
nextResponse = setIn(nextResponse, path, { __id: id });
|
|
694
|
+
dispatch(
|
|
695
|
+
saveFragment({
|
|
696
|
+
fragmentId: id,
|
|
697
|
+
data: node
|
|
698
|
+
})
|
|
699
|
+
);
|
|
700
|
+
});
|
|
701
|
+
nextResponse.data.forEach((message) => {
|
|
702
|
+
if (message.handler === "append") {
|
|
703
|
+
dispatch(
|
|
704
|
+
streamAppend(message.fragmentIds, message.data, message.options)
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
if (message.handler === "prepend") {
|
|
708
|
+
dispatch(
|
|
709
|
+
streamPrepend(message.fragmentIds, message.data, message.options)
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
if (message.handler === "save") {
|
|
713
|
+
dispatch(streamSave(message.fragmentIds[0], message.data));
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
};
|
|
717
|
+
};
|
|
718
|
+
|
|
540
719
|
// lib/action_creators/index.ts
|
|
541
720
|
function fetchDeferments(pageKey, defers = []) {
|
|
542
721
|
pageKey = urlToPageKey(pageKey);
|
|
@@ -546,8 +725,7 @@ function fetchDeferments(pageKey, defers = []) {
|
|
|
546
725
|
successAction = GRAFTING_SUCCESS,
|
|
547
726
|
failAction = GRAFTING_ERROR
|
|
548
727
|
}) {
|
|
549
|
-
const
|
|
550
|
-
const keyPath = parsedUrl.query.props_at;
|
|
728
|
+
const keyPath = propsAtParam(url);
|
|
551
729
|
return dispatch(remote(url, { pageKey })).then(() => {
|
|
552
730
|
dispatch({
|
|
553
731
|
type: successAction,
|
|
@@ -572,57 +750,40 @@ function fetchDeferments(pageKey, defers = []) {
|
|
|
572
750
|
};
|
|
573
751
|
}
|
|
574
752
|
function saveAndProcessPage(pageKey, page) {
|
|
575
|
-
return (dispatch
|
|
753
|
+
return (dispatch) => {
|
|
576
754
|
pageKey = urlToPageKey(pageKey);
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
value: currentFragment,
|
|
592
|
-
path
|
|
593
|
-
})
|
|
594
|
-
);
|
|
595
|
-
} else if (currentFragment !== prevFragment) {
|
|
596
|
-
dispatch(
|
|
597
|
-
updateFragments({
|
|
598
|
-
name: type,
|
|
599
|
-
pageKey,
|
|
600
|
-
value: currentFragment,
|
|
601
|
-
previousValue: prevFragment,
|
|
602
|
-
path
|
|
603
|
-
})
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
} else {
|
|
608
|
-
dispatch(saveResponse({ pageKey, page }));
|
|
609
|
-
const currentPage = getState().pages[pageKey];
|
|
610
|
-
currentPage.fragments.forEach((fragment) => {
|
|
611
|
-
const { type, path } = fragment;
|
|
612
|
-
const currentFragment = getIn(currentPage, path);
|
|
755
|
+
let nextPage = page;
|
|
756
|
+
page.fragments.reverse().forEach((fragment) => {
|
|
757
|
+
const { id, path } = fragment;
|
|
758
|
+
const node = getIn(nextPage, path);
|
|
759
|
+
nextPage = setIn(page, path, { __id: id });
|
|
760
|
+
dispatch(
|
|
761
|
+
saveFragment({
|
|
762
|
+
fragmentId: id,
|
|
763
|
+
data: node
|
|
764
|
+
})
|
|
765
|
+
);
|
|
766
|
+
});
|
|
767
|
+
if (nextPage.action === "graft") {
|
|
768
|
+
if (typeof nextPage.fragmentContext === "string") {
|
|
613
769
|
dispatch(
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
value: currentFragment,
|
|
618
|
-
path
|
|
770
|
+
handleFragmentGraft({
|
|
771
|
+
fragmentId: nextPage.fragmentContext,
|
|
772
|
+
response: nextPage
|
|
619
773
|
})
|
|
620
774
|
);
|
|
621
|
-
}
|
|
775
|
+
} else {
|
|
776
|
+
dispatch(handleGraft({ pageKey, page: nextPage }));
|
|
777
|
+
}
|
|
778
|
+
} else if (nextPage.action === "handleStreamResponse") {
|
|
779
|
+
dispatch(handleStreamResponse(nextPage));
|
|
780
|
+
return Promise.resolve();
|
|
781
|
+
} else {
|
|
782
|
+
dispatch(saveResponse({ pageKey, page: nextPage }));
|
|
622
783
|
}
|
|
623
784
|
const hasFetch = typeof fetch != "undefined";
|
|
624
785
|
if (hasFetch) {
|
|
625
|
-
return dispatch(fetchDeferments(pageKey, defers)).then(
|
|
786
|
+
return dispatch(fetchDeferments(pageKey, nextPage.defers)).then(
|
|
626
787
|
() => Promise.resolve()
|
|
627
788
|
);
|
|
628
789
|
} else {
|