decap-cms-lib-util 3.2.0 → 3.3.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.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/decap-cms-lib-util.js +1 -1
  3. package/dist/decap-cms-lib-util.js.LICENSE.txt +9 -0
  4. package/dist/decap-cms-lib-util.js.map +1 -1
  5. package/dist/esm/API.js +17 -25
  6. package/dist/esm/APIError.js +0 -7
  7. package/dist/esm/AccessTokenError.js +0 -4
  8. package/dist/esm/Cursor.js +4 -9
  9. package/dist/esm/EditorialWorkflowError.js +0 -5
  10. package/dist/esm/backendUtil.js +6 -7
  11. package/dist/esm/getBlobSHA.js +3 -3
  12. package/dist/esm/git-lfs.js +21 -29
  13. package/dist/esm/implementation.js +14 -17
  14. package/dist/esm/unsentRequest.js +9 -12
  15. package/package.json +5 -2
  16. package/CHANGELOG.md +0 -382
  17. package/dist/esm/stega.js +0 -129
  18. package/src/API.ts +0 -376
  19. package/src/APIError.ts +0 -17
  20. package/src/APIUtils.ts +0 -38
  21. package/src/AccessTokenError.ts +0 -11
  22. package/src/Cursor.ts +0 -178
  23. package/src/EditorialWorkflowError.ts +0 -12
  24. package/src/__tests__/api.spec.js +0 -13
  25. package/src/__tests__/apiUtils.spec.js +0 -74
  26. package/src/__tests__/asyncLock.spec.js +0 -85
  27. package/src/__tests__/backendUtil.spec.js +0 -97
  28. package/src/__tests__/implementation.spec.js +0 -58
  29. package/src/__tests__/path.spec.js +0 -53
  30. package/src/__tests__/unsentRequest.spec.js +0 -19
  31. package/src/asyncLock.ts +0 -43
  32. package/src/backendUtil.ts +0 -120
  33. package/src/getBlobSHA.ts +0 -12
  34. package/src/git-lfs.ts +0 -133
  35. package/src/implementation.ts +0 -575
  36. package/src/index.ts +0 -213
  37. package/src/loadScript.js +0 -24
  38. package/src/localForage.ts +0 -21
  39. package/src/path.ts +0 -86
  40. package/src/promise.ts +0 -21
  41. package/src/stega.ts +0 -134
  42. package/src/types/semaphore.d.ts +0 -5
  43. package/src/types.ts +0 -9
  44. package/src/unsentRequest.js +0 -133
  45. package/webpack.config.js +0 -3
