decap-cms-lib-util 2.16.0-beta.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +601 -0
  2. package/LICENSE +22 -0
  3. package/README.md +22 -0
  4. package/dist/decap-cms-lib-util.js +3 -0
  5. package/dist/decap-cms-lib-util.js.LICENSE.txt +15 -0
  6. package/dist/decap-cms-lib-util.js.map +1 -0
  7. package/dist/esm/API.js +177 -0
  8. package/dist/esm/APIError.js +47 -0
  9. package/dist/esm/APIUtils.js +48 -0
  10. package/dist/esm/AccessTokenError.js +41 -0
  11. package/dist/esm/Cursor.js +135 -0
  12. package/dist/esm/EditorialWorkflowError.js +43 -0
  13. package/dist/esm/asyncLock.js +45 -0
  14. package/dist/esm/backendUtil.js +98 -0
  15. package/dist/esm/getBlobSHA.js +19 -0
  16. package/dist/esm/git-lfs.js +123 -0
  17. package/dist/esm/implementation.js +304 -0
  18. package/dist/esm/index.js +403 -0
  19. package/dist/esm/loadScript.js +27 -0
  20. package/dist/esm/localForage.js +25 -0
  21. package/dist/esm/path.js +93 -0
  22. package/dist/esm/promise.js +23 -0
  23. package/dist/esm/types/semaphore.d.js +1 -0
  24. package/dist/esm/unsentRequest.js +123 -0
  25. package/package.json +29 -0
  26. package/src/API.ts +220 -0
  27. package/src/APIError.ts +17 -0
  28. package/src/APIUtils.ts +38 -0
  29. package/src/AccessTokenError.ts +11 -0
  30. package/src/Cursor.ts +178 -0
  31. package/src/EditorialWorkflowError.ts +12 -0
  32. package/src/__tests__/api.spec.js +12 -0
  33. package/src/__tests__/apiUtils.spec.js +74 -0
  34. package/src/__tests__/asyncLock.spec.js +85 -0
  35. package/src/__tests__/backendUtil.spec.js +97 -0
  36. package/src/__tests__/implementation.spec.js +58 -0
  37. package/src/__tests__/path.spec.js +53 -0
  38. package/src/__tests__/unsentRequest.spec.js +19 -0
  39. package/src/asyncLock.ts +43 -0
  40. package/src/backendUtil.ts +120 -0
  41. package/src/getBlobSHA.ts +12 -0
  42. package/src/git-lfs.ts +133 -0
  43. package/src/implementation.ts +573 -0
  44. package/src/index.ts +210 -0
  45. package/src/loadScript.js +24 -0
  46. package/src/localForage.ts +21 -0
  47. package/src/path.ts +86 -0
  48. package/src/promise.ts +21 -0
  49. package/src/types/semaphore.d.ts +5 -0
  50. package/src/unsentRequest.js +133 -0
  51. package/webpack.config.js +3 -0
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.PreviewState = void 0;
7
+ exports.getPreviewStatus = getPreviewStatus;
8
+ exports.isPreviewContext = isPreviewContext;
9
+ exports.readFile = readFile;
10
+ exports.readFileMetadata = readFileMetadata;
11
+ exports.requestWithBackoff = requestWithBackoff;
12
+ exports.throwOnConflictingBranches = throwOnConflictingBranches;
13
+ var _asyncLock = require("./asyncLock");
14
+ var _unsentRequest = _interopRequireDefault(require("./unsentRequest"));
15
+ var _APIError = _interopRequireDefault(require("./APIError"));
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
19
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
20
+ function _extendableBuiltin(cls) {
21
+ function ExtendableBuiltin() {
22
+ var instance = Reflect.construct(cls, Array.from(arguments));
23
+ Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
24
+ return instance;
25
+ }
26
+ ExtendableBuiltin.prototype = Object.create(cls.prototype, {
27
+ constructor: {
28
+ value: cls,
29
+ enumerable: false,
30
+ writable: true,
31
+ configurable: true
32
+ }
33
+ });
34
+ if (Object.setPrototypeOf) {
35
+ Object.setPrototypeOf(ExtendableBuiltin, cls);
36
+ } else {
37
+ ExtendableBuiltin.__proto__ = cls;
38
+ }
39
+ return ExtendableBuiltin;
40
+ }
41
+ class RateLimitError extends _extendableBuiltin(Error) {
42
+ constructor(message, resetSeconds) {
43
+ super(message);
44
+ _defineProperty(this, "resetSeconds", void 0);
45
+ if (resetSeconds < 0) {
46
+ this.resetSeconds = 1;
47
+ } else if (resetSeconds > 60 * 60) {
48
+ this.resetSeconds = 60 * 60;
49
+ } else {
50
+ this.resetSeconds = resetSeconds;
51
+ }
52
+ }
53
+ }
54
+ async function requestWithBackoff(api, req, attempt = 1) {
55
+ if (api.rateLimiter) {
56
+ await api.rateLimiter.acquire();
57
+ }
58
+ try {
59
+ const builtRequest = await api.buildRequest(req);
60
+ const requestFunction = api.requestFunction || _unsentRequest.default.performRequest;
61
+ const response = await requestFunction(builtRequest);
62
+ if (response.status === 429) {
63
+ // GitLab/Bitbucket too many requests
64
+ const text = await response.text().catch(() => 'Too many requests');
65
+ throw new Error(text);
66
+ } else if (response.status === 403) {
67
+ // GitHub too many requests
68
+ const json = await response.json().catch(() => ({
69
+ message: ''
70
+ }));
71
+ if (json.message.match('API rate limit exceeded')) {
72
+ const now = new Date();
73
+ const nextWindowInSeconds = response.headers.has('X-RateLimit-Reset') ? parseInt(response.headers.get('X-RateLimit-Reset')) : now.getTime() / 1000 + 60;
74
+ throw new RateLimitError(json.message, nextWindowInSeconds);
75
+ }
76
+ response.json = () => Promise.resolve(json);
77
+ }
78
+ return response;
79
+ } catch (err) {
80
+ if (attempt > 5 || err.message === "Can't refresh access token when using implicit auth") {
81
+ throw err;
82
+ } else {
83
+ if (!api.rateLimiter) {
84
+ const timeout = err.resetSeconds || attempt * attempt;
85
+ console.log(`Pausing requests for ${timeout} ${attempt === 1 ? 'second' : 'seconds'} due to fetch failures:`, err.message);
86
+ api.rateLimiter = (0, _asyncLock.asyncLock)();
87
+ api.rateLimiter.acquire();
88
+ setTimeout(() => {
89
+ var _api$rateLimiter;
90
+ (_api$rateLimiter = api.rateLimiter) === null || _api$rateLimiter === void 0 ? void 0 : _api$rateLimiter.release();
91
+ api.rateLimiter = undefined;
92
+ console.log(`Done pausing requests`);
93
+ }, 1000 * timeout);
94
+ }
95
+ return requestWithBackoff(api, req, attempt + 1);
96
+ }
97
+ }
98
+ }
99
+ async function readFile(id, fetchContent, localForage, isText) {
100
+ const key = id ? isText ? `gh.${id}` : `gh.${id}.blob` : null;
101
+ const cached = key ? await localForage.getItem(key) : null;
102
+ if (cached) {
103
+ return cached;
104
+ }
105
+ const content = await fetchContent();
106
+ if (key) {
107
+ await localForage.setItem(key, content);
108
+ }
109
+ return content;
110
+ }
111
+ function getFileMetadataKey(id) {
112
+ return `gh.${id}.meta`;
113
+ }
114
+ async function readFileMetadata(id, fetchMetadata, localForage) {
115
+ const key = id ? getFileMetadataKey(id) : null;
116
+ const cached = key && (await localForage.getItem(key));
117
+ if (cached) {
118
+ return cached;
119
+ }
120
+ const metadata = await fetchMetadata();
121
+ if (key) {
122
+ await localForage.setItem(key, metadata);
123
+ }
124
+ return metadata;
125
+ }
126
+
127
+ /**
128
+ * Keywords for inferring a status that will provide a deploy preview URL.
129
+ */
130
+ const PREVIEW_CONTEXT_KEYWORDS = ['deploy'];
131
+
132
+ /**
133
+ * Check a given status context string to determine if it provides a link to a
134
+ * deploy preview. Checks for an exact match against `previewContext` if given,
135
+ * otherwise checks for inclusion of a value from `PREVIEW_CONTEXT_KEYWORDS`.
136
+ */
137
+ function isPreviewContext(context, previewContext) {
138
+ if (previewContext) {
139
+ return context === previewContext;
140
+ }
141
+ return PREVIEW_CONTEXT_KEYWORDS.some(keyword => context.includes(keyword));
142
+ }
143
+ let PreviewState = /*#__PURE__*/function (PreviewState) {
144
+ PreviewState["Other"] = "other";
145
+ PreviewState["Success"] = "success";
146
+ return PreviewState;
147
+ }({});
148
+ /**
149
+ * Retrieve a deploy preview URL from an array of statuses. By default, a
150
+ * matching status is inferred via `isPreviewContext`.
151
+ */
152
+ exports.PreviewState = PreviewState;
153
+ function getPreviewStatus(statuses, previewContext) {
154
+ return statuses.find(({
155
+ context
156
+ }) => {
157
+ return isPreviewContext(context, previewContext);
158
+ });
159
+ }
160
+ function getConflictingBranches(branchName) {
161
+ // for cms/posts/post-1, conflicting branches are cms/posts, cms
162
+ const parts = branchName.split('/');
163
+ parts.pop();
164
+ const conflictingBranches = parts.reduce((acc, _, index) => {
165
+ acc = [...acc, parts.slice(0, index + 1).join('/')];
166
+ return acc;
167
+ }, []);
168
+ return conflictingBranches;
169
+ }
170
+ async function throwOnConflictingBranches(branchName, getBranch, apiName) {
171
+ const possibleConflictingBranches = getConflictingBranches(branchName);
172
+ const conflictingBranches = await Promise.all(possibleConflictingBranches.map(b => getBranch(b).then(b => b.name).catch(() => '')));
173
+ const conflictingBranch = conflictingBranches.filter(Boolean)[0];
174
+ if (conflictingBranch) {
175
+ throw new _APIError.default(`Failed creating branch '${branchName}' since there is already a branch named '${conflictingBranch}'. Please delete the '${conflictingBranch}' branch and try again`, 500, apiName);
176
+ }
177
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.API_ERROR = void 0;
7
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
9
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
10
+ function _extendableBuiltin(cls) {
11
+ function ExtendableBuiltin() {
12
+ var instance = Reflect.construct(cls, Array.from(arguments));
13
+ Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
14
+ return instance;
15
+ }
16
+ ExtendableBuiltin.prototype = Object.create(cls.prototype, {
17
+ constructor: {
18
+ value: cls,
19
+ enumerable: false,
20
+ writable: true,
21
+ configurable: true
22
+ }
23
+ });
24
+ if (Object.setPrototypeOf) {
25
+ Object.setPrototypeOf(ExtendableBuiltin, cls);
26
+ } else {
27
+ ExtendableBuiltin.__proto__ = cls;
28
+ }
29
+ return ExtendableBuiltin;
30
+ }
31
+ const API_ERROR = 'API_ERROR';
32
+ exports.API_ERROR = API_ERROR;
33
+ class APIError extends _extendableBuiltin(Error) {
34
+ constructor(message, status, api, meta = {}) {
35
+ super(message);
36
+ _defineProperty(this, "message", void 0);
37
+ _defineProperty(this, "status", void 0);
38
+ _defineProperty(this, "api", void 0);
39
+ _defineProperty(this, "meta", void 0);
40
+ this.message = message;
41
+ this.status = status;
42
+ this.api = api;
43
+ this.name = API_ERROR;
44
+ this.meta = meta;
45
+ }
46
+ }
47
+ exports.default = APIError;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MERGE_COMMIT_MESSAGE = exports.DEFAULT_PR_BODY = exports.CMS_BRANCH_PREFIX = void 0;
7
+ exports.branchFromContentKey = branchFromContentKey;
8
+ exports.contentKeyFromBranch = contentKeyFromBranch;
9
+ exports.generateContentKey = generateContentKey;
10
+ exports.isCMSLabel = isCMSLabel;
11
+ exports.labelToStatus = labelToStatus;
12
+ exports.parseContentKey = parseContentKey;
13
+ exports.statusToLabel = statusToLabel;
14
+ const CMS_BRANCH_PREFIX = 'cms';
15
+ exports.CMS_BRANCH_PREFIX = CMS_BRANCH_PREFIX;
16
+ const DEFAULT_PR_BODY = 'Automatically generated by Decap CMS';
17
+ exports.DEFAULT_PR_BODY = DEFAULT_PR_BODY;
18
+ const MERGE_COMMIT_MESSAGE = 'Automatically generated. Merged on Decap CMS.';
19
+ exports.MERGE_COMMIT_MESSAGE = MERGE_COMMIT_MESSAGE;
20
+ const DEFAULT_DECAP_CMS_LABEL_PREFIX = 'decap-cms/';
21
+ function getLabelPrefix(labelPrefix) {
22
+ return labelPrefix || DEFAULT_DECAP_CMS_LABEL_PREFIX;
23
+ }
24
+ function isCMSLabel(label, labelPrefix) {
25
+ return label.startsWith(getLabelPrefix(labelPrefix));
26
+ }
27
+ function labelToStatus(label, labelPrefix) {
28
+ return label.slice(getLabelPrefix(labelPrefix).length);
29
+ }
30
+ function statusToLabel(status, labelPrefix) {
31
+ return `${getLabelPrefix(labelPrefix)}${status}`;
32
+ }
33
+ function generateContentKey(collectionName, slug) {
34
+ return `${collectionName}/${slug}`;
35
+ }
36
+ function parseContentKey(contentKey) {
37
+ const index = contentKey.indexOf('/');
38
+ return {
39
+ collection: contentKey.slice(0, index),
40
+ slug: contentKey.slice(index + 1)
41
+ };
42
+ }
43
+ function contentKeyFromBranch(branch) {
44
+ return branch.slice(`${CMS_BRANCH_PREFIX}/`.length);
45
+ }
46
+ function branchFromContentKey(contentKey) {
47
+ return `${CMS_BRANCH_PREFIX}/${contentKey}`;
48
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.ACCESS_TOKEN_ERROR = void 0;
7
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
9
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
10
+ function _extendableBuiltin(cls) {
11
+ function ExtendableBuiltin() {
12
+ var instance = Reflect.construct(cls, Array.from(arguments));
13
+ Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
14
+ return instance;
15
+ }
16
+ ExtendableBuiltin.prototype = Object.create(cls.prototype, {
17
+ constructor: {
18
+ value: cls,
19
+ enumerable: false,
20
+ writable: true,
21
+ configurable: true
22
+ }
23
+ });
24
+ if (Object.setPrototypeOf) {
25
+ Object.setPrototypeOf(ExtendableBuiltin, cls);
26
+ } else {
27
+ ExtendableBuiltin.__proto__ = cls;
28
+ }
29
+ return ExtendableBuiltin;
30
+ }
31
+ const ACCESS_TOKEN_ERROR = 'ACCESS_TOKEN_ERROR';
32
+ exports.ACCESS_TOKEN_ERROR = ACCESS_TOKEN_ERROR;
33
+ class AccessTokenError extends _extendableBuiltin(Error) {
34
+ constructor(message) {
35
+ super(message);
36
+ _defineProperty(this, "message", void 0);
37
+ this.message = message;
38
+ this.name = ACCESS_TOKEN_ERROR;
39
+ }
40
+ }
41
+ exports.default = AccessTokenError;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.CURSOR_COMPATIBILITY_SYMBOL = void 0;
7
+ var _immutable = require("immutable");
8
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
9
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
10
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
11
+ function jsToMap(obj) {
12
+ if (obj === undefined) {
13
+ return (0, _immutable.Map)();
14
+ }
15
+ const immutableObj = (0, _immutable.fromJS)(obj);
16
+ if (!_immutable.Map.isMap(immutableObj)) {
17
+ throw new Error('Object must be equivalent to a Map.');
18
+ }
19
+ return immutableObj;
20
+ }
21
+ const knownMetaKeys = (0, _immutable.Set)(['index', 'page', 'count', 'pageSize', 'pageCount', 'usingOldPaginationAPI', 'extension', 'folder', 'depth']);
22
+ function filterUnknownMetaKeys(meta) {
23
+ return meta.filter((_v, k) => knownMetaKeys.has(k));
24
+ }
25
+
26
+ /*
27
+ createCursorMap takes one of three signatures:
28
+ - () -> cursor with empty actions, data, and meta
29
+ - (cursorMap: <object/Map with optional actions, data, and meta keys>) -> cursor
30
+ - (actions: <array/List>, data: <object/Map>, meta: <optional object/Map>) -> cursor
31
+ */
32
+ function createCursorStore(...args) {
33
+ const {
34
+ actions,
35
+ data,
36
+ meta
37
+ } = args.length === 1 ? jsToMap(args[0]).toObject() : {
38
+ actions: args[0],
39
+ data: args[1],
40
+ meta: args[2]
41
+ };
42
+ return (0, _immutable.Map)({
43
+ // actions are a Set, rather than a List, to ensure an efficient .has
44
+ actions: (0, _immutable.Set)(actions),
45
+ // data and meta are Maps
46
+ data: jsToMap(data),
47
+ meta: jsToMap(meta).update(filterUnknownMetaKeys)
48
+ });
49
+ }
50
+ function hasAction(store, action) {
51
+ return store.hasIn(['actions', action]);
52
+ }
53
+ function getActionHandlers(store, handler) {
54
+ return store.get('actions', (0, _immutable.Set)()).toMap().map(action => handler(action));
55
+ }
56
+
57
+ // The cursor logic is entirely functional, so this class simply
58
+ // provides a chainable interface
59
+ class Cursor {
60
+ static create(...args) {
61
+ return new Cursor(...args);
62
+ }
63
+ constructor(...args) {
64
+ _defineProperty(this, "store", void 0);
65
+ _defineProperty(this, "actions", void 0);
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ _defineProperty(this, "data", void 0);
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ _defineProperty(this, "meta", void 0);
70
+ if (args[0] instanceof Cursor) {
71
+ return args[0];
72
+ }
73
+ this.store = createCursorStore(...args);
74
+ this.actions = this.store.get('actions');
75
+ this.data = this.store.get('data');
76
+ this.meta = this.store.get('meta');
77
+ }
78
+
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ updateStore(...args) {
81
+ return new Cursor(this.store.update(...args));
82
+ }
83
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
+ updateInStore(...args) {
85
+ return new Cursor(this.store.updateIn(...args));
86
+ }
87
+ hasAction(action) {
88
+ return hasAction(this.store, action);
89
+ }
90
+ addAction(action) {
91
+ return this.updateStore('actions', actions => actions.add(action));
92
+ }
93
+ removeAction(action) {
94
+ return this.updateStore('actions', actions => actions.delete(action));
95
+ }
96
+ setActions(actions) {
97
+ return this.updateStore(store => store.set('actions', (0, _immutable.Set)(actions)));
98
+ }
99
+ mergeActions(actions) {
100
+ return this.updateStore('actions', oldActions => oldActions.union(actions));
101
+ }
102
+ getActionHandlers(handler) {
103
+ return getActionHandlers(this.store, handler);
104
+ }
105
+ setData(data) {
106
+ return new Cursor(this.store.set('data', jsToMap(data)));
107
+ }
108
+ mergeData(data) {
109
+ return new Cursor(this.store.mergeIn(['data'], jsToMap(data)));
110
+ }
111
+ wrapData(data) {
112
+ return this.updateStore('data', oldData => jsToMap(data).set('wrapped_cursor_data', oldData));
113
+ }
114
+ unwrapData() {
115
+ return [this.store.get('data').delete('wrapped_cursor_data'), this.updateStore('data', data => data.get('wrapped_cursor_data'))];
116
+ }
117
+ clearData() {
118
+ return this.updateStore('data', () => (0, _immutable.Map)());
119
+ }
120
+ setMeta(meta) {
121
+ return this.updateStore(store => store.set('meta', jsToMap(meta)));
122
+ }
123
+ mergeMeta(meta) {
124
+ return this.updateStore(store => store.update('meta', oldMeta => oldMeta.merge(jsToMap(meta))));
125
+ }
126
+ }
127
+
128
+ // This is a temporary hack to allow cursors to be added to the
129
+ // interface between backend.js and backends without modifying old
130
+ // backends at all. This should be removed in favor of wrapping old
131
+ // backends with a compatibility layer, as part of the backend API
132
+ // refactor.
133
+ exports.default = Cursor;
134
+ const CURSOR_COMPATIBILITY_SYMBOL = Symbol('cursor key for compatibility with old backends');
135
+ exports.CURSOR_COMPATIBILITY_SYMBOL = CURSOR_COMPATIBILITY_SYMBOL;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.EDITORIAL_WORKFLOW_ERROR = void 0;
7
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
9
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
10
+ function _extendableBuiltin(cls) {
11
+ function ExtendableBuiltin() {
12
+ var instance = Reflect.construct(cls, Array.from(arguments));
13
+ Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
14
+ return instance;
15
+ }
16
+ ExtendableBuiltin.prototype = Object.create(cls.prototype, {
17
+ constructor: {
18
+ value: cls,
19
+ enumerable: false,
20
+ writable: true,
21
+ configurable: true
22
+ }
23
+ });
24
+ if (Object.setPrototypeOf) {
25
+ Object.setPrototypeOf(ExtendableBuiltin, cls);
26
+ } else {
27
+ ExtendableBuiltin.__proto__ = cls;
28
+ }
29
+ return ExtendableBuiltin;
30
+ }
31
+ const EDITORIAL_WORKFLOW_ERROR = 'EDITORIAL_WORKFLOW_ERROR';
32
+ exports.EDITORIAL_WORKFLOW_ERROR = EDITORIAL_WORKFLOW_ERROR;
33
+ class EditorialWorkflowError extends _extendableBuiltin(Error) {
34
+ constructor(message, notUnderEditorialWorkflow) {
35
+ super(message);
36
+ _defineProperty(this, "message", void 0);
37
+ _defineProperty(this, "notUnderEditorialWorkflow", void 0);
38
+ this.message = message;
39
+ this.notUnderEditorialWorkflow = notUnderEditorialWorkflow;
40
+ this.name = EDITORIAL_WORKFLOW_ERROR;
41
+ }
42
+ }
43
+ exports.default = EditorialWorkflowError;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.asyncLock = asyncLock;
7
+ var _semaphore = _interopRequireDefault(require("semaphore"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ function asyncLock() {
10
+ let lock = (0, _semaphore.default)(1);
11
+ function acquire(timeout = 15000) {
12
+ const promise = new Promise(resolve => {
13
+ // this makes sure a caller doesn't gets stuck forever awaiting on the lock
14
+ const timeoutId = setTimeout(() => {
15
+ // we reset the lock in that case to allow future consumers to use it without being blocked
16
+ lock = (0, _semaphore.default)(1);
17
+ resolve(false);
18
+ }, timeout);
19
+ lock.take(() => {
20
+ clearTimeout(timeoutId);
21
+ resolve(true);
22
+ });
23
+ });
24
+ return promise;
25
+ }
26
+ function release() {
27
+ try {
28
+ // suppress too many calls to leave error
29
+ lock.leave();
30
+ } catch (e) {
31
+ // calling 'leave' too many times might not be good behavior
32
+ // but there is no reason to completely fail on it
33
+ if (e.message !== 'leave called too many times.') {
34
+ throw e;
35
+ } else {
36
+ console.warn('leave called too many times.');
37
+ lock = (0, _semaphore.default)(1);
38
+ }
39
+ }
40
+ }
41
+ return {
42
+ acquire,
43
+ release
44
+ };
45
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.filterByExtension = filterByExtension;
7
+ exports.getAllResponses = getAllResponses;
8
+ exports.getPathDepth = getPathDepth;
9
+ exports.parseLinkHeader = parseLinkHeader;
10
+ exports.parseResponse = parseResponse;
11
+ exports.responseParser = responseParser;
12
+ var _map2 = _interopRequireDefault(require("lodash/fp/map"));
13
+ var _fromPairs2 = _interopRequireDefault(require("lodash/fromPairs"));
14
+ var _flow2 = _interopRequireDefault(require("lodash/flow"));
15
+ var _immutable = require("immutable");
16
+ var _unsentRequest = _interopRequireDefault(require("./unsentRequest"));
17
+ var _APIError = _interopRequireDefault(require("./APIError"));
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+ function filterByExtension(file, extension) {
20
+ const path = (file === null || file === void 0 ? void 0 : file.path) || '';
21
+ return path.endsWith(extension.startsWith('.') ? extension : `.${extension}`);
22
+ }
23
+ function catchFormatErrors(format, formatter) {
24
+ return res => {
25
+ try {
26
+ return formatter(res);
27
+ } catch (err) {
28
+ throw new Error(`Response cannot be parsed into the expected format (${format}): ${err.message}`);
29
+ }
30
+ };
31
+ }
32
+ const responseFormatters = (0, _immutable.fromJS)({
33
+ json: async res => {
34
+ const contentType = res.headers.get('Content-Type') || '';
35
+ if (!contentType.startsWith('application/json') && !contentType.startsWith('text/json')) {
36
+ throw new Error(`${contentType} is not a valid JSON Content-Type`);
37
+ }
38
+ return res.json();
39
+ },
40
+ text: async res => res.text(),
41
+ blob: async res => res.blob()
42
+ }).mapEntries(([format, formatter]) => [format, catchFormatErrors(format, formatter)]);
43
+ async function parseResponse(res, {
44
+ expectingOk = true,
45
+ format = 'text',
46
+ apiName = ''
47
+ }) {
48
+ let body;
49
+ try {
50
+ const formatter = responseFormatters.get(format, false);
51
+ if (!formatter) {
52
+ throw new Error(`${format} is not a supported response format.`);
53
+ }
54
+ body = await formatter(res);
55
+ } catch (err) {
56
+ throw new _APIError.default(err.message, res.status, apiName);
57
+ }
58
+ if (expectingOk && !res.ok) {
59
+ var _body$error;
60
+ const isJSON = format === 'json';
61
+ const message = isJSON ? body.message || body.msg || ((_body$error = body.error) === null || _body$error === void 0 ? void 0 : _body$error.message) : body;
62
+ throw new _APIError.default(isJSON && message ? message : body, res.status, apiName);
63
+ }
64
+ return body;
65
+ }
66
+ function responseParser(options) {
67
+ return res => parseResponse(res, options);
68
+ }
69
+ function parseLinkHeader(header) {
70
+ if (!header) {
71
+ return {};
72
+ }
73
+ return (0, _flow2.default)([linksString => linksString.split(','), (0, _map2.default)(str => str.trim().split(';')), (0, _map2.default)(([linkStr, keyStr]) => [keyStr.match(/rel="(.*?)"/)[1], linkStr.trim().match(/<(.*?)>/)[1].replace(/\+/g, '%20')]), _fromPairs2.default])(header);
74
+ }
75
+ async function getAllResponses(url, options = {}, linkHeaderRelName, nextUrlProcessor) {
76
+ const maxResponses = 30;
77
+ let responseCount = 1;
78
+ let req = _unsentRequest.default.fromFetchArguments(url, options);
79
+ const pageResponses = [];
80
+ while (req && responseCount < maxResponses) {
81
+ const pageResponse = await _unsentRequest.default.performRequest(req);
82
+ const linkHeader = pageResponse.headers.get('Link');
83
+ const nextURL = linkHeader && parseLinkHeader(linkHeader)[linkHeaderRelName];
84
+ const {
85
+ headers = {}
86
+ } = options;
87
+ req = nextURL && _unsentRequest.default.fromFetchArguments(nextUrlProcessor(nextURL), {
88
+ headers
89
+ });
90
+ pageResponses.push(pageResponse);
91
+ responseCount++;
92
+ }
93
+ return pageResponses;
94
+ }
95
+ function getPathDepth(path) {
96
+ const depth = path.split('/').length;
97
+ return depth;
98
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _jsSha = require("js-sha256");
8
+ var _default = blob => new Promise((resolve, reject) => {
9
+ const fr = new FileReader();
10
+ fr.onload = ({
11
+ target
12
+ }) => resolve((0, _jsSha.sha256)((target === null || target === void 0 ? void 0 : target.result) || ''));
13
+ fr.onerror = err => {
14
+ fr.abort();
15
+ reject(err);
16
+ };
17
+ fr.readAsArrayBuffer(blob);
18
+ });
19
+ exports.default = _default;