@expo/cli 55.0.4 → 55.0.6
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/build/bin/cli +1 -1
- package/build/src/api/graphql/client.js +133 -68
- package/build/src/api/graphql/client.js.map +1 -1
- package/build/src/api/graphql/queries/AppQuery.js +21 -25
- package/build/src/api/graphql/queries/AppQuery.js.map +1 -1
- package/build/src/api/graphql/queries/UserQuery.js +45 -38
- package/build/src/api/graphql/queries/UserQuery.js.map +1 -1
- package/build/src/api/rest/cache/FileSystemResponseCache.js.map +1 -1
- package/build/src/api/rest/cache/ResponseCache.js.map +1 -1
- package/build/src/api/rest/cache/wrapFetchWithCache.js +7 -7
- package/build/src/api/rest/cache/wrapFetchWithCache.js.map +1 -1
- package/build/src/api/rest/client.js +3 -7
- package/build/src/api/rest/client.js.map +1 -1
- package/build/src/api/rest/wrapFetchWithProgress.js +1 -8
- package/build/src/api/rest/wrapFetchWithProgress.js.map +1 -1
- package/build/src/api/user/user.js +6 -36
- package/build/src/api/user/user.js.map +1 -1
- package/build/src/prebuild/renameTemplateAppName.js +2 -6
- package/build/src/prebuild/renameTemplateAppName.js.map +1 -1
- package/build/src/prebuild/resolveLocalTemplate.js +2 -4
- package/build/src/prebuild/resolveLocalTemplate.js.map +1 -1
- package/build/src/prebuild/resolveTemplate.js +13 -17
- package/build/src/prebuild/resolveTemplate.js.map +1 -1
- package/build/src/prebuild/updateFromTemplate.js +4 -6
- package/build/src/prebuild/updateFromTemplate.js.map +1 -1
- package/build/src/start/doctor/ngrok/ExternalModule.js +2 -8
- package/build/src/start/doctor/ngrok/ExternalModule.js.map +1 -1
- package/build/src/start/platforms/android/AndroidSdk.js +15 -6
- package/build/src/start/platforms/android/AndroidSdk.js.map +1 -1
- package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js +1 -9
- package/build/src/start/server/metro/DevToolsPluginWebsocketEndpoint.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +10 -4
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/createServerComponentsMiddleware.js +2 -12
- package/build/src/start/server/metro/createServerComponentsMiddleware.js.map +1 -1
- package/build/src/start/server/metro/createServerRouteMiddleware.js +17 -0
- package/build/src/start/server/metro/createServerRouteMiddleware.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +2 -3
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js +47 -34
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/ManifestMiddleware.js +27 -4
- package/build/src/start/server/middleware/ManifestMiddleware.js.map +1 -1
- package/build/src/start/server/type-generation/routes.js +2 -59
- package/build/src/start/server/type-generation/routes.js.map +1 -1
- package/build/src/start/server/webpack/WebpackBundlerDevServer.js +2 -1
- package/build/src/start/server/webpack/WebpackBundlerDevServer.js.map +1 -1
- package/build/src/utils/codesigning.js +3 -17
- package/build/src/utils/codesigning.js.map +1 -1
- package/build/src/utils/createFileTransform.js +3 -38
- package/build/src/utils/createFileTransform.js.map +1 -1
- package/build/src/utils/downloadAppAsync.js +1 -12
- package/build/src/utils/downloadAppAsync.js.map +1 -1
- package/build/src/utils/fetch.js +23 -4
- package/build/src/utils/fetch.js.map +1 -1
- package/build/src/utils/getOrPromptApplicationId.js +2 -15
- package/build/src/utils/getOrPromptApplicationId.js.map +1 -1
- package/build/src/utils/npm.js +60 -65
- package/build/src/utils/npm.js.map +1 -1
- package/build/src/utils/resolveGlobal.js +195 -0
- package/build/src/utils/resolveGlobal.js.map +1 -0
- package/build/src/utils/tar.js +138 -69
- package/build/src/utils/tar.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +12 -24
- package/build/src/utils/telemetry/clients/FetchClient.js.map +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +16 -26
- package/build/src/api/graphql/types/App.js +0 -29
- package/build/src/api/graphql/types/App.js.map +0 -1
- package/build/src/api/rest/wrapFetchWithProxy.js +0 -31
- package/build/src/api/rest/wrapFetchWithProxy.js.map +0 -1
- package/build/src/graphql/generated.js +0 -1196
- package/build/src/graphql/generated.js.map +0 -1
- package/build/src/start/server/middleware/createBuiltinAPIRequestHandler.js +0 -85
- package/build/src/start/server/middleware/createBuiltinAPIRequestHandler.js.map +0 -1
- package/build/src/utils/multipartMixed.js +0 -56
- package/build/src/utils/multipartMixed.js.map +0 -1
package/build/bin/cli
CHANGED
|
@@ -9,35 +9,24 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
|
|
13
|
-
return
|
|
12
|
+
UnexpectedServerData: function() {
|
|
13
|
+
return _client.UnexpectedServerData;
|
|
14
14
|
},
|
|
15
|
-
|
|
16
|
-
return
|
|
15
|
+
UnexpectedServerError: function() {
|
|
16
|
+
return _client.UnexpectedServerError;
|
|
17
17
|
},
|
|
18
|
-
|
|
19
|
-
return
|
|
18
|
+
graphql: function() {
|
|
19
|
+
return graphql;
|
|
20
|
+
},
|
|
21
|
+
query: function() {
|
|
22
|
+
return query;
|
|
20
23
|
}
|
|
21
24
|
});
|
|
22
|
-
function _core() {
|
|
23
|
-
const data = require("@urql/core");
|
|
24
|
-
_core = function() {
|
|
25
|
-
return data;
|
|
26
|
-
};
|
|
27
|
-
return data;
|
|
28
|
-
}
|
|
29
|
-
function _exchangeretry() {
|
|
30
|
-
const data = require("@urql/exchange-retry");
|
|
31
|
-
_exchangeretry = function() {
|
|
32
|
-
return data;
|
|
33
|
-
};
|
|
34
|
-
return data;
|
|
35
|
-
}
|
|
36
25
|
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../log"));
|
|
37
26
|
const _fetch = require("../../utils/fetch");
|
|
38
27
|
const _endpoint = require("../endpoint");
|
|
28
|
+
const _client = require("../rest/client");
|
|
39
29
|
const _wrapFetchWithOffline = require("../rest/wrapFetchWithOffline");
|
|
40
|
-
const _wrapFetchWithProxy = require("../rest/wrapFetchWithProxy");
|
|
41
30
|
const _wrapFetchWithUserAgent = require("../rest/wrapFetchWithUserAgent");
|
|
42
31
|
const _UserSettings = require("../user/UserSettings");
|
|
43
32
|
function _getRequireWildcardCache(nodeInterop) {
|
|
@@ -81,59 +70,135 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
81
70
|
}
|
|
82
71
|
return newObj;
|
|
83
72
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
73
|
+
function graphql(query) {
|
|
74
|
+
return query.trim();
|
|
75
|
+
}
|
|
76
|
+
const query = (()=>{
|
|
77
|
+
const url = (0, _endpoint.getExpoApiBaseUrl)() + '/graphql';
|
|
78
|
+
let _fetch1;
|
|
79
|
+
const wrappedFetch = (...args)=>{
|
|
80
|
+
if (!_fetch1) {
|
|
81
|
+
_fetch1 = (0, _wrapFetchWithOffline.wrapFetchWithOffline)((0, _wrapFetchWithUserAgent.wrapFetchWithUserAgent)(_fetch.fetch));
|
|
82
|
+
}
|
|
83
|
+
return _fetch1(...args);
|
|
84
|
+
};
|
|
85
|
+
const randomDelay = (attemptCount)=>new Promise((resolve)=>{
|
|
86
|
+
setTimeout(resolve, Math.min(500 + Math.random() * 1000 * attemptCount, 4000));
|
|
87
|
+
});
|
|
88
|
+
const getFetchHeaders = ()=>{
|
|
100
89
|
var _getSession;
|
|
101
90
|
const token = (0, _UserSettings.getAccessToken)();
|
|
91
|
+
const headers = {
|
|
92
|
+
'content-type': 'application/json',
|
|
93
|
+
accept: 'application/graphql-response+json, application/graphql+json, application/json'
|
|
94
|
+
};
|
|
95
|
+
let sessionSecret;
|
|
102
96
|
if (token) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
headers.authorization = `Bearer ${token}`;
|
|
98
|
+
} else if (sessionSecret = (_getSession = (0, _UserSettings.getSession)()) == null ? void 0 : _getSession.sessionSecret) {
|
|
99
|
+
headers['expo-session'] = sessionSecret;
|
|
100
|
+
}
|
|
101
|
+
return headers;
|
|
102
|
+
};
|
|
103
|
+
// NOTE(@kitten): This only sorted keys one level deep since this is sufficient for most cases
|
|
104
|
+
const stringifySorted = (variables)=>JSON.stringify(Object.keys(variables).sort().reduce((acc, key)=>{
|
|
105
|
+
acc[key] = variables[key];
|
|
106
|
+
return acc;
|
|
107
|
+
}, {}));
|
|
108
|
+
let cache = {};
|
|
109
|
+
let cacheKey;
|
|
110
|
+
function resetCache() {
|
|
111
|
+
cache = {};
|
|
112
|
+
}
|
|
113
|
+
return async function query(query, variables, options) {
|
|
114
|
+
let isTransient = false;
|
|
115
|
+
let response;
|
|
116
|
+
let data;
|
|
117
|
+
let error;
|
|
118
|
+
// Pre-instantiate headers and reset the cache if they've changed
|
|
119
|
+
const headers = {
|
|
120
|
+
...getFetchHeaders(),
|
|
121
|
+
...options == null ? void 0 : options.headers
|
|
122
|
+
};
|
|
123
|
+
const headersKey = stringifySorted(headers);
|
|
124
|
+
if (!cacheKey || cacheKey !== headersKey) {
|
|
125
|
+
resetCache();
|
|
108
126
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
// Retrieve a cached result, if we have any via a `query => variables => Result` cache key
|
|
128
|
+
const variablesKey = stringifySorted(variables);
|
|
129
|
+
const queryCache = cache[query] || (cache[query] = new Map());
|
|
130
|
+
if (queryCache.has(variablesKey)) {
|
|
131
|
+
data = queryCache.get(variablesKey);
|
|
132
|
+
}
|
|
133
|
+
// Retry the query if it fails due to an unknown or transient error
|
|
134
|
+
for(let attemptCount = 0; attemptCount < 3 && !data; attemptCount++){
|
|
135
|
+
// Add a random delay on each subsequent attempt
|
|
136
|
+
if (attemptCount > 0) {
|
|
137
|
+
await randomDelay(attemptCount);
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
response = await wrappedFetch(url, {
|
|
141
|
+
...options,
|
|
142
|
+
method: 'POST',
|
|
143
|
+
body: JSON.stringify({
|
|
144
|
+
query,
|
|
145
|
+
variables
|
|
146
|
+
}),
|
|
147
|
+
headers
|
|
148
|
+
});
|
|
149
|
+
} catch (networkError) {
|
|
150
|
+
error = networkError || error;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const json = await response.json();
|
|
154
|
+
if (typeof json === 'object' && json) {
|
|
155
|
+
// If we have a transient error, we retry immediately and discard the data
|
|
156
|
+
// Otherwise, we store the first available error and get the data
|
|
157
|
+
if ('errors' in json && Array.isArray(json.errors)) {
|
|
158
|
+
isTransient = json.errors.some((e)=>{
|
|
159
|
+
var _e_extensions;
|
|
160
|
+
return e == null ? void 0 : (_e_extensions = e.extensions) == null ? void 0 : _e_extensions.isTransient;
|
|
161
|
+
});
|
|
162
|
+
if (isTransient) {
|
|
163
|
+
data = undefined;
|
|
164
|
+
continue;
|
|
165
|
+
} else {
|
|
166
|
+
error = json.errors[0] || error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
data = (0, _client.getResponseDataOrThrow)(json);
|
|
171
|
+
} catch (dataError) {
|
|
172
|
+
// We only use the data error, if we don't have an error already
|
|
173
|
+
if (!error) {
|
|
174
|
+
error = dataError || error;
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
114
177
|
}
|
|
115
|
-
}
|
|
178
|
+
}
|
|
116
179
|
}
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
var _e_extensions;
|
|
125
|
-
return e == null ? void 0 : (_e_extensions = e.extensions) == null ? void 0 : _e_extensions.isTransient;
|
|
126
|
-
})) {
|
|
127
|
-
_log.error(`We've encountered a transient error, please try again shortly.`);
|
|
180
|
+
// Store the data in the cache, and only return a result if we have any values
|
|
181
|
+
if (data) {
|
|
182
|
+
queryCache.set(variablesKey, data);
|
|
183
|
+
const keys = Object.keys(data);
|
|
184
|
+
if (keys.length > 0 && keys.some((key)=>data[key] != null)) {
|
|
185
|
+
return data;
|
|
186
|
+
}
|
|
128
187
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
188
|
+
// If we have an error, rethrow it wrapped in our custom errors
|
|
189
|
+
if (error) {
|
|
190
|
+
if (isTransient) {
|
|
191
|
+
_log.error(`We've encountered a transient error, please try again shortly.`);
|
|
192
|
+
}
|
|
193
|
+
const wrappedError = new _client.UnexpectedServerError('' + error.message);
|
|
194
|
+
wrappedError.cause = error;
|
|
195
|
+
throw wrappedError;
|
|
196
|
+
} else if (response && !response.ok) {
|
|
197
|
+
throw new _client.UnexpectedServerError(`Unexpected server error: ${response.statusText}`);
|
|
198
|
+
} else {
|
|
199
|
+
throw new _client.UnexpectedServerData('Unexpected server error: No returned query result');
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
})();
|
|
138
203
|
|
|
139
204
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/api/graphql/client.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../../src/api/graphql/client.ts"],"sourcesContent":["import * as Log from '../../log';\nimport { fetch, type Response } from '../../utils/fetch';\nimport { getExpoApiBaseUrl } from '../endpoint';\nimport {\n getResponseDataOrThrow,\n UnexpectedServerData,\n UnexpectedServerError,\n} from '../rest/client';\nimport { FetchLike } from '../rest/client.types';\nimport { wrapFetchWithOffline } from '../rest/wrapFetchWithOffline';\nimport { wrapFetchWithUserAgent } from '../rest/wrapFetchWithUserAgent';\nimport { getAccessToken, getSession } from '../user/UserSettings';\n\ntype JSONObject = Record<string, unknown>;\ntype EmptyVariables = Record<string, never>;\n\nexport type StaticDocumentNode<Result extends JSONObject, Variables extends JSONObject> = string & {\n readonly __graphql: (vars: Variables) => Result;\n};\n\nexport function graphql<Result extends JSONObject, Variables extends JSONObject = EmptyVariables>(\n query: string\n): StaticDocumentNode<Result, Variables> {\n return query.trim() as StaticDocumentNode<Result, Variables>;\n}\n\nexport { UnexpectedServerError, UnexpectedServerData };\n\nexport interface QueryOptions {\n headers?: Record<string, string>;\n}\n\nexport const query = (() => {\n const url = getExpoApiBaseUrl() + '/graphql';\n\n let _fetch: FetchLike | undefined;\n const wrappedFetch: FetchLike = (...args) => {\n if (!_fetch) {\n _fetch = wrapFetchWithOffline(wrapFetchWithUserAgent(fetch));\n }\n return _fetch(...args);\n };\n\n const randomDelay = (attemptCount: number) =>\n new Promise((resolve) => {\n setTimeout(resolve, Math.min(500 + Math.random() * 1000 * attemptCount, 4_000));\n });\n\n const getFetchHeaders = (): Record<string, string> => {\n const token = getAccessToken();\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/graphql-response+json, application/graphql+json, application/json',\n };\n let sessionSecret: string | undefined;\n if (token) {\n headers.authorization = `Bearer ${token}`;\n } else if ((sessionSecret = getSession()?.sessionSecret)) {\n headers['expo-session'] = sessionSecret;\n }\n return headers;\n };\n\n // NOTE(@kitten): This only sorted keys one level deep since this is sufficient for most cases\n const stringifySorted = (variables: JSONObject): string =>\n JSON.stringify(\n Object.keys(variables)\n .sort()\n .reduce((acc, key) => {\n acc[key] = variables[key];\n return acc;\n }, {} as JSONObject)\n );\n\n let cache: Record<string, Map<string, unknown>> = {};\n let cacheKey: string | undefined;\n\n function resetCache() {\n cache = {};\n }\n\n return async function query<Result extends JSONObject, Variables extends JSONObject>(\n query: StaticDocumentNode<Result, Variables>,\n variables: Variables,\n options?: QueryOptions\n ): Promise<Result> {\n let isTransient = false;\n let response: Response | undefined;\n let data: Result | null | undefined;\n let error: unknown;\n\n // Pre-instantiate headers and reset the cache if they've changed\n const headers = { ...getFetchHeaders(), ...options?.headers };\n const headersKey = stringifySorted(headers);\n if (!cacheKey || cacheKey !== headersKey) {\n resetCache();\n }\n\n // Retrieve a cached result, if we have any via a `query => variables => Result` cache key\n const variablesKey = stringifySorted(variables);\n const queryCache = cache[query] || (cache[query] = new Map());\n if (queryCache.has(variablesKey)) {\n data = queryCache.get(variablesKey) as Result;\n }\n\n // Retry the query if it fails due to an unknown or transient error\n for (let attemptCount = 0; attemptCount < 3 && !data; attemptCount++) {\n // Add a random delay on each subsequent attempt\n if (attemptCount > 0) {\n await randomDelay(attemptCount);\n }\n\n try {\n response = await wrappedFetch(url, {\n ...options,\n method: 'POST',\n body: JSON.stringify({ query, variables }),\n headers,\n });\n } catch (networkError) {\n error = networkError || error;\n continue;\n }\n\n const json = await response.json();\n if (typeof json === 'object' && json) {\n // If we have a transient error, we retry immediately and discard the data\n // Otherwise, we store the first available error and get the data\n if ('errors' in json && Array.isArray(json.errors)) {\n isTransient = json.errors.some((e: any) => e?.extensions?.isTransient);\n if (isTransient) {\n data = undefined;\n continue;\n } else {\n error = json.errors[0] || error;\n }\n }\n\n try {\n data = getResponseDataOrThrow<Result | null>(json);\n } catch (dataError) {\n // We only use the data error, if we don't have an error already\n if (!error) {\n error = dataError || error;\n }\n continue;\n }\n }\n }\n\n // Store the data in the cache, and only return a result if we have any values\n if (data) {\n queryCache.set(variablesKey, data);\n const keys = Object.keys(data);\n if (keys.length > 0 && keys.some((key) => data[key as keyof typeof data] != null)) {\n return data;\n }\n }\n\n // If we have an error, rethrow it wrapped in our custom errors\n if (error) {\n if (isTransient) {\n Log.error(`We've encountered a transient error, please try again shortly.`);\n }\n const wrappedError = new UnexpectedServerError('' + (error as any).message);\n wrappedError.cause = error;\n throw wrappedError;\n } else if (response && !response.ok) {\n throw new UnexpectedServerError(`Unexpected server error: ${response.statusText}`);\n } else {\n throw new UnexpectedServerData('Unexpected server error: No returned query result');\n }\n };\n})();\n"],"names":["UnexpectedServerData","UnexpectedServerError","graphql","query","trim","url","getExpoApiBaseUrl","_fetch","wrappedFetch","args","wrapFetchWithOffline","wrapFetchWithUserAgent","fetch","randomDelay","attemptCount","Promise","resolve","setTimeout","Math","min","random","getFetchHeaders","getSession","token","getAccessToken","headers","accept","sessionSecret","authorization","stringifySorted","variables","JSON","stringify","Object","keys","sort","reduce","acc","key","cache","cacheKey","resetCache","options","isTransient","response","data","error","headersKey","variablesKey","queryCache","Map","has","get","method","body","networkError","json","Array","isArray","errors","some","e","extensions","undefined","getResponseDataOrThrow","dataError","set","length","Log","wrappedError","message","cause","ok","statusText"],"mappings":"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"}
|
|
@@ -8,35 +8,31 @@ Object.defineProperty(exports, "AppQuery", {
|
|
|
8
8
|
return AppQuery;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
function _core() {
|
|
12
|
-
const data = require("@urql/core");
|
|
13
|
-
_core = function() {
|
|
14
|
-
return data;
|
|
15
|
-
};
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
11
|
const _client = require("../client");
|
|
19
|
-
const
|
|
12
|
+
const AppQueryDocument = (0, _client.graphql)(`
|
|
13
|
+
query AppByIdQuery($appId: String!) {
|
|
14
|
+
app {
|
|
15
|
+
byId(appId: $appId) {
|
|
16
|
+
id
|
|
17
|
+
...AppFragment
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fragment AppFragment on App {
|
|
23
|
+
id
|
|
24
|
+
scopeKey
|
|
25
|
+
ownerAccount {
|
|
26
|
+
id
|
|
27
|
+
name
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`);
|
|
20
31
|
const AppQuery = {
|
|
21
32
|
async byIdAsync (projectId) {
|
|
22
|
-
const data = await (0, _client.
|
|
23
|
-
query AppByIdQuery($appId: String!) {
|
|
24
|
-
app {
|
|
25
|
-
byId(appId: $appId) {
|
|
26
|
-
id
|
|
27
|
-
...AppFragment
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
${_App.AppFragmentNode}
|
|
33
|
-
`, {
|
|
33
|
+
const data = await (0, _client.query)(AppQueryDocument, {
|
|
34
34
|
appId: projectId
|
|
35
|
-
}
|
|
36
|
-
additionalTypenames: [
|
|
37
|
-
'App'
|
|
38
|
-
]
|
|
39
|
-
}).toPromise());
|
|
35
|
+
});
|
|
40
36
|
return data.app.byId;
|
|
41
37
|
}
|
|
42
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/api/graphql/queries/AppQuery.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/api/graphql/queries/AppQuery.ts"],"sourcesContent":["import { graphql, query } from '../client';\n\nexport type App = {\n id: string;\n scopeKey: string;\n ownerAccount: {\n id: string;\n name: string;\n };\n};\n\ntype AppQueryData = {\n app: {\n byId: App;\n };\n};\n\ntype AppQueryVariables = {\n appId: string;\n};\n\nconst AppQueryDocument = graphql<AppQueryData, AppQueryVariables>(`\n query AppByIdQuery($appId: String!) {\n app {\n byId(appId: $appId) {\n id\n ...AppFragment\n }\n }\n }\n\n fragment AppFragment on App {\n id\n scopeKey\n ownerAccount {\n id\n name\n }\n }\n`);\n\nexport const AppQuery = {\n async byIdAsync(projectId: string): Promise<AppQueryData['app']['byId']> {\n const data = await query(AppQueryDocument, { appId: projectId });\n return data.app.byId;\n },\n};\n"],"names":["AppQuery","AppQueryDocument","graphql","byIdAsync","projectId","data","query","appId","app","byId"],"mappings":";;;;+BAyCaA;;;eAAAA;;;wBAzCkB;AAqB/B,MAAMC,mBAAmBC,IAAAA,eAAO,EAAkC,CAAC;;;;;;;;;;;;;;;;;;AAkBnE,CAAC;AAEM,MAAMF,WAAW;IACtB,MAAMG,WAAUC,SAAiB;QAC/B,MAAMC,OAAO,MAAMC,IAAAA,aAAK,EAACL,kBAAkB;YAAEM,OAAOH;QAAU;QAC9D,OAAOC,KAAKG,GAAG,CAACC,IAAI;IACtB;AACF"}
|
|
@@ -8,48 +8,55 @@ Object.defineProperty(exports, "UserQuery", {
|
|
|
8
8
|
return UserQuery;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
function _core() {
|
|
12
|
-
const data = require("@urql/core");
|
|
13
|
-
_core = function() {
|
|
14
|
-
return data;
|
|
15
|
-
};
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
11
|
const _client = require("../client");
|
|
12
|
+
const CurrentUserDocument = (0, _client.graphql)(`
|
|
13
|
+
query CurrentUser {
|
|
14
|
+
meActor {
|
|
15
|
+
__typename
|
|
16
|
+
id
|
|
17
|
+
... on UserActor {
|
|
18
|
+
primaryAccount {
|
|
19
|
+
id
|
|
20
|
+
}
|
|
21
|
+
username
|
|
22
|
+
}
|
|
23
|
+
... on Robot {
|
|
24
|
+
firstName
|
|
25
|
+
}
|
|
26
|
+
accounts {
|
|
27
|
+
id
|
|
28
|
+
users {
|
|
29
|
+
actor {
|
|
30
|
+
__typename
|
|
31
|
+
id
|
|
32
|
+
}
|
|
33
|
+
permissions
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`);
|
|
39
|
+
const UserQueryDocument = (0, _client.graphql)(`
|
|
40
|
+
query UserQuery {
|
|
41
|
+
meUserActor {
|
|
42
|
+
id
|
|
43
|
+
username
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`);
|
|
19
47
|
const UserQuery = {
|
|
20
48
|
async currentUserAsync () {
|
|
21
|
-
const data = await (0, _client.
|
|
22
|
-
query CurrentUser {
|
|
23
|
-
meActor {
|
|
24
|
-
__typename
|
|
25
|
-
id
|
|
26
|
-
... on UserActor {
|
|
27
|
-
primaryAccount {
|
|
28
|
-
id
|
|
29
|
-
}
|
|
30
|
-
username
|
|
31
|
-
}
|
|
32
|
-
... on Robot {
|
|
33
|
-
firstName
|
|
34
|
-
}
|
|
35
|
-
accounts {
|
|
36
|
-
id
|
|
37
|
-
users {
|
|
38
|
-
actor {
|
|
39
|
-
id
|
|
40
|
-
}
|
|
41
|
-
permissions
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
`, /* variables */ undefined, {
|
|
47
|
-
additionalTypenames: [
|
|
48
|
-
'User',
|
|
49
|
-
'SSOUser'
|
|
50
|
-
]
|
|
51
|
-
}).toPromise());
|
|
49
|
+
const data = await (0, _client.query)(CurrentUserDocument, {});
|
|
52
50
|
return data.meActor;
|
|
51
|
+
},
|
|
52
|
+
async meUserActorAsync (headers) {
|
|
53
|
+
const data = await (0, _client.query)(UserQueryDocument, {}, {
|
|
54
|
+
headers
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
id: data.meUserActor.id,
|
|
58
|
+
username: data.meUserActor.username
|
|
59
|
+
};
|
|
53
60
|
}
|
|
54
61
|
};
|
|
55
62
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/api/graphql/queries/UserQuery.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/api/graphql/queries/UserQuery.ts"],"sourcesContent":["import { graphql, query } from '../client';\n\nexport type Permission = 'ADMIN' | 'OWN' | 'PUBLISH' | 'VIEW';\n\ntype CurrentUserDataUser = {\n permissions: Permission[];\n actor: {\n __typename: 'Robot' | 'SSOUser' | 'User';\n id: string;\n };\n};\n\ntype CurrentUserDataAccount = {\n __typename?: 'Account';\n id: string;\n users: CurrentUserDataUser[];\n};\n\nexport type Actor =\n | {\n __typename: 'Robot';\n firstName?: string | null;\n id: string;\n accounts: CurrentUserDataAccount[];\n }\n | {\n __typename: 'SSOUser' | 'User';\n id: string;\n username: string;\n primaryAccount: {\n id: string;\n };\n accounts: CurrentUserDataAccount[];\n };\n\ntype CurrentUserData = {\n meActor: Actor | null;\n};\n\nconst CurrentUserDocument = graphql<CurrentUserData>(`\n query CurrentUser {\n meActor {\n __typename\n id\n ... on UserActor {\n primaryAccount {\n id\n }\n username\n }\n ... on Robot {\n firstName\n }\n accounts {\n id\n users {\n actor {\n __typename\n id\n }\n permissions\n }\n }\n }\n }\n`);\n\ntype UserQueryData = {\n meUserActor: {\n id: string;\n username: string;\n };\n};\n\nconst UserQueryDocument = graphql<UserQueryData>(`\n query UserQuery {\n meUserActor {\n id\n username\n }\n }\n`);\n\nexport const UserQuery = {\n async currentUserAsync() {\n const data = await query(CurrentUserDocument, {});\n return data.meActor;\n },\n async meUserActorAsync(headers: Record<string, string>) {\n const data = await query(UserQueryDocument, {}, { headers });\n return {\n id: data.meUserActor.id,\n username: data.meUserActor.username,\n };\n },\n};\n"],"names":["UserQuery","CurrentUserDocument","graphql","UserQueryDocument","currentUserAsync","data","query","meActor","meUserActorAsync","headers","id","meUserActor","username"],"mappings":";;;;+BAmFaA;;;eAAAA;;;wBAnFkB;AAuC/B,MAAMC,sBAAsBC,IAAAA,eAAO,EAAkB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BtD,CAAC;AASD,MAAMC,oBAAoBD,IAAAA,eAAO,EAAgB,CAAC;;;;;;;AAOlD,CAAC;AAEM,MAAMF,YAAY;IACvB,MAAMI;QACJ,MAAMC,OAAO,MAAMC,IAAAA,aAAK,EAACL,qBAAqB,CAAC;QAC/C,OAAOI,KAAKE,OAAO;IACrB;IACA,MAAMC,kBAAiBC,OAA+B;QACpD,MAAMJ,OAAO,MAAMC,IAAAA,aAAK,EAACH,mBAAmB,CAAC,GAAG;YAAEM;QAAQ;QAC1D,OAAO;YACLC,IAAIL,KAAKM,WAAW,CAACD,EAAE;YACvBE,UAAUP,KAAKM,WAAW,CAACC,QAAQ;QACrC;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/api/rest/cache/FileSystemResponseCache.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport stream, { Readable } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\n\nimport type { ResponseCache, ResponseCacheEntry } from './ResponseCache';\nimport { fileExistsAsync } from '../../../utils/dir';\n\ntype FileSystemResponseCacheInfo = ResponseCacheEntry['info'] & {\n /** The path to the cached body file */\n bodyPath?: string;\n /** If there is no response body */\n empty?: boolean;\n /** The expiration time, in milliseconds, when the response should be invalidated */\n expiration?: number;\n};\n\nexport class FileSystemResponseCache implements ResponseCache {\n /** The absolute path to the directory used to store responses */\n private cacheDirectory: string;\n /** Optional auto-expiration for all stored responses */\n private timeToLive?: number;\n\n constructor(options: { cacheDirectory: string; ttl?: number }) {\n this.cacheDirectory = options.cacheDirectory;\n this.timeToLive = options.ttl;\n }\n\n private getFilePaths(cacheKey: string) {\n // Create a hash of the cache key to use as filename\n const hash = crypto.createHash('sha256').update(cacheKey).digest('hex');\n return {\n info: path.join(this.cacheDirectory, `${hash}-info.json`),\n body: path.join(this.cacheDirectory, `${hash}-body.bin`),\n };\n }\n\n /** Retrieve the cache response, if any */\n async get(cacheKey: string): Promise<ResponseCacheEntry | undefined> {\n const paths = this.getFilePaths(cacheKey);\n\n if (!(await fileExistsAsync(paths.info))) {\n return undefined;\n }\n\n // Read and parse the info file\n const infoBuffer = await fs.promises.readFile(paths.info);\n\n try {\n const responseInfo: FileSystemResponseCacheInfo = JSON.parse(infoBuffer.toString());\n\n // Check if the response has expired\n if (responseInfo.expiration && responseInfo.expiration < Date.now()) {\n await this.remove(cacheKey);\n return undefined;\n }\n\n // Remove cache-specific data from the response info\n const { empty, expiration, bodyPath, ...cleanInfo } = responseInfo;\n\n // Create response body stream\n let responseBody: ReadableStream;\n if (empty) {\n responseBody = Readable.toWeb(Readable.from(Buffer.alloc(0)));\n } else {\n const bodyBuffer = await fs.promises.readFile(paths.body);\n responseBody = Readable.toWeb(Readable.from(bodyBuffer));\n }\n\n return {\n body: responseBody,\n info: cleanInfo,\n };\n } catch {\n // If file doesn't exist or other errors, return undefined\n return undefined;\n }\n }\n\n /** Store the response for caching */\n async set(\n cacheKey: string,\n response: ResponseCacheEntry\n ): Promise<ResponseCacheEntry | undefined> {\n await fs.promises.mkdir(this.cacheDirectory, { recursive: true });\n const paths = this.getFilePaths(cacheKey);\n\n // Create a copy of the response info, to add cache-specific data\n const responseInfo: FileSystemResponseCacheInfo = { ...response.info };\n\n // Add expiration time if the \"time to live\" is set\n if (typeof this.timeToLive === 'number') {\n responseInfo.expiration = Date.now() + this.timeToLive;\n }\n\n try {\n // Clone the response body stream since we need to read it twice\n const [forSize, forWrite] = response.body.tee();\n\n // Check if the body is empty by reading the first stream\n const reader = forSize.getReader();\n const { value } = await reader.read();\n reader.releaseLock();\n\n if (!value || value.length === 0) {\n responseInfo.empty = true;\n } else {\n // Create write stream and pipe response body to file\n const writeStream = fs.createWriteStream(paths.body);\n const nodeStream = Readable.fromWeb(forWrite);\n nodeStream.pipe(writeStream);\n\n // Wait for the stream to finish\n await stream.promises.finished(writeStream);\n\n responseInfo.bodyPath = paths.body;\n }\n\n // Write info to file\n await fs.promises.writeFile(paths.info, JSON.stringify(responseInfo));\n\n return await this.get(cacheKey);\n } catch (error) {\n // Clean up any partially written files\n await this.remove(cacheKey);\n throw error;\n }\n }\n\n /** Remove the response from caching */\n async remove(cacheKey: string): Promise<void> {\n const paths = this.getFilePaths(cacheKey);\n await removeAllAsync(paths.info, paths.body);\n }\n}\n\nfunction removeAllAsync(...paths: string[]) {\n return Promise.all(\n paths.map((path) => fs.promises.rm(path, { recursive: true, force: true }).catch(() => {}))\n );\n}\n"],"names":["FileSystemResponseCache","constructor","options","cacheDirectory","timeToLive","ttl","getFilePaths","cacheKey","hash","crypto","createHash","update","digest","info","path","join","body","get","paths","fileExistsAsync","undefined","infoBuffer","fs","promises","readFile","responseInfo","JSON","parse","toString","expiration","Date","now","remove","empty","bodyPath","cleanInfo","responseBody","Readable","toWeb","from","Buffer","alloc","bodyBuffer","set","response","mkdir","recursive","forSize","forWrite","tee","reader","getReader","value","read","releaseLock","length","writeStream","createWriteStream","nodeStream","fromWeb","pipe","stream","finished","writeFile","stringify","error","removeAllAsync","Promise","all","map","rm","force","catch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/api/rest/cache/FileSystemResponseCache.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport stream, { Readable } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\n\nimport type { ResponseCache, ResponseCacheEntry } from './ResponseCache';\nimport { fileExistsAsync } from '../../../utils/dir';\n\ntype FileSystemResponseCacheInfo = ResponseCacheEntry['info'] & {\n /** The path to the cached body file */\n bodyPath?: string;\n /** If there is no response body */\n empty?: boolean;\n /** The expiration time, in milliseconds, when the response should be invalidated */\n expiration?: number;\n};\n\nexport class FileSystemResponseCache implements ResponseCache {\n /** The absolute path to the directory used to store responses */\n private cacheDirectory: string;\n /** Optional auto-expiration for all stored responses */\n private timeToLive?: number;\n\n constructor(options: { cacheDirectory: string; ttl?: number }) {\n this.cacheDirectory = options.cacheDirectory;\n this.timeToLive = options.ttl;\n }\n\n private getFilePaths(cacheKey: string) {\n // Create a hash of the cache key to use as filename\n const hash = crypto.createHash('sha256').update(cacheKey).digest('hex');\n return {\n info: path.join(this.cacheDirectory, `${hash}-info.json`),\n body: path.join(this.cacheDirectory, `${hash}-body.bin`),\n };\n }\n\n /** Retrieve the cache response, if any */\n async get(cacheKey: string): Promise<ResponseCacheEntry | undefined> {\n const paths = this.getFilePaths(cacheKey);\n\n if (!(await fileExistsAsync(paths.info))) {\n return undefined;\n }\n\n // Read and parse the info file\n const infoBuffer = await fs.promises.readFile(paths.info);\n\n try {\n const responseInfo: FileSystemResponseCacheInfo = JSON.parse(infoBuffer.toString());\n\n // Check if the response has expired\n if (responseInfo.expiration && responseInfo.expiration < Date.now()) {\n await this.remove(cacheKey);\n return undefined;\n }\n\n // Remove cache-specific data from the response info\n const { empty, expiration, bodyPath, ...cleanInfo } = responseInfo;\n\n // Create response body stream\n let responseBody: ReadableStream;\n if (empty) {\n responseBody = Readable.toWeb(Readable.from(Buffer.alloc(0)));\n } else {\n const bodyBuffer = await fs.promises.readFile(paths.body);\n responseBody = Readable.toWeb(Readable.from(bodyBuffer));\n }\n\n return {\n body: responseBody as globalThis.ReadableStream,\n info: cleanInfo,\n };\n } catch {\n // If file doesn't exist or other errors, return undefined\n return undefined;\n }\n }\n\n /** Store the response for caching */\n async set(\n cacheKey: string,\n response: ResponseCacheEntry\n ): Promise<ResponseCacheEntry | undefined> {\n await fs.promises.mkdir(this.cacheDirectory, { recursive: true });\n const paths = this.getFilePaths(cacheKey);\n\n // Create a copy of the response info, to add cache-specific data\n const responseInfo: FileSystemResponseCacheInfo = { ...response.info };\n\n // Add expiration time if the \"time to live\" is set\n if (typeof this.timeToLive === 'number') {\n responseInfo.expiration = Date.now() + this.timeToLive;\n }\n\n try {\n // Clone the response body stream since we need to read it twice\n const [forSize, forWrite] = response.body.tee();\n\n // Check if the body is empty by reading the first stream\n const reader = forSize.getReader();\n const { value } = await reader.read();\n reader.releaseLock();\n\n if (!value || value.length === 0) {\n responseInfo.empty = true;\n } else {\n // Create write stream and pipe response body to file\n const writeStream = fs.createWriteStream(paths.body);\n const nodeStream = Readable.fromWeb(forWrite as ReadableStream);\n nodeStream.pipe(writeStream);\n\n // Wait for the stream to finish\n await stream.promises.finished(writeStream);\n\n responseInfo.bodyPath = paths.body;\n }\n\n // Write info to file\n await fs.promises.writeFile(paths.info, JSON.stringify(responseInfo));\n\n return await this.get(cacheKey);\n } catch (error) {\n // Clean up any partially written files\n await this.remove(cacheKey);\n throw error;\n }\n }\n\n /** Remove the response from caching */\n async remove(cacheKey: string): Promise<void> {\n const paths = this.getFilePaths(cacheKey);\n await removeAllAsync(paths.info, paths.body);\n }\n}\n\nfunction removeAllAsync(...paths: string[]) {\n return Promise.all(\n paths.map((path) => fs.promises.rm(path, { recursive: true, force: true }).catch(() => {}))\n );\n}\n"],"names":["FileSystemResponseCache","constructor","options","cacheDirectory","timeToLive","ttl","getFilePaths","cacheKey","hash","crypto","createHash","update","digest","info","path","join","body","get","paths","fileExistsAsync","undefined","infoBuffer","fs","promises","readFile","responseInfo","JSON","parse","toString","expiration","Date","now","remove","empty","bodyPath","cleanInfo","responseBody","Readable","toWeb","from","Buffer","alloc","bodyBuffer","set","response","mkdir","recursive","forSize","forWrite","tee","reader","getReader","value","read","releaseLock","length","writeStream","createWriteStream","nodeStream","fromWeb","pipe","stream","finished","writeFile","stringify","error","removeAllAsync","Promise","all","map","rm","force","catch"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/api/rest/cache/ResponseCache.ts"],"sourcesContent":["import crypto from 'crypto';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/api/rest/cache/ResponseCache.ts"],"sourcesContent":["import crypto from 'crypto';\nimport type { Response, RequestInfo, RequestInit } from 'fetch-nodeshim';\nimport { ReadStream } from 'fs';\n\nconst GLOBAL_CACHE_VERSION = 4;\n\nexport type ResponseCacheEntry = {\n body: ReadableStream;\n info: ReturnType<typeof getResponseInfo>;\n};\n\nexport interface ResponseCache {\n /** Load the response info from cache, if any */\n get(cacheKey: string): Promise<ResponseCacheEntry | undefined>;\n /** Store the response info to cache, and return the cached info */\n set(cacheKey: string, response: ResponseCacheEntry): Promise<ResponseCacheEntry | undefined>;\n /** Remove a response entry from the cache */\n remove(cacheKey: string): Promise<void>;\n}\n\nexport function getResponseInfo(response: Response) {\n const headers = Object.fromEntries(response.headers.entries());\n delete headers['set-cookie'];\n return {\n url: response.url,\n status: response.status,\n statusText: response.statusText,\n headers,\n };\n}\n\nexport function getRequestCacheKey(info: RequestInfo, init?: RequestInit) {\n const infoKeyData = getRequestInfoCacheData(info);\n const initKeyData = { body: init?.body ? getRequestBodyCacheData(init.body) : undefined };\n\n return crypto\n .createHash('md5')\n .update(JSON.stringify([infoKeyData, initKeyData, GLOBAL_CACHE_VERSION]))\n .digest('hex');\n}\n\n/** @internal Exposed for testing */\nexport function getRequestInfoCacheData(info: RequestInfo) {\n if (typeof info === 'string') {\n return { url: info };\n }\n\n if (info instanceof URL) {\n return { url: info.toString() };\n }\n\n if (info instanceof Request) {\n return {\n // cache: req.cache,\n credentials: info.credentials.toString(),\n destination: info.destination.toString(),\n headers: Object.fromEntries(info.headers.entries()),\n integrity: info.integrity,\n method: info.method,\n redirect: info.redirect,\n referrer: info.referrer,\n referrerPolicy: info.referrerPolicy,\n url: info.url.toString(),\n // body: // TODO\n };\n }\n\n throw new Error('Unsupported request info type for caching: ' + typeof info);\n}\n\n/** @internal Exposed for testing */\nexport function getRequestBodyCacheData(body: RequestInit['body']) {\n if (!body) {\n return body;\n }\n\n if (typeof body === 'string') {\n return body;\n }\n\n if (body instanceof URLSearchParams) {\n return body.toString();\n }\n\n // Supported for legacy purposes because node-fetch uses fs.readStream\n if (body instanceof ReadStream) {\n return body.path;\n }\n\n if (body.toString && body.toString() === '[object FormData]') {\n return new URLSearchParams(body as any).toString();\n }\n\n if (body instanceof Buffer) {\n return body.toString();\n }\n\n throw new Error(`Unsupported request body type for caching: ${typeof body}`);\n}\n"],"names":["getRequestBodyCacheData","getRequestCacheKey","getRequestInfoCacheData","getResponseInfo","GLOBAL_CACHE_VERSION","response","headers","Object","fromEntries","entries","url","status","statusText","info","init","infoKeyData","initKeyData","body","undefined","crypto","createHash","update","JSON","stringify","digest","URL","toString","Request","credentials","destination","integrity","method","redirect","referrer","referrerPolicy","Error","URLSearchParams","ReadStream","path","Buffer"],"mappings":";;;;;;;;;;;IAuEgBA,uBAAuB;eAAvBA;;IAxCAC,kBAAkB;eAAlBA;;IAWAC,uBAAuB;eAAvBA;;IAtBAC,eAAe;eAAfA;;;;gEApBG;;;;;;;yBAEQ;;;;;;;;;;;AAE3B,MAAMC,uBAAuB;AAgBtB,SAASD,gBAAgBE,QAAkB;IAChD,MAAMC,UAAUC,OAAOC,WAAW,CAACH,SAASC,OAAO,CAACG,OAAO;IAC3D,OAAOH,OAAO,CAAC,aAAa;IAC5B,OAAO;QACLI,KAAKL,SAASK,GAAG;QACjBC,QAAQN,SAASM,MAAM;QACvBC,YAAYP,SAASO,UAAU;QAC/BN;IACF;AACF;AAEO,SAASL,mBAAmBY,IAAiB,EAAEC,IAAkB;IACtE,MAAMC,cAAcb,wBAAwBW;IAC5C,MAAMG,cAAc;QAAEC,MAAMH,CAAAA,wBAAAA,KAAMG,IAAI,IAAGjB,wBAAwBc,KAAKG,IAAI,IAAIC;IAAU;IAExF,OAAOC,iBAAM,CACVC,UAAU,CAAC,OACXC,MAAM,CAACC,KAAKC,SAAS,CAAC;QAACR;QAAaC;QAAaZ;KAAqB,GACtEoB,MAAM,CAAC;AACZ;AAGO,SAAStB,wBAAwBW,IAAiB;IACvD,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAO;YAAEH,KAAKG;QAAK;IACrB;IAEA,IAAIA,gBAAgBY,KAAK;QACvB,OAAO;YAAEf,KAAKG,KAAKa,QAAQ;QAAG;IAChC;IAEA,IAAIb,gBAAgBc,SAAS;QAC3B,OAAO;YACL,oBAAoB;YACpBC,aAAaf,KAAKe,WAAW,CAACF,QAAQ;YACtCG,aAAahB,KAAKgB,WAAW,CAACH,QAAQ;YACtCpB,SAASC,OAAOC,WAAW,CAACK,KAAKP,OAAO,CAACG,OAAO;YAChDqB,WAAWjB,KAAKiB,SAAS;YACzBC,QAAQlB,KAAKkB,MAAM;YACnBC,UAAUnB,KAAKmB,QAAQ;YACvBC,UAAUpB,KAAKoB,QAAQ;YACvBC,gBAAgBrB,KAAKqB,cAAc;YACnCxB,KAAKG,KAAKH,GAAG,CAACgB,QAAQ;QAExB;IACF;IAEA,MAAM,IAAIS,MAAM,gDAAgD,OAAOtB;AACzE;AAGO,SAASb,wBAAwBiB,IAAyB;IAC/D,IAAI,CAACA,MAAM;QACT,OAAOA;IACT;IAEA,IAAI,OAAOA,SAAS,UAAU;QAC5B,OAAOA;IACT;IAEA,IAAIA,gBAAgBmB,iBAAiB;QACnC,OAAOnB,KAAKS,QAAQ;IACtB;IAEA,sEAAsE;IACtE,IAAIT,gBAAgBoB,gBAAU,EAAE;QAC9B,OAAOpB,KAAKqB,IAAI;IAClB;IAEA,IAAIrB,KAAKS,QAAQ,IAAIT,KAAKS,QAAQ,OAAO,qBAAqB;QAC5D,OAAO,IAAIU,gBAAgBnB,MAAaS,QAAQ;IAClD;IAEA,IAAIT,gBAAgBsB,QAAQ;QAC1B,OAAOtB,KAAKS,QAAQ;IACtB;IAEA,MAAM,IAAIS,MAAM,CAAC,2CAA2C,EAAE,OAAOlB,MAAM;AAC7E"}
|
|
@@ -8,28 +8,28 @@ Object.defineProperty(exports, "wrapFetchWithCache", {
|
|
|
8
8
|
return wrapFetchWithCache;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
function
|
|
12
|
-
const data = require("
|
|
13
|
-
|
|
11
|
+
function _fetchnodeshim() {
|
|
12
|
+
const data = require("fetch-nodeshim");
|
|
13
|
+
_fetchnodeshim = function() {
|
|
14
14
|
return data;
|
|
15
15
|
};
|
|
16
16
|
return data;
|
|
17
17
|
}
|
|
18
18
|
const _ResponseCache = require("./ResponseCache");
|
|
19
|
-
const debug = require('debug')('expo:
|
|
19
|
+
const debug = require('debug')('expo:fetch-cache');
|
|
20
20
|
function wrapFetchWithCache(fetch, cache) {
|
|
21
21
|
return async function cachedFetch(url, init) {
|
|
22
22
|
const cacheKey = (0, _ResponseCache.getRequestCacheKey)(url, init);
|
|
23
23
|
const cachedResponse = await cache.get(cacheKey);
|
|
24
24
|
if (cachedResponse) {
|
|
25
|
-
return new (
|
|
25
|
+
return new (_fetchnodeshim()).Response(cachedResponse.body, cachedResponse.info);
|
|
26
26
|
}
|
|
27
27
|
await lock(cacheKey);
|
|
28
28
|
try {
|
|
29
29
|
// Retry loading from cache, in case it was stored during the lock
|
|
30
30
|
let cachedResponse = await cache.get(cacheKey);
|
|
31
31
|
if (cachedResponse) {
|
|
32
|
-
return new (
|
|
32
|
+
return new (_fetchnodeshim()).Response(cachedResponse.body, cachedResponse.info);
|
|
33
33
|
}
|
|
34
34
|
// Execute the fetch request
|
|
35
35
|
const response = await fetch(url, init);
|
|
@@ -48,7 +48,7 @@ function wrapFetchWithCache(fetch, cache) {
|
|
|
48
48
|
return response;
|
|
49
49
|
}
|
|
50
50
|
// Return the cached response
|
|
51
|
-
return new (
|
|
51
|
+
return new (_fetchnodeshim()).Response(cachedResponse.body, cachedResponse.info);
|
|
52
52
|
} finally{
|
|
53
53
|
unlock(cacheKey);
|
|
54
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/api/rest/cache/wrapFetchWithCache.ts"],"sourcesContent":["import { Response, type RequestInfo, type RequestInit } from '
|
|
1
|
+
{"version":3,"sources":["../../../../../src/api/rest/cache/wrapFetchWithCache.ts"],"sourcesContent":["import { Response, type RequestInfo, type RequestInit } from 'fetch-nodeshim';\n\nimport { getRequestCacheKey, getResponseInfo, type ResponseCache } from './ResponseCache';\nimport type { FetchLike } from '../client.types';\n\nconst debug = require('debug')('expo:fetch-cache');\n\nexport function wrapFetchWithCache(fetch: FetchLike, cache: ResponseCache): FetchLike {\n return async function cachedFetch(url: RequestInfo, init?: RequestInit) {\n const cacheKey = getRequestCacheKey(url, init);\n const cachedResponse = await cache.get(cacheKey);\n if (cachedResponse) {\n return new Response(cachedResponse.body, cachedResponse.info);\n }\n\n await lock(cacheKey);\n\n try {\n // Retry loading from cache, in case it was stored during the lock\n let cachedResponse = await cache.get(cacheKey);\n if (cachedResponse) {\n return new Response(cachedResponse.body, cachedResponse.info);\n }\n\n // Execute the fetch request\n const response = await fetch(url, init);\n if (!response.ok || !response.body) {\n return response;\n }\n\n // Cache the response\n cachedResponse = await cache.set(cacheKey, {\n body: response.body,\n info: getResponseInfo(response),\n });\n\n // Warn through debug logs that caching failed\n if (!cachedResponse) {\n debug(`Failed to cache response for: ${url}`);\n await cache.remove(cacheKey);\n return response;\n }\n\n // Return the cached response\n return new Response(cachedResponse.body, cachedResponse.info);\n } finally {\n unlock(cacheKey);\n }\n };\n}\n\nconst lockPromiseForKey: Record<string, Promise<any>> = {};\nconst unlockFunctionForKey: Record<string, any> = {};\n\nasync function lock(key: string) {\n if (!lockPromiseForKey[key]) {\n lockPromiseForKey[key] = Promise.resolve();\n }\n\n const takeLockPromise = lockPromiseForKey[key];\n lockPromiseForKey[key] = takeLockPromise.then(\n () =>\n new Promise((fulfill) => {\n unlockFunctionForKey[key] = fulfill;\n })\n );\n\n return takeLockPromise;\n}\n\nfunction unlock(key: string) {\n if (unlockFunctionForKey[key]) {\n unlockFunctionForKey[key]();\n delete unlockFunctionForKey[key];\n }\n}\n"],"names":["wrapFetchWithCache","debug","require","fetch","cache","cachedFetch","url","init","cacheKey","getRequestCacheKey","cachedResponse","get","Response","body","info","lock","response","ok","set","getResponseInfo","remove","unlock","lockPromiseForKey","unlockFunctionForKey","key","Promise","resolve","takeLockPromise","then","fulfill"],"mappings":";;;;+BAOgBA;;;eAAAA;;;;yBAP6C;;;;;;+BAEW;AAGxE,MAAMC,QAAQC,QAAQ,SAAS;AAExB,SAASF,mBAAmBG,KAAgB,EAAEC,KAAoB;IACvE,OAAO,eAAeC,YAAYC,GAAgB,EAAEC,IAAkB;QACpE,MAAMC,WAAWC,IAAAA,iCAAkB,EAACH,KAAKC;QACzC,MAAMG,iBAAiB,MAAMN,MAAMO,GAAG,CAACH;QACvC,IAAIE,gBAAgB;YAClB,OAAO,IAAIE,CAAAA,gBAAO,UAAC,CAACF,eAAeG,IAAI,EAAEH,eAAeI,IAAI;QAC9D;QAEA,MAAMC,KAAKP;QAEX,IAAI;YACF,kEAAkE;YAClE,IAAIE,iBAAiB,MAAMN,MAAMO,GAAG,CAACH;YACrC,IAAIE,gBAAgB;gBAClB,OAAO,IAAIE,CAAAA,gBAAO,UAAC,CAACF,eAAeG,IAAI,EAAEH,eAAeI,IAAI;YAC9D;YAEA,4BAA4B;YAC5B,MAAME,WAAW,MAAMb,MAAMG,KAAKC;YAClC,IAAI,CAACS,SAASC,EAAE,IAAI,CAACD,SAASH,IAAI,EAAE;gBAClC,OAAOG;YACT;YAEA,qBAAqB;YACrBN,iBAAiB,MAAMN,MAAMc,GAAG,CAACV,UAAU;gBACzCK,MAAMG,SAASH,IAAI;gBACnBC,MAAMK,IAAAA,8BAAe,EAACH;YACxB;YAEA,8CAA8C;YAC9C,IAAI,CAACN,gBAAgB;gBACnBT,MAAM,CAAC,8BAA8B,EAAEK,KAAK;gBAC5C,MAAMF,MAAMgB,MAAM,CAACZ;gBACnB,OAAOQ;YACT;YAEA,6BAA6B;YAC7B,OAAO,IAAIJ,CAAAA,gBAAO,UAAC,CAACF,eAAeG,IAAI,EAAEH,eAAeI,IAAI;QAC9D,SAAU;YACRO,OAAOb;QACT;IACF;AACF;AAEA,MAAMc,oBAAkD,CAAC;AACzD,MAAMC,uBAA4C,CAAC;AAEnD,eAAeR,KAAKS,GAAW;IAC7B,IAAI,CAACF,iBAAiB,CAACE,IAAI,EAAE;QAC3BF,iBAAiB,CAACE,IAAI,GAAGC,QAAQC,OAAO;IAC1C;IAEA,MAAMC,kBAAkBL,iBAAiB,CAACE,IAAI;IAC9CF,iBAAiB,CAACE,IAAI,GAAGG,gBAAgBC,IAAI,CAC3C,IACE,IAAIH,QAAQ,CAACI;YACXN,oBAAoB,CAACC,IAAI,GAAGK;QAC9B;IAGJ,OAAOF;AACT;AAEA,SAASN,OAAOG,GAAW;IACzB,IAAID,oBAAoB,CAACC,IAAI,EAAE;QAC7BD,oBAAoB,CAACC,IAAI;QACzB,OAAOD,oBAAoB,CAACC,IAAI;IAClC;AACF"}
|