package/src/index.ts DELETED
@@ -1,213 +0,0 @@
1
- import APIError from './APIError';
2
- import Cursor, { CURSOR_COMPATIBILITY_SYMBOL } from './Cursor';
3
- import EditorialWorkflowError, { EDITORIAL_WORKFLOW_ERROR } from './EditorialWorkflowError';
4
- import AccessTokenError from './AccessTokenError';
5
- import localForage from './localForage';
6
- import { isAbsolutePath, basename, fileExtensionWithSeparator, fileExtension } from './path';
7
- import { onlySuccessfulPromises, flowAsync, then } from './promise';
8
- import unsentRequest from './unsentRequest';
9
- import {
10
- filterByExtension,
11
- getAllResponses,
12
- parseLinkHeader,
13
- parseResponse,
14
- responseParser,
15
- getPathDepth,
16
- } from './backendUtil';
17
- import loadScript from './loadScript';
18
- import getBlobSHA from './getBlobSHA';
19
- import { asyncLock } from './asyncLock';
20
- import {
21
- entriesByFiles,
22
- entriesByFolder,
23
- unpublishedEntries,
24
- getMediaDisplayURL,
25
- getMediaAsBlob,
26
- runWithLock,
27
- blobToFileObj,
28
- allEntriesByFolder,
29
- } from './implementation';
30
- import {
31
- readFile,
32
- readFileMetadata,
33
- isPreviewContext,
34
- getPreviewStatus,
35
- PreviewState,
36
- requestWithBackoff,
37
- getDefaultBranchName,
38
- throwOnConflictingBranches,
39
- } from './API';
40
- import {
41
- CMS_BRANCH_PREFIX,
42
- generateContentKey,
43
- isCMSLabel,
44
- labelToStatus,
45
- statusToLabel,
46
- DEFAULT_PR_BODY,
47
- MERGE_COMMIT_MESSAGE,
48
- parseContentKey,
49
- branchFromContentKey,
50
- contentKeyFromBranch,
51
- } from './APIUtils';
52
- import {
53
- createPointerFile,
54
- getLargeMediaFilteredMediaFiles,
55
- getLargeMediaPatternsFromGitAttributesFile,
56
- parsePointerFile,
57
- getPointerFileForMediaFileObj,
58
- } from './git-lfs';
59
-
60
- import type { PointerFile as PF } from './git-lfs';
61
- import type { FetchError as FE, ApiRequest as AR } from './API';
62
- import type {
63
- Implementation as I,
64
- ImplementationEntry as IE,
65
- UnpublishedEntryDiff as UED,
66
- UnpublishedEntry as UE,
67
- ImplementationMediaFile as IMF,
68
- ImplementationFile as IF,
69
- DisplayURLObject as DUO,
70
- DisplayURL as DU,
71
- Credentials as Cred,
72
- User as U,
73
- Entry as E,
74
- PersistOptions as PO,
75
- AssetProxy as AP,
76
- Config as C,
77
- UnpublishedEntryMediaFile as UEMF,
78
- DataFile as DF,
79
- } from './implementation';
80
- import type { AsyncLock as AL } from './asyncLock';
81
-
82
- export type AsyncLock = AL;
83
- export type Implementation = I;
84
- export type ImplementationEntry = IE;
85
- export type UnpublishedEntryDiff = UED;
86
- export type UnpublishedEntry = UE;
87
- export type ImplementationMediaFile = IMF;
88
- export type ImplementationFile = IF;
89
- export type DisplayURL = DU;
90
- export type DisplayURLObject = DUO;
91
- export type Credentials = Cred;
92
- export type User = U;
93
- export type Entry = E;
94
- export type UnpublishedEntryMediaFile = UEMF;
95
- export type PersistOptions = PO;
96
- export type AssetProxy = AP;
97
- export type ApiRequest = AR;
98
- export type Config = C;
99
- export type FetchError = FE;
100
- export type PointerFile = PF;
101
- export type DataFile = DF;
102
-
103
- export const DecapCmsLibUtil = {
104
- APIError,
105
- Cursor,
106
- CURSOR_COMPATIBILITY_SYMBOL,
107
- EditorialWorkflowError,
108
- EDITORIAL_WORKFLOW_ERROR,
109
- localForage,
110
- basename,
111
- fileExtensionWithSeparator,
112
- fileExtension,
113
- onlySuccessfulPromises,
114
- flowAsync,
115
- then,
116
- unsentRequest,
117
- filterByExtension,
118
- parseLinkHeader,
119
- parseResponse,
120
- responseParser,
121
- loadScript,
122
- getBlobSHA,
123
- getPathDepth,
124
- entriesByFiles,
125
- entriesByFolder,
126
- unpublishedEntries,
127
- getMediaDisplayURL,
128
- getMediaAsBlob,
129
- readFile,
130
- readFileMetadata,
131
- CMS_BRANCH_PREFIX,
132
- generateContentKey,
133
- isCMSLabel,
134
- labelToStatus,
135
- statusToLabel,
136
- DEFAULT_PR_BODY,
137
- MERGE_COMMIT_MESSAGE,
138
- isPreviewContext,
139
- getPreviewStatus,
140
- runWithLock,
141
- PreviewState,
142
- parseContentKey,
143
- createPointerFile,
144
- getLargeMediaFilteredMediaFiles,
145
- getLargeMediaPatternsFromGitAttributesFile,
146
- parsePointerFile,
147
- getPointerFileForMediaFileObj,
148
- branchFromContentKey,
149
- contentKeyFromBranch,
150
- blobToFileObj,
151
- requestWithBackoff,
152
- getDefaultBranchName,
153
- allEntriesByFolder,
154
- AccessTokenError,
155
- throwOnConflictingBranches,
156
- };
157
- export {
158
- APIError,
159
- Cursor,
160
- CURSOR_COMPATIBILITY_SYMBOL,
161
- EditorialWorkflowError,
162
- EDITORIAL_WORKFLOW_ERROR,
163
- localForage,
164
- basename,
165
- fileExtensionWithSeparator,
166
- fileExtension,
167
- onlySuccessfulPromises,
168
- flowAsync,
169
- then,
170
- unsentRequest,
171
- filterByExtension,
172
- parseLinkHeader,
173
- getAllResponses,
174
- parseResponse,
175
- responseParser,
176
- loadScript,
177
- getBlobSHA,
178
- asyncLock,
179
- isAbsolutePath,
180
- getPathDepth,
181
- entriesByFiles,
182
- entriesByFolder,
183
- unpublishedEntries,
184
- getMediaDisplayURL,
185
- getMediaAsBlob,
186
- readFile,
187
- readFileMetadata,
188
- CMS_BRANCH_PREFIX,
189
- generateContentKey,
190
- isCMSLabel,
191
- labelToStatus,
192
- statusToLabel,
193
- DEFAULT_PR_BODY,
194
- MERGE_COMMIT_MESSAGE,
195
- isPreviewContext,
196
- getPreviewStatus,
197
- runWithLock,
198
- PreviewState,
199
- parseContentKey,
200
- createPointerFile,
201
- getLargeMediaFilteredMediaFiles,
202
- getLargeMediaPatternsFromGitAttributesFile,
203
- parsePointerFile,
204
- getPointerFileForMediaFileObj,
205
- branchFromContentKey,
206
- contentKeyFromBranch,
207
- blobToFileObj,
208
- requestWithBackoff,
209
- getDefaultBranchName,
210
- allEntriesByFolder,
211
- AccessTokenError,
212
- throwOnConflictingBranches,
213
- };
package/src/loadScript.js DELETED
@@ -1,24 +0,0 @@
1
- /**
2
- * Simple script loader that returns a promise.
3
- */
4
- export default function loadScript(url) {
5
- return new Promise((resolve, reject) => {
6
- let done = false;
7
- const head = document.getElementsByTagName('head')[0];
8
- const script = document.createElement('script');
9
- script.src = url;
10
- script.onload = script.onreadystatechange = function () {
11
- if (
12
- !done &&
13
- (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete')
14
- ) {
15
- done = true;
16
- resolve();
17
- } else {
18
- reject();
19
- }
20
- };
21
- script.onerror = error => reject(error);
22
- head.appendChild(script);
23
- });
24
- }
@@ -1,21 +0,0 @@
1
- import localForage from 'localforage';
2
-
3
- function localForageTest() {
4
- const testKey = 'localForageTest';
5
- localForage
6
- .setItem(testKey, { expires: Date.now() + 300000 })
7
- .then(() => {
8
- localForage.removeItem(testKey);
9
- })
10
- .catch(err => {
11
- if (err.code === 22) {
12
- const message = 'Unable to set localStorage key. Quota exceeded! Full disk?';
13
- console.warn(message);
14
- }
15
- console.log(err);
16
- });
17
- }
18
-
19
- localForageTest();
20
-
21
- export default localForage;
package/src/path.ts DELETED
@@ -1,86 +0,0 @@
1
- const absolutePath = new RegExp('^(?:[a-z]+:)?//', 'i');
2
-
3
- function normalizePath(path: string) {
4
- return path.replace(/[\\/]+/g, '/');
5
- }
6
-
7
- export function isAbsolutePath(path: string) {
8
- return absolutePath.test(path);
9
- }
10
-
11
- /**
12
- * Return the last portion of a path. Similar to the Unix basename command.
13
- * @example Usage example
14
- * path.basename('/foo/bar/baz/asdf/quux.html')
15
- * // returns
16
- * 'quux.html'
17
- *
18
- * path.basename('/foo/bar/baz/asdf/quux.html', '.html')
19
- * // returns
20
- * 'quux'
21
- */
22
- export function basename(p: string, ext = '') {
23
- // Special case: Normalize will modify this to '.'
24
- if (p === '') {
25
- return p;
26
- }
27
- // Normalize the string first to remove any weirdness.
28
- p = normalizePath(p);
29
- // Get the last part of the string.
30
- const sections = p.split('/');
31
- const lastPart = sections[sections.length - 1];
32
- // Special case: If it's empty, then we have a string like so: foo/
33
- // Meaning, 'foo' is guaranteed to be a directory.
34
- if (lastPart === '' && sections.length > 1) {
35
- return sections[sections.length - 2];
36
- }
37
- // Remove the extension, if need be.
38
- if (ext.length > 0) {
39
- const lastPartExt = lastPart.slice(-ext.length);
40
- if (lastPartExt === ext) {
41
- return lastPart.slice(0, -ext.length);
42
- }
43
- }
44
- return lastPart;
45
- }
46
-
47
- /**
48
- * Return the extension of the path, from the last '.' to end of string in the
49
- * last portion of the path. If there is no '.' in the last portion of the path
50
- * or the first character of it is '.', then it returns an empty string.
51
- * @example Usage example
52
- * path.fileExtensionWithSeparator('index.html')
53
- * // returns
54
- * '.html'
55
- */
56
- export function fileExtensionWithSeparator(p: string) {
57
- p = normalizePath(p);
58
- const sections = p.split('/');
59
- p = sections.pop() as string;
60
- // Special case: foo/file.ext/ should return '.ext'
61
- if (p === '' && sections.length > 0) {
62
- p = sections.pop() as string;
63
- }
64
- if (p === '..') {
65
- return '';
66
- }
67
- const i = p.lastIndexOf('.');
68
- if (i === -1 || i === 0) {
69
- return '';
70
- }
71
- return p.slice(i);
72
- }
73
-
74
- /**
75
- * Return the extension of the path, from after the last '.' to end of string in the
76
- * last portion of the path. If there is no '.' in the last portion of the path
77
- * or the first character of it is '.', then it returns an empty string.
78
- * @example Usage example
79
- * path.fileExtension('index.html')
80
- * // returns
81
- * 'html'
82
- */
83
- export function fileExtension(p: string) {
84
- const ext = fileExtensionWithSeparator(p);
85
- return ext === '' ? ext : ext.slice(1);
86
- }
package/src/promise.ts DELETED
@@ -1,21 +0,0 @@
1
- import flow from 'lodash/flow';
2
-
3
- export function then<T, V>(fn: (r: T) => V) {
4
- return (p: Promise<T>) => Promise.resolve(p).then(fn);
5
- }
6
-
7
- const filterPromiseSymbol = Symbol('filterPromiseSymbol');
8
-
9
- export function onlySuccessfulPromises(promises: Promise<unknown>[]) {
10
- return Promise.all(promises.map(p => p.catch(() => filterPromiseSymbol))).then(results =>
11
- results.filter(result => result !== filterPromiseSymbol),
12
- );
13
- }
14
-
15
- function wrapFlowAsync(fn: Function) {
16
- return async (arg: unknown) => fn(await arg);
17
- }
18
-
19
- export function flowAsync(fns: Function[]) {
20
- return flow(fns.map(fn => wrapFlowAsync(fn)));
21
- }
package/src/stega.ts DELETED
@@ -1,134 +0,0 @@
1
- import { vercelStegaEncode } from '@vercel/stega';
2
-
3
- import { isImmutableMap, isImmutableList } from './types';
4
-
5
- import type { Map as ImmutableMap, List } from 'immutable';
6
- import type { CmsField } from 'decap-cms-core';
7
-
8
- /**
9
- * Context passed to encode functions, containing the current state of the encoding process
10
- */
11
- interface EncodeContext {
12
- fields: CmsField[]; // Available CMS fields at current level
13
- path: string; // Path to current value in object tree
14
- visit: (value: unknown, fields: CmsField[], path: string) => unknown; // Visitor for recursive traversal
15
- }
16
-
17
- /**
18
- * Get the fields that should be used for encoding nested values
19
- */
20
- function getNestedFields(f?: CmsField): CmsField[] {
21
- if (f) {
22
- if ('types' in f) {
23
- return f.types ?? [];
24
- }
25
- if ('fields' in f) {
26
- return f.fields ?? [];
27
- }
28
- if ('field' in f) {
29
- return f.field ? [f.field] : [];
30
- }
31
- return [f];
32
- }
33
- return [];
34
- }
35
-
36
- /**
37
- * Encode a string value by appending steganographic data
38
- * For markdown fields, encode each paragraph separately
39
- */
40
- function encodeString(value: string, { fields, path }: EncodeContext): string {
41
- const stega = vercelStegaEncode({ decap: path });
42
- const isMarkdown = fields[0]?.widget === 'markdown';
43
-
44
- if (isMarkdown && value.includes('\n\n')) {
45
- const blocks = value.split(/(\n\n+)/);
46
- return blocks.map(block => (block.trim() ? block + stega : block)).join('');
47
- }
48
- return value + stega;
49
- }
50
-
51
- /**
52
- * Encode a list of values, handling both simple values and nested objects/lists
53
- * For typed lists, use the type field to determine which fields to use
54
- */
55
- function encodeList(list: List<unknown>, ctx: EncodeContext): List<unknown> {
56
- let newList = list;
57
- for (let i = 0; i < newList.size; i++) {
58
- const item = newList.get(i);
59
- if (isImmutableMap(item)) {
60
- const itemType = item.get('type');
61
- if (typeof itemType === 'string') {
62
- // For typed items, look up fields based on type
63
- const field = ctx.fields.find(f => f.name === itemType);
64
- const newItem = ctx.visit(item, getNestedFields(field), `${ctx.path}.${i}`);
65
- newList = newList.set(i, newItem);
66
- } else {
67
- // For untyped items, use current fields
68
- const newItem = ctx.visit(item, ctx.fields, `${ctx.path}.${i}`);
69
- newList = newList.set(i, newItem);
70
- }
71
- } else {
72
- // For simple values, use first field if available
73
- const field = ctx.fields[0];
74
- const newItem = ctx.visit(item, field ? [field] : [], `${ctx.path}.${i}`);
75
- if (newItem !== item) {
76
- newList = newList.set(i, newItem);
77
- }
78
- }
79
- }
80
- return newList;
81
- }
82
-
83
- /**
84
- * Encode a map of values, looking up the appropriate field for each key
85
- * and recursively encoding nested values
86
- */
87
- function encodeMap(
88
- map: ImmutableMap<string, unknown>,
89
- ctx: EncodeContext,
90
- ): ImmutableMap<string, unknown> {
91
- let newMap = map;
92
- for (const [key, val] of newMap.entrySeq().toArray()) {
93
- const field = ctx.fields.find(f => f.name === key);
94
- if (field) {
95
- const fields = getNestedFields(field);
96
- const newVal = ctx.visit(val, fields, ctx.path ? `${ctx.path}.${key}` : key);
97
- if (newVal !== val) {
98
- newMap = newMap.set(key, newVal);
99
- }
100
- }
101
- }
102
- return newMap;
103
- }
104
-
105
- /**
106
- * Main entry point for encoding steganographic data into entry values
107
- * Uses a visitor pattern with caching to handle recursive structures
108
- */
109
- export function encodeEntry(value: unknown, fields: List<ImmutableMap<string, unknown>>) {
110
- const plainFields = fields.toJS() as CmsField[];
111
- const cache = new Map();
112
-
113
- function visit(value: unknown, fields: CmsField[], path = '') {
114
- const cached = cache.get(path);
115
- if (cached === value) return value;
116
-
117
- const ctx: EncodeContext = { fields, path, visit };
118
- let result;
119
- if (isImmutableList(value)) {
120
- result = encodeList(value, ctx);
121
- } else if (isImmutableMap(value)) {
122
- result = encodeMap(value, ctx);
123
- } else if (typeof value === 'string') {
124
- result = encodeString(value, ctx);
125
- } else {
126
- result = value;
127
- }
128
-
129
- cache.set(path, result);
130
- return result;
131
- }
132
-
133
- return visit(value, plainFields);
134
- }
@@ -1,5 +0,0 @@
1
- declare module 'semaphore' {
2
- export type Semaphore = { take: (f: Function) => void; leave: () => void };
3
- const semaphore: (count: number) => Semaphore;
4
- export default semaphore;
5
- }
package/src/types.ts DELETED
@@ -1,9 +0,0 @@
1
- import { Map as ImmutableMap, List } from 'immutable';
2
-
3
- export function isImmutableMap(value: unknown): value is ImmutableMap<string, unknown> {
4
- return ImmutableMap.isMap(value);
5
- }
6
-
7
- export function isImmutableList(value: unknown): value is List<unknown> {
8
- return List.isList(value);
9
- }
@@ -1,133 +0,0 @@
1
- import { fromJS, List, Map } from 'immutable';
2
- import curry from 'lodash/curry';
3
- import flow from 'lodash/flow';
4
- import isString from 'lodash/isString';
5
-
6
- function isAbortControllerSupported() {
7
- if (typeof window !== 'undefined') {
8
- return !!window.AbortController;
9
- }
10
- return false;
11
- }
12
-
13
- const timeout = 60;
14
-
15
- function fetchWithTimeout(input, init) {
16
- if ((init && init.signal) || !isAbortControllerSupported()) {
17
- return fetch(input, init);
18
- }
19
- const controller = new AbortController();
20
- const timeoutId = setTimeout(() => controller.abort(), timeout * 1000);
21
- return fetch(input, { ...init, signal: controller.signal })
22
- .then(res => {
23
- clearTimeout(timeoutId);
24
- return res;
25
- })
26
- .catch(e => {
27
- if (e.name === 'AbortError' || e.name === 'DOMException') {
28
- throw new Error(`Request timed out after ${timeout} seconds`);
29
- }
30
- throw e;
31
- });
32
- }
33
-
34
- function decodeParams(paramsString) {
35
- return List(paramsString.split('&'))
36
- .map(s => List(s.split('=')).map(decodeURIComponent))
37
- .update(Map);
38
- }
39
-
40
- function fromURL(wholeURL) {
41
- const [url, allParamsString] = wholeURL.split('?');
42
- return Map({ url, ...(allParamsString ? { params: decodeParams(allParamsString) } : {}) });
43
- }
44
-
45
- function fromFetchArguments(wholeURL, options) {
46
- return fromURL(wholeURL).merge(
47
- (options ? fromJS(options) : Map()).remove('url').remove('params'),
48
- );
49
- }
50
-
51
- function encodeParams(params) {
52
- return params
53
- .entrySeq()
54
- .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
55
- .join('&');
56
- }
57
-
58
- function toURL(req) {
59
- return `${req.get('url')}${req.get('params') ? `?${encodeParams(req.get('params'))}` : ''}`;
60
- }
61
-
62
- function toFetchArguments(req) {
63
- return [toURL(req), req.remove('url').remove('params').toJS()];
64
- }
65
-
66
- function maybeRequestArg(req) {
67
- if (isString(req)) {
68
- return fromURL(req);
69
- }
70
- if (req) {
71
- return fromJS(req);
72
- }
73
- return Map();
74
- }
75
-
76
- function ensureRequestArg(func) {
77
- return req => func(maybeRequestArg(req));
78
- }
79
-
80
- function ensureRequestArg2(func) {
81
- return (arg, req) => func(arg, maybeRequestArg(req));
82
- }
83
-
84
- // This actually performs the built request object
85
- const performRequest = ensureRequestArg(req => {
86
- const args = toFetchArguments(req);
87
- return fetchWithTimeout(...args);
88
- });
89
-
90
- // Each of the following functions takes options and returns another
91
- // function that performs the requested action on a request.
92
- const getCurriedRequestProcessor = flow([ensureRequestArg2, curry]);
93
-
94
- function getPropSetFunction(path) {
95
- return getCurriedRequestProcessor((val, req) => req.setIn(path, val));
96
- }
97
-
98
- function getPropMergeFunction(path) {
99
- return getCurriedRequestProcessor((obj, req) => req.updateIn(path, (p = Map()) => p.merge(obj)));
100
- }
101
-
102
- const withMethod = getPropSetFunction(['method']);
103
- const withBody = getPropSetFunction(['body']);
104
- const withNoCache = getPropSetFunction(['cache'])('no-cache');
105
- const withParams = getPropMergeFunction(['params']);
106
- const withHeaders = getPropMergeFunction(['headers']);
107
-
108
- // withRoot sets a root URL, unless the URL is already absolute
109
- const absolutePath = new RegExp('^(?:[a-z]+:)?//', 'i');
110
- const withRoot = getCurriedRequestProcessor((root, req) =>
111
- req.update('url', p => {
112
- if (absolutePath.test(p)) {
113
- return p;
114
- }
115
- return root && p && p[0] !== '/' && root[root.length - 1] !== '/'
116
- ? `${root}/${p}`
117
- : `${root}${p}`;
118
- }),
119
- );
120
-
121
- export default {
122
- toURL,
123
- fromURL,
124
- fromFetchArguments,
125
- performRequest,
126
- withMethod,
127
- withBody,
128
- withHeaders,
129
- withParams,
130
- withRoot,
131
- withNoCache,
132
- fetchWithTimeout,
133
- };
package/webpack.config.js DELETED
@@ -1,3 +0,0 @@
1
- const { getConfig } = require('../../scripts/webpack.js');
2
-
3
- module.exports = getConfig();