@immediately-run/sandpack-client 2.19.8
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/README.md +26 -0
- package/dist/.ir-build-stamp.json +6 -0
- package/dist/base-DBh7xJX9.mjs +48 -0
- package/dist/base-DelKLlDk.js +50 -0
- package/dist/clients/base.d.ts +34 -0
- package/dist/clients/event-emitter.d.ts +10 -0
- package/dist/clients/iframe-factory.d.ts +27 -0
- package/dist/clients/index.d.ts +4 -0
- package/dist/clients/node/client.utils.d.ts +7 -0
- package/dist/clients/node/iframe.utils.d.ts +3 -0
- package/dist/clients/node/index.d.ts +49 -0
- package/dist/clients/node/index.js +631 -0
- package/dist/clients/node/index.mjs +629 -0
- package/dist/clients/node/inject-scripts/historyListener.d.ts +5 -0
- package/dist/clients/node/inject-scripts/index.d.ts +1 -0
- package/dist/clients/node/inject-scripts/resize.d.ts +5 -0
- package/dist/clients/node/taskManager.d.ts +20 -0
- package/dist/clients/node/types.d.ts +63 -0
- package/dist/clients/runtime/file-resolver-protocol.d.ts +17 -0
- package/dist/clients/runtime/iframe-protocol.d.ts +17 -0
- package/dist/clients/runtime/immutable-fetch-protocol.d.ts +39 -0
- package/dist/clients/runtime/index.d.ts +76 -0
- package/dist/clients/runtime/index.js +1046 -0
- package/dist/clients/runtime/index.mjs +1044 -0
- package/dist/clients/runtime/mime.d.ts +1 -0
- package/dist/clients/runtime/types.d.ts +129 -0
- package/dist/clients/runtime/utils.d.ts +8 -0
- package/dist/clients/static/index.d.ts +25 -0
- package/dist/clients/static/utils.d.ts +5 -0
- package/dist/consoleHook-DQVWjDRE.mjs +230 -0
- package/dist/consoleHook-znXctRzh.js +236 -0
- package/dist/fs/SandpackFS.d.ts +116 -0
- package/dist/iframe-factory-BcC-S_XQ.js +54 -0
- package/dist/iframe-factory-DybmkzJZ.mjs +51 -0
- package/dist/index--fILWAw8.js +210 -0
- package/dist/index-rbhm_KmF.mjs +208 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +53 -0
- package/dist/index.mjs +40 -0
- package/dist/inject-scripts/consoleHook.d.ts +6 -0
- package/dist/types-BFONOA2L.mjs +531 -0
- package/dist/types-BIIEoWr6.js +534 -0
- package/dist/types.d.ts +348 -0
- package/dist/utils-BiVyytui.js +262 -0
- package/dist/utils-DG1HA4RZ.mjs +250 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +13 -0
- package/dist/utils.mjs +2 -0
- package/package.json +82 -0
|
@@ -0,0 +1,1044 @@
|
|
|
1
|
+
import { _ as __awaiter, a as __generator, h as __assign, i as __rest, j as __spreadArray, g as __extends, f as nullthrows, e as extractErrorDetails, c as createError, d as createPackageJSON } from '../../utils-DG1HA4RZ.mjs';
|
|
2
|
+
import { dequal } from 'dequal';
|
|
3
|
+
import { a as SandpackLogLevel } from '../../types-BFONOA2L.mjs';
|
|
4
|
+
import { S as SandpackClient } from '../../base-DBh7xJX9.mjs';
|
|
5
|
+
import { c as createSandboxedIframe, e as ensureSandboxed } from '../../iframe-factory-DybmkzJZ.mjs';
|
|
6
|
+
import mimeDB from 'mime-db';
|
|
7
|
+
import 'outvariant';
|
|
8
|
+
import '@zenfs/core';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* This file is a copy of the resolver from the `codesandbox-api` package.
|
|
12
|
+
* We wanted to avoid to reference codesandbox-api because of the code that runs on load in the package.
|
|
13
|
+
* The plan is to take some time and refactor codesandbox-api into what it was supposed to be in the first place,
|
|
14
|
+
* an abstraction over the actions that can be dispatched between the bundler and the iframe.
|
|
15
|
+
*/
|
|
16
|
+
var Protocol = /** @class */ (function () {
|
|
17
|
+
function Protocol(type, handleMessage, protocol) {
|
|
18
|
+
var _this = this;
|
|
19
|
+
this.type = type;
|
|
20
|
+
this.handleMessage = handleMessage;
|
|
21
|
+
this.protocol = protocol;
|
|
22
|
+
this._disposeMessageListener = this.protocol.channelListen(function (msg) { return __awaiter(_this, void 0, void 0, function () {
|
|
23
|
+
var message, result, response, err_1, response;
|
|
24
|
+
return __generator(this, function (_a) {
|
|
25
|
+
switch (_a.label) {
|
|
26
|
+
case 0:
|
|
27
|
+
if (!(msg.type === this.getTypeId() && msg.method)) return [3 /*break*/, 4];
|
|
28
|
+
message = msg;
|
|
29
|
+
_a.label = 1;
|
|
30
|
+
case 1:
|
|
31
|
+
_a.trys.push([1, 3, , 4]);
|
|
32
|
+
return [4 /*yield*/, this.handleMessage(message)];
|
|
33
|
+
case 2:
|
|
34
|
+
result = _a.sent();
|
|
35
|
+
response = {
|
|
36
|
+
type: this.getTypeId(),
|
|
37
|
+
msgId: message.msgId,
|
|
38
|
+
result: result,
|
|
39
|
+
};
|
|
40
|
+
this.protocol.dispatch(response);
|
|
41
|
+
return [3 /*break*/, 4];
|
|
42
|
+
case 3:
|
|
43
|
+
err_1 = _a.sent();
|
|
44
|
+
response = {
|
|
45
|
+
type: this.getTypeId(),
|
|
46
|
+
msgId: message.msgId,
|
|
47
|
+
error: {
|
|
48
|
+
message: err_1.message,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
this.protocol.dispatch(response);
|
|
52
|
+
return [3 /*break*/, 4];
|
|
53
|
+
case 4: return [2 /*return*/];
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}); });
|
|
57
|
+
}
|
|
58
|
+
Protocol.prototype.getTypeId = function () {
|
|
59
|
+
return "protocol-".concat(this.type);
|
|
60
|
+
};
|
|
61
|
+
Protocol.prototype.dispose = function () {
|
|
62
|
+
this._disposeMessageListener();
|
|
63
|
+
};
|
|
64
|
+
return Protocol;
|
|
65
|
+
}());
|
|
66
|
+
|
|
67
|
+
var IFrameProtocol = /** @class */ (function () {
|
|
68
|
+
function IFrameProtocol(iframe, origin) {
|
|
69
|
+
// React to messages from any iframe
|
|
70
|
+
this.globalListeners = {};
|
|
71
|
+
this.globalListenersCount = 0;
|
|
72
|
+
// React to messages from the iframe owned by this instance
|
|
73
|
+
this.channelListeners = {};
|
|
74
|
+
this.channelListenersCount = 0;
|
|
75
|
+
// Random number to identify this instance of the client when messages are coming from multiple iframes
|
|
76
|
+
this.channelId = Math.floor(Math.random() * 1000000);
|
|
77
|
+
this.frameWindow = iframe.contentWindow;
|
|
78
|
+
this.origin = '*'; //origin;
|
|
79
|
+
this.globalListeners = [];
|
|
80
|
+
this.channelListeners = [];
|
|
81
|
+
this.eventListener = this.eventListener.bind(this);
|
|
82
|
+
if (typeof window !== "undefined") {
|
|
83
|
+
window.addEventListener("message", this.eventListener);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
IFrameProtocol.prototype.cleanup = function () {
|
|
87
|
+
window.removeEventListener("message", this.eventListener);
|
|
88
|
+
this.globalListeners = {};
|
|
89
|
+
this.channelListeners = {};
|
|
90
|
+
this.globalListenersCount = 0;
|
|
91
|
+
this.channelListenersCount = 0;
|
|
92
|
+
};
|
|
93
|
+
// Sends the channelId and triggers an iframeHandshake promise to resolve,
|
|
94
|
+
// so the iframe can start listening for messages (based on the id).
|
|
95
|
+
// `config` carries the bundler's bootstrap configuration (template/logLevel/
|
|
96
|
+
// recompileDelay) — the bundler watches the shared filesystem itself and no
|
|
97
|
+
// longer receives a `compile` message, so it needs this delivered once here.
|
|
98
|
+
IFrameProtocol.prototype.register = function (port, config, babelPort) {
|
|
99
|
+
if (!this.frameWindow) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
console.log("[IFrameProtocol] Registering iframe with channelId", this.channelId, this);
|
|
103
|
+
// Order matters: the bundler reads ports[0] as the fs port and ports[1] as
|
|
104
|
+
// the Babel worker port. `filter` keeps that order as long as the fs port
|
|
105
|
+
// is always present (it is, in normal operation).
|
|
106
|
+
var ports = [port, babelPort].filter(function (p) { return p != null; });
|
|
107
|
+
this.frameWindow.postMessage(__assign({ type: "register-frame", origin: document.location.origin, id: this.channelId }, config), this.origin, ports);
|
|
108
|
+
};
|
|
109
|
+
// Messages are dispatched from the client directly to the instance iframe
|
|
110
|
+
IFrameProtocol.prototype.dispatch = function (message) {
|
|
111
|
+
if (!this.frameWindow) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// `_transfer` (e.g. a MessagePort for a mount's filesystem) must be passed
|
|
115
|
+
// as the postMessage transfer list, not as a serialized payload field.
|
|
116
|
+
var _transfer = message._transfer, payload = __rest(message, ["_transfer"]);
|
|
117
|
+
this.frameWindow.postMessage(__assign({ $id: this.channelId, codesandbox: true }, payload), this.origin, _transfer !== null && _transfer !== void 0 ? _transfer : []);
|
|
118
|
+
};
|
|
119
|
+
// Add a listener that is called on any message coming from an iframe in the page
|
|
120
|
+
// This is needed for the `initialize` message which comes without a channelId
|
|
121
|
+
IFrameProtocol.prototype.globalListen = function (listener) {
|
|
122
|
+
var _this = this;
|
|
123
|
+
if (typeof listener !== "function") {
|
|
124
|
+
return function () {
|
|
125
|
+
return;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
var listenerId = this.globalListenersCount;
|
|
129
|
+
this.globalListeners[listenerId] = listener;
|
|
130
|
+
this.globalListenersCount++;
|
|
131
|
+
return function () {
|
|
132
|
+
delete _this.globalListeners[listenerId];
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
// Add a listener that is called on any message coming from an iframe with the instance channelId
|
|
136
|
+
// All other messages (eg: from other iframes) are ignored
|
|
137
|
+
IFrameProtocol.prototype.channelListen = function (listener) {
|
|
138
|
+
var _this = this;
|
|
139
|
+
if (typeof listener !== "function") {
|
|
140
|
+
return function () {
|
|
141
|
+
return;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
var listenerId = this.channelListenersCount;
|
|
145
|
+
this.channelListeners[listenerId] = listener;
|
|
146
|
+
this.channelListenersCount++;
|
|
147
|
+
return function () {
|
|
148
|
+
delete _this.channelListeners[listenerId];
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
// Handles message windows coming from iframes
|
|
152
|
+
IFrameProtocol.prototype.eventListener = function (evt) {
|
|
153
|
+
// skip events originating from different iframes
|
|
154
|
+
if (evt.source !== this.frameWindow) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
var message = evt.data;
|
|
158
|
+
if (!message.codesandbox) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
Object.values(this.globalListeners).forEach(function (listener) {
|
|
162
|
+
return listener(message);
|
|
163
|
+
});
|
|
164
|
+
if (message.$id !== this.channelId) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
Object.values(this.channelListeners).forEach(function (listener) {
|
|
168
|
+
return listener(message);
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
return IFrameProtocol;
|
|
172
|
+
}());
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Parent-side fetch + cache for immutable, exact-versioned module URLs.
|
|
176
|
+
*
|
|
177
|
+
* The bundler iframe runs at an opaque origin (sandboxed without
|
|
178
|
+
* `allow-same-origin`), so it has no persistent storage of any kind — its own
|
|
179
|
+
* Cache API is unavailable. It therefore forwards immutable-URL fetches here
|
|
180
|
+
* over the iframe protocol (`protocol-immutable-fetch`), and the parent — a
|
|
181
|
+
* real origin — serves them cache-first from a persistent Cache API cache.
|
|
182
|
+
*
|
|
183
|
+
* Security: the handler only fetches URLs matching {@link IMMUTABLE_URL_ALLOWLIST}.
|
|
184
|
+
* The iframe runs untrusted code, and an unrestricted parent-side fetch proxy
|
|
185
|
+
* would let it read arbitrary cross-origin responses with the parent's network
|
|
186
|
+
* context (a CORS bypass). The allowlist mirrors the prefixes the bundler
|
|
187
|
+
* registers via `registerImmutableUrlPrefix` (see sandpack-bundler
|
|
188
|
+
* `src/utils/fetch.ts`) — keep the two in sync.
|
|
189
|
+
*/
|
|
190
|
+
/**
|
|
191
|
+
* URL prefixes whose responses never change for a given URL (the URL encodes
|
|
192
|
+
* the exact content version). Only these may be fetched on the iframe's
|
|
193
|
+
* behalf, and they are safe to cache forever.
|
|
194
|
+
*/
|
|
195
|
+
var IMMUTABLE_URL_ALLOWLIST = [
|
|
196
|
+
// Module CDN, exact-versioned package bundles. (NOT /dep_tree/, which
|
|
197
|
+
// resolves semver ranges and changes as new versions publish.)
|
|
198
|
+
"https://sandpack-cdn-staging.blazingly.io/package/",
|
|
199
|
+
// unpkg files, requested by the bundler at registry-resolved exact versions.
|
|
200
|
+
"https://unpkg.com/",
|
|
201
|
+
// Self-hosted, versioned @immediately-run/sdk builds (SDK_PACKAGING_SPEC
|
|
202
|
+
// §5/§11, Option A). The /v/<version>/ path encodes the exact version, so
|
|
203
|
+
// responses are immutable; the bundler fetches these when an app opts the SDK
|
|
204
|
+
// into immediately.run.resolveFromRegistry. Keep in sync with the prefix the
|
|
205
|
+
// bundler registers via registerImmutableUrlPrefix (sandbox bundler.ts).
|
|
206
|
+
"https://immediately-run.github.io/immediately-run-sdk/v/",
|
|
207
|
+
];
|
|
208
|
+
var IMMUTABLE_CACHE_NAME = "sandpack-immutable-fetch-v1";
|
|
209
|
+
var serializeResponse = function (res) { return __awaiter(void 0, void 0, void 0, function () {
|
|
210
|
+
var _a;
|
|
211
|
+
var _b;
|
|
212
|
+
return __generator(this, function (_c) {
|
|
213
|
+
switch (_c.label) {
|
|
214
|
+
case 0:
|
|
215
|
+
_a = {
|
|
216
|
+
status: res.status,
|
|
217
|
+
contentType: (_b = res.headers.get("content-type")) !== null && _b !== void 0 ? _b : ""
|
|
218
|
+
};
|
|
219
|
+
return [4 /*yield*/, res.arrayBuffer()];
|
|
220
|
+
case 1: return [2 /*return*/, (_a.body = _c.sent(),
|
|
221
|
+
_a)];
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}); };
|
|
225
|
+
// CacheStorage may be unavailable (insecure context) or fail (storage
|
|
226
|
+
// pressure); degrade to a plain fetch rather than failing the request.
|
|
227
|
+
var openCache = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
228
|
+
return __generator(this, function (_b) {
|
|
229
|
+
switch (_b.label) {
|
|
230
|
+
case 0:
|
|
231
|
+
_b.trys.push([0, 2, , 3]);
|
|
232
|
+
return [4 /*yield*/, caches.open(IMMUTABLE_CACHE_NAME)];
|
|
233
|
+
case 1: return [2 /*return*/, _b.sent()];
|
|
234
|
+
case 2:
|
|
235
|
+
_b.sent();
|
|
236
|
+
return [2 /*return*/, undefined];
|
|
237
|
+
case 3: return [2 /*return*/];
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}); };
|
|
241
|
+
/** SHA-384 of bytes, formatted `sha384-<base64>` (SRI style). */
|
|
242
|
+
var sha384 = function (body) { return __awaiter(void 0, void 0, void 0, function () {
|
|
243
|
+
var digest, bin, view, i;
|
|
244
|
+
return __generator(this, function (_a) {
|
|
245
|
+
switch (_a.label) {
|
|
246
|
+
case 0: return [4 /*yield*/, crypto.subtle.digest("SHA-384", body)];
|
|
247
|
+
case 1:
|
|
248
|
+
digest = _a.sent();
|
|
249
|
+
bin = "";
|
|
250
|
+
view = new Uint8Array(digest);
|
|
251
|
+
for (i = 0; i < view.length; i++)
|
|
252
|
+
bin += String.fromCharCode(view[i]);
|
|
253
|
+
return [2 /*return*/, "sha384-".concat(btoa(bin))];
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}); };
|
|
257
|
+
/**
|
|
258
|
+
* Does `body` match the caller-supplied `integrity` (an `sha384-<base64>` SRI
|
|
259
|
+
* hash)? Returns true when no integrity was supplied (nothing to check).
|
|
260
|
+
*/
|
|
261
|
+
var matchesIntegrity = function (body, integrity) { return __awaiter(void 0, void 0, void 0, function () {
|
|
262
|
+
return __generator(this, function (_b) {
|
|
263
|
+
switch (_b.label) {
|
|
264
|
+
case 0:
|
|
265
|
+
if (!integrity)
|
|
266
|
+
return [2 /*return*/, true];
|
|
267
|
+
_b.label = 1;
|
|
268
|
+
case 1:
|
|
269
|
+
_b.trys.push([1, 3, , 4]);
|
|
270
|
+
return [4 /*yield*/, sha384(body)];
|
|
271
|
+
case 2: return [2 /*return*/, (_b.sent()) === integrity];
|
|
272
|
+
case 3:
|
|
273
|
+
_b.sent();
|
|
274
|
+
// crypto unavailable → can't verify; treat as a non-match so we neither
|
|
275
|
+
// serve nor persist bytes we couldn't validate (fail safe).
|
|
276
|
+
return [2 /*return*/, false];
|
|
277
|
+
case 4: return [2 /*return*/];
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}); };
|
|
281
|
+
/**
|
|
282
|
+
* `protocol-immutable-fetch` handler: serve an allowlisted immutable URL,
|
|
283
|
+
* cache-first from the persistent parent-side cache.
|
|
284
|
+
*
|
|
285
|
+
* INTEGRITY-AWARE CACHING (cache-poisoning prevention). When the caller passes
|
|
286
|
+
* the expected SHA-384 (`integrity`), the cache is never allowed to serve or
|
|
287
|
+
* persist bytes that don't match it:
|
|
288
|
+
* - verify-on-read: a cache HIT whose bytes no longer match the expected hash
|
|
289
|
+
* (the host re-pinned the version under the cached bytes) is EVICTED and the
|
|
290
|
+
* URL refetched, so a stale/poisoned entry self-heals instead of failing the
|
|
291
|
+
* consumer forever.
|
|
292
|
+
* - verify-before-cache: freshly fetched bytes are only stored when they match.
|
|
293
|
+
* Mismatched bytes are returned (so the consumer's own check fails closed with
|
|
294
|
+
* a clear error) but NEVER cached, so a bad upstream window can't poison the
|
|
295
|
+
* cache. Without an `integrity` argument the URL is cached by URL as before.
|
|
296
|
+
*/
|
|
297
|
+
function handleImmutableFetch(url, integrity) {
|
|
298
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
299
|
+
var expected, cache, hit, body, res, result, _a;
|
|
300
|
+
return __generator(this, function (_b) {
|
|
301
|
+
switch (_b.label) {
|
|
302
|
+
case 0:
|
|
303
|
+
if (typeof url !== "string" ||
|
|
304
|
+
!IMMUTABLE_URL_ALLOWLIST.some(function (prefix) { return url.startsWith(prefix); })) {
|
|
305
|
+
throw new Error("URL not allowed for immutable fetch: ".concat(String(url)));
|
|
306
|
+
}
|
|
307
|
+
expected = typeof integrity === "string" ? integrity : undefined;
|
|
308
|
+
return [4 /*yield*/, openCache()];
|
|
309
|
+
case 1:
|
|
310
|
+
cache = _b.sent();
|
|
311
|
+
if (!cache) return [3 /*break*/, 6];
|
|
312
|
+
return [4 /*yield*/, cache.match(url).catch(function () { return undefined; })];
|
|
313
|
+
case 2:
|
|
314
|
+
hit = _b.sent();
|
|
315
|
+
if (!hit) return [3 /*break*/, 6];
|
|
316
|
+
return [4 /*yield*/, hit.clone().arrayBuffer()];
|
|
317
|
+
case 3:
|
|
318
|
+
body = _b.sent();
|
|
319
|
+
return [4 /*yield*/, matchesIntegrity(body, expected)];
|
|
320
|
+
case 4:
|
|
321
|
+
if (_b.sent()) {
|
|
322
|
+
return [2 /*return*/, serializeResponse(hit)];
|
|
323
|
+
}
|
|
324
|
+
// Stale/poisoned entry: drop it and fall through to a fresh fetch.
|
|
325
|
+
return [4 /*yield*/, cache.delete(url).catch(function () { })];
|
|
326
|
+
case 5:
|
|
327
|
+
// Stale/poisoned entry: drop it and fall through to a fresh fetch.
|
|
328
|
+
_b.sent();
|
|
329
|
+
_b.label = 6;
|
|
330
|
+
case 6: return [4 /*yield*/, fetch(url)];
|
|
331
|
+
case 7:
|
|
332
|
+
res = _b.sent();
|
|
333
|
+
if (!res.ok) {
|
|
334
|
+
throw new Error("Immutable fetch failed with status ".concat(res.status, ": ").concat(url));
|
|
335
|
+
}
|
|
336
|
+
return [4 /*yield*/, serializeResponse(res)];
|
|
337
|
+
case 8:
|
|
338
|
+
result = _b.sent();
|
|
339
|
+
_a = cache;
|
|
340
|
+
if (!_a) return [3 /*break*/, 10];
|
|
341
|
+
return [4 /*yield*/, matchesIntegrity(result.body, expected)];
|
|
342
|
+
case 9:
|
|
343
|
+
_a = (_b.sent());
|
|
344
|
+
_b.label = 10;
|
|
345
|
+
case 10:
|
|
346
|
+
if (!_a) return [3 /*break*/, 12];
|
|
347
|
+
// Only persist verified bytes. A failed put (quota) only costs the entry.
|
|
348
|
+
return [4 /*yield*/, cache
|
|
349
|
+
.put(url, new Response(result.body.slice(0), { status: result.status, headers: { "content-type": result.contentType } }))
|
|
350
|
+
.catch(function () { })];
|
|
351
|
+
case 11:
|
|
352
|
+
// Only persist verified bytes. A failed put (quota) only costs the entry.
|
|
353
|
+
_b.sent();
|
|
354
|
+
_b.label = 12;
|
|
355
|
+
case 12: return [2 /*return*/, result];
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
var extensionMap = new Map();
|
|
362
|
+
var entries = Object.entries(mimeDB);
|
|
363
|
+
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
364
|
+
var _a$1 = entries_1[_i], mimetype = _a$1[0], entry = _a$1[1];
|
|
365
|
+
// eslint-disable-next-line
|
|
366
|
+
// @ts-ignore
|
|
367
|
+
if (!entry.extensions) {
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
// eslint-disable-next-line
|
|
371
|
+
// @ts-ignore
|
|
372
|
+
var extensions = entry.extensions;
|
|
373
|
+
if (extensions.length) {
|
|
374
|
+
for (var _b = 0, extensions_1 = extensions; _b < extensions_1.length; _b++) {
|
|
375
|
+
var ext = extensions_1[_b];
|
|
376
|
+
extensionMap.set(ext, mimetype);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
var EXTENSIONS_MAP = extensionMap;
|
|
381
|
+
|
|
382
|
+
var CHANNEL_NAME = "$CSB_RELAY";
|
|
383
|
+
|
|
384
|
+
var MAX_CLIENT_DEPENDENCY_COUNT = 50;
|
|
385
|
+
function getTemplate(pkg,
|
|
386
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
387
|
+
modules) {
|
|
388
|
+
if (!pkg) {
|
|
389
|
+
return "static";
|
|
390
|
+
}
|
|
391
|
+
var _a = pkg.dependencies, dependencies = _a === void 0 ? {} : _a, _b = pkg.devDependencies, devDependencies = _b === void 0 ? {} : _b;
|
|
392
|
+
var totalDependencies = __spreadArray(__spreadArray([], Object.keys(dependencies), true), Object.keys(devDependencies), true);
|
|
393
|
+
var moduleNames = Object.keys(modules);
|
|
394
|
+
var adonis = ["@adonisjs/framework", "@adonisjs/core"];
|
|
395
|
+
if (totalDependencies.some(function (dep) { return adonis.indexOf(dep) > -1; })) {
|
|
396
|
+
return "adonis";
|
|
397
|
+
}
|
|
398
|
+
var nuxt = ["nuxt", "nuxt-edge", "nuxt-ts", "nuxt-ts-edge", "nuxt3"];
|
|
399
|
+
if (totalDependencies.some(function (dep) { return nuxt.indexOf(dep) > -1; })) {
|
|
400
|
+
return "nuxt";
|
|
401
|
+
}
|
|
402
|
+
if (totalDependencies.indexOf("next") > -1) {
|
|
403
|
+
return "next";
|
|
404
|
+
}
|
|
405
|
+
var apollo = [
|
|
406
|
+
"apollo-server",
|
|
407
|
+
"apollo-server-express",
|
|
408
|
+
"apollo-server-hapi",
|
|
409
|
+
"apollo-server-koa",
|
|
410
|
+
"apollo-server-lambda",
|
|
411
|
+
"apollo-server-micro",
|
|
412
|
+
];
|
|
413
|
+
if (totalDependencies.some(function (dep) { return apollo.indexOf(dep) > -1; })) {
|
|
414
|
+
return "apollo";
|
|
415
|
+
}
|
|
416
|
+
if (totalDependencies.indexOf("mdx-deck") > -1) {
|
|
417
|
+
return "mdx-deck";
|
|
418
|
+
}
|
|
419
|
+
if (totalDependencies.indexOf("gridsome") > -1) {
|
|
420
|
+
return "gridsome";
|
|
421
|
+
}
|
|
422
|
+
if (totalDependencies.indexOf("vuepress") > -1) {
|
|
423
|
+
return "vuepress";
|
|
424
|
+
}
|
|
425
|
+
if (totalDependencies.indexOf("ember-cli") > -1) {
|
|
426
|
+
return "ember";
|
|
427
|
+
}
|
|
428
|
+
if (totalDependencies.indexOf("sapper") > -1) {
|
|
429
|
+
return "sapper";
|
|
430
|
+
}
|
|
431
|
+
if (totalDependencies.indexOf("gatsby") > -1) {
|
|
432
|
+
return "gatsby";
|
|
433
|
+
}
|
|
434
|
+
if (totalDependencies.indexOf("quasar") > -1) {
|
|
435
|
+
return "quasar";
|
|
436
|
+
}
|
|
437
|
+
if (totalDependencies.indexOf("@docusaurus/core") > -1) {
|
|
438
|
+
return "docusaurus";
|
|
439
|
+
}
|
|
440
|
+
if (totalDependencies.indexOf("remix") > -1) {
|
|
441
|
+
return "remix";
|
|
442
|
+
}
|
|
443
|
+
if (totalDependencies.indexOf("astro") > -1) {
|
|
444
|
+
return "node";
|
|
445
|
+
}
|
|
446
|
+
// CLIENT
|
|
447
|
+
if (moduleNames.some(function (m) { return m.endsWith(".re"); })) {
|
|
448
|
+
return "reason";
|
|
449
|
+
}
|
|
450
|
+
var parcel = ["parcel-bundler", "parcel"];
|
|
451
|
+
if (totalDependencies.some(function (dep) { return parcel.indexOf(dep) > -1; })) {
|
|
452
|
+
return "parcel";
|
|
453
|
+
}
|
|
454
|
+
var dojo = ["@dojo/core", "@dojo/framework"];
|
|
455
|
+
if (totalDependencies.some(function (dep) { return dojo.indexOf(dep) > -1; })) {
|
|
456
|
+
return "@dojo/cli-create-app";
|
|
457
|
+
}
|
|
458
|
+
if (totalDependencies.indexOf("@nestjs/core") > -1 ||
|
|
459
|
+
totalDependencies.indexOf("@nestjs/common") > -1) {
|
|
460
|
+
return "nest";
|
|
461
|
+
}
|
|
462
|
+
if (totalDependencies.indexOf("react-styleguidist") > -1) {
|
|
463
|
+
return "styleguidist";
|
|
464
|
+
}
|
|
465
|
+
if (totalDependencies.indexOf("react-scripts") > -1) {
|
|
466
|
+
return "create-react-app";
|
|
467
|
+
}
|
|
468
|
+
if (totalDependencies.indexOf("react-scripts-ts") > -1) {
|
|
469
|
+
return "create-react-app-typescript";
|
|
470
|
+
}
|
|
471
|
+
if (totalDependencies.indexOf("@angular/core") > -1) {
|
|
472
|
+
return "angular-cli";
|
|
473
|
+
}
|
|
474
|
+
if (totalDependencies.indexOf("preact-cli") > -1) {
|
|
475
|
+
return "preact-cli";
|
|
476
|
+
}
|
|
477
|
+
if (totalDependencies.indexOf("@sveltech/routify") > -1 ||
|
|
478
|
+
totalDependencies.indexOf("@roxi/routify") > -1) {
|
|
479
|
+
return "node";
|
|
480
|
+
}
|
|
481
|
+
if (totalDependencies.indexOf("vite") > -1) {
|
|
482
|
+
return "node";
|
|
483
|
+
}
|
|
484
|
+
if (totalDependencies.indexOf("@frontity/core") > -1) {
|
|
485
|
+
return "node";
|
|
486
|
+
}
|
|
487
|
+
if (totalDependencies.indexOf("svelte") > -1) {
|
|
488
|
+
return "svelte";
|
|
489
|
+
}
|
|
490
|
+
if (totalDependencies.indexOf("vue") > -1) {
|
|
491
|
+
return "vue-cli";
|
|
492
|
+
}
|
|
493
|
+
if (totalDependencies.indexOf("cx") > -1) {
|
|
494
|
+
return "cxjs";
|
|
495
|
+
}
|
|
496
|
+
var nodeDeps = [
|
|
497
|
+
"express",
|
|
498
|
+
"koa",
|
|
499
|
+
"nodemon",
|
|
500
|
+
"ts-node",
|
|
501
|
+
"@tensorflow/tfjs-node",
|
|
502
|
+
"webpack-dev-server",
|
|
503
|
+
"snowpack",
|
|
504
|
+
];
|
|
505
|
+
if (totalDependencies.some(function (dep) { return nodeDeps.indexOf(dep) > -1; })) {
|
|
506
|
+
return "node";
|
|
507
|
+
}
|
|
508
|
+
if (Object.keys(dependencies).length >= MAX_CLIENT_DEPENDENCY_COUNT) {
|
|
509
|
+
// The dependencies are too much for client sandboxes to handle
|
|
510
|
+
return "node";
|
|
511
|
+
}
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
function getExtension(filepath) {
|
|
515
|
+
var parts = filepath.split(".");
|
|
516
|
+
if (parts.length <= 1) {
|
|
517
|
+
return "";
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
var ext = parts[parts.length - 1];
|
|
521
|
+
return ext;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
var _a;
|
|
526
|
+
var SUFFIX_PLACEHOLDER = "-{{suffix}}";
|
|
527
|
+
var BUNDLER_URL = "https://".concat((_a = "2.19.8") === null || _a === void 0 ? void 0 : _a.replace(/\./g, "-")).concat(SUFFIX_PLACEHOLDER, "-sandpack.codesandbox.io/");
|
|
528
|
+
var SandpackRuntime = /** @class */ (function (_super) {
|
|
529
|
+
__extends(SandpackRuntime, _super);
|
|
530
|
+
function SandpackRuntime(selector, sandboxSetup, options) {
|
|
531
|
+
if (options === void 0) { options = {}; }
|
|
532
|
+
var _this = _super.call(this, selector, sandboxSetup, options) || this;
|
|
533
|
+
/** Parent-owned Babel transpiler worker, connected to the iframe by port. */
|
|
534
|
+
_this.babelWorker = null;
|
|
535
|
+
_this.getTranspilerContext = function () {
|
|
536
|
+
return new Promise(function (resolve) {
|
|
537
|
+
var unsubscribe = _this.listen(function (message) {
|
|
538
|
+
if (message.type === "transpiler-context") {
|
|
539
|
+
resolve(message.data);
|
|
540
|
+
unsubscribe();
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
_this.dispatch({ type: "get-transpiler-context" });
|
|
544
|
+
});
|
|
545
|
+
};
|
|
546
|
+
_this.getTranspiledFiles = function () {
|
|
547
|
+
return new Promise(function (resolve) {
|
|
548
|
+
var unsubscribe = _this.listen(function (message) {
|
|
549
|
+
if (message.type === "all-modules") {
|
|
550
|
+
resolve(message.data);
|
|
551
|
+
unsubscribe();
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
_this.dispatch({ type: "get-modules" });
|
|
555
|
+
});
|
|
556
|
+
};
|
|
557
|
+
_this.bundlerURL = _this.createBundlerURL();
|
|
558
|
+
_this.bundlerState = undefined;
|
|
559
|
+
_this.errors = [];
|
|
560
|
+
_this.status = "initializing";
|
|
561
|
+
_this.fs = sandboxSetup.fs;
|
|
562
|
+
if (typeof selector === "string") {
|
|
563
|
+
_this.selector = selector;
|
|
564
|
+
var element = document.querySelector(selector);
|
|
565
|
+
nullthrows(element, "The element '".concat(selector, "' was not found"));
|
|
566
|
+
_this.element = element;
|
|
567
|
+
// Opaque-origin app iframe via the single factory (G1/T1). No
|
|
568
|
+
// `allow-same-origin`: the iframe runs untrusted code at an opaque origin
|
|
569
|
+
// so it can't read domain-scoped cookies, register service workers, or
|
|
570
|
+
// touch shared storage on the bundler origin. The Babel worker that used
|
|
571
|
+
// to require same-origin is now owned by the parent and reached over a
|
|
572
|
+
// transferred `MessagePort` (see `createBabelWorkerPort`).
|
|
573
|
+
_this.iframe = createSandboxedIframe();
|
|
574
|
+
_this.initializeElement();
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
_this.element = selector;
|
|
578
|
+
_this.iframe = selector;
|
|
579
|
+
}
|
|
580
|
+
// Set-and-assert: a host-provided iframe is hardened here, and any iframe
|
|
581
|
+
// (created or passed) is verified to carry no `allow-same-origin`.
|
|
582
|
+
ensureSandboxed(_this.iframe);
|
|
583
|
+
_this.setLocationURLIntoIFrame();
|
|
584
|
+
_this.iframeProtocol = new IFrameProtocol(_this.iframe, _this.bundlerURL);
|
|
585
|
+
_this.unsubscribeGlobalListener = _this.iframeProtocol.globalListen(function (mes) {
|
|
586
|
+
if (mes.type !== "initialized" || !_this.iframe.contentWindow) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
// this may not work with a boundedcontext, it may require an actual FS instance
|
|
590
|
+
var remotePortPromise = _this.fs.connectRemote();
|
|
591
|
+
remotePortPromise.then(function (remotePort) { return __awaiter(_this, void 0, void 0, function () {
|
|
592
|
+
var config, babelPort;
|
|
593
|
+
var _this = this;
|
|
594
|
+
return __generator(this, function (_a) {
|
|
595
|
+
switch (_a.label) {
|
|
596
|
+
case 0:
|
|
597
|
+
/**
|
|
598
|
+
* Lazy file resolution over the iframe protocol, backed by the
|
|
599
|
+
* {@link SandpackFS} passed on construction. Created before `register`
|
|
600
|
+
* so it's ready for the bundler's lazy file reads as soon as the
|
|
601
|
+
* bundler has the fs port.
|
|
602
|
+
*/
|
|
603
|
+
this.fileResolverProtocol = new Protocol("fs", function (data) { return __awaiter(_this, void 0, void 0, function () {
|
|
604
|
+
return __generator(this, function (_a) {
|
|
605
|
+
if (data.method === "isFile") {
|
|
606
|
+
return [2 /*return*/, this.sandboxSetup.fs.exists(data.params[0])];
|
|
607
|
+
}
|
|
608
|
+
else if (data.method === "readFile") {
|
|
609
|
+
return [2 /*return*/, this.sandboxSetup.fs.readFile(data.params[0])];
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
throw new Error("Method not supported");
|
|
613
|
+
}
|
|
614
|
+
});
|
|
615
|
+
}); }, this.iframeProtocol);
|
|
616
|
+
/**
|
|
617
|
+
* Parent-side fetch + persistent cache for immutable module URLs.
|
|
618
|
+
* The iframe's opaque origin has no storage, so it forwards these
|
|
619
|
+
* here (see immutable-fetch-protocol.ts for the allowlist).
|
|
620
|
+
*/
|
|
621
|
+
this.immutableFetchProtocol = new Protocol("immutable-fetch", function (data) { return __awaiter(_this, void 0, void 0, function () {
|
|
622
|
+
return __generator(this, function (_a) {
|
|
623
|
+
if (data.method !== "fetch") {
|
|
624
|
+
throw new Error("Method not supported");
|
|
625
|
+
}
|
|
626
|
+
// params[1] is an optional `sha384-…` integrity the caller pins
|
|
627
|
+
// for this URL (SDK files); the cache verifies against it.
|
|
628
|
+
return [2 /*return*/, handleImmutableFetch(data.params[0], data.params[1])];
|
|
629
|
+
});
|
|
630
|
+
}); }, this.iframeProtocol);
|
|
631
|
+
return [4 /*yield*/, this.computeInitConfig()];
|
|
632
|
+
case 1:
|
|
633
|
+
config = _a.sent();
|
|
634
|
+
babelPort = this.createBabelWorkerPort();
|
|
635
|
+
this.iframeProtocol.register(remotePort, config, babelPort);
|
|
636
|
+
return [2 /*return*/];
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
}); });
|
|
640
|
+
});
|
|
641
|
+
_this.unsubscribeChannelListener = _this.iframeProtocol.channelListen(function (mes) {
|
|
642
|
+
switch (mes.type) {
|
|
643
|
+
case "start": {
|
|
644
|
+
_this.errors = [];
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
case "status": {
|
|
648
|
+
_this.status = mes.status;
|
|
649
|
+
break;
|
|
650
|
+
}
|
|
651
|
+
case "action": {
|
|
652
|
+
if (mes.action === "show-error") {
|
|
653
|
+
_this.errors = __spreadArray(__spreadArray([], _this.errors, true), [extractErrorDetails(mes)], false);
|
|
654
|
+
}
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
case "done": {
|
|
658
|
+
_this.status = "done";
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
case "state": {
|
|
662
|
+
_this.bundlerState = mes.state;
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
if (options.experimental_enableServiceWorker) {
|
|
668
|
+
_this.serviceWorkerHandshake();
|
|
669
|
+
}
|
|
670
|
+
return _this;
|
|
671
|
+
}
|
|
672
|
+
SandpackRuntime.prototype.createBundlerURL = function () {
|
|
673
|
+
var _a;
|
|
674
|
+
var bundlerURL = this.options.bundlerURL || BUNDLER_URL;
|
|
675
|
+
// if it's a custom, skip the rest
|
|
676
|
+
if (this.options.bundlerURL) {
|
|
677
|
+
return bundlerURL;
|
|
678
|
+
}
|
|
679
|
+
if (this.options.teamId) {
|
|
680
|
+
bundlerURL =
|
|
681
|
+
bundlerURL.replace("https://", "https://" + this.options.teamId + "-") +
|
|
682
|
+
"?cache=".concat(Date.now());
|
|
683
|
+
}
|
|
684
|
+
if (this.options.experimental_enableServiceWorker) {
|
|
685
|
+
var suffixes = [];
|
|
686
|
+
suffixes.push(Math.random().toString(36).slice(4));
|
|
687
|
+
bundlerURL = bundlerURL.replace(SUFFIX_PLACEHOLDER, "-".concat((_a = this.options.experimental_stableServiceWorkerId) !== null && _a !== void 0 ? _a : suffixes.join("-")));
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
bundlerURL = bundlerURL.replace(SUFFIX_PLACEHOLDER, "");
|
|
691
|
+
}
|
|
692
|
+
return bundlerURL;
|
|
693
|
+
};
|
|
694
|
+
/**
|
|
695
|
+
* Creates (or recreates) the parent-owned Babel transpiler worker and returns
|
|
696
|
+
* the `MessagePort` to transfer into the iframe. The iframe can no longer run
|
|
697
|
+
* its own worker — without `allow-same-origin` it has an opaque origin, and a
|
|
698
|
+
* same-origin worker script won't load there — so transpilation happens in
|
|
699
|
+
* this worker on the parent's real origin. Per-transform traffic then flows
|
|
700
|
+
* iframe<->worker directly over the entangled ports; the parent doesn't relay.
|
|
701
|
+
*/
|
|
702
|
+
SandpackRuntime.prototype.createBabelWorkerPort = function () {
|
|
703
|
+
var _a;
|
|
704
|
+
var workerURL = this.options.babelWorkerURL;
|
|
705
|
+
if (!workerURL) {
|
|
706
|
+
console.warn("[SandpackRuntime] No `babelWorkerURL` configured — the bundler cannot transpile without a Babel worker.");
|
|
707
|
+
return undefined;
|
|
708
|
+
}
|
|
709
|
+
// A reload re-runs this handshake; terminate the previous worker first so
|
|
710
|
+
// we don't leak one per reload.
|
|
711
|
+
(_a = this.babelWorker) === null || _a === void 0 ? void 0 : _a.terminate();
|
|
712
|
+
// Classic (not module) worker: the bundled worker lazily loads its Babel
|
|
713
|
+
// plugin/preset chunks via importScripts(), which a `{ type: "module" }`
|
|
714
|
+
// worker forbids. The worker artifact is built with outputFormat "globalThis"
|
|
715
|
+
// to match (see sandpack-bundler's babelWorker Parcel target).
|
|
716
|
+
var worker = new Worker(workerURL);
|
|
717
|
+
this.babelWorker = worker;
|
|
718
|
+
var channel = new MessageChannel();
|
|
719
|
+
// Hand the worker one end; it binds its message bus to this port on receipt.
|
|
720
|
+
worker.postMessage({ type: "connect" }, [channel.port1]);
|
|
721
|
+
return channel.port2;
|
|
722
|
+
};
|
|
723
|
+
SandpackRuntime.prototype.serviceWorkerHandshake = function () {
|
|
724
|
+
var _this = this;
|
|
725
|
+
var channel = new MessageChannel();
|
|
726
|
+
var iframeContentWindow = this.iframe.contentWindow;
|
|
727
|
+
if (!iframeContentWindow) {
|
|
728
|
+
throw new Error("Could not get iframe contentWindow");
|
|
729
|
+
}
|
|
730
|
+
var port = channel.port1;
|
|
731
|
+
port.onmessage = function (evt) {
|
|
732
|
+
if (typeof evt.data === "object" && evt.data.$channel === CHANNEL_NAME) {
|
|
733
|
+
switch (evt.data.$type) {
|
|
734
|
+
case "preview/ready":
|
|
735
|
+
// no op for now
|
|
736
|
+
break;
|
|
737
|
+
case "preview/request":
|
|
738
|
+
_this.handleWorkerRequest(evt.data, port);
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
var sendMessage = function () {
|
|
744
|
+
var initMsg = {
|
|
745
|
+
$channel: CHANNEL_NAME,
|
|
746
|
+
$type: "preview/init",
|
|
747
|
+
};
|
|
748
|
+
iframeContentWindow.postMessage(initMsg, "*", [channel.port2]);
|
|
749
|
+
_this.iframe.removeEventListener("load", sendMessage);
|
|
750
|
+
};
|
|
751
|
+
this.iframe.addEventListener("load", sendMessage);
|
|
752
|
+
};
|
|
753
|
+
SandpackRuntime.prototype.handleWorkerRequest = function (request, port) {
|
|
754
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
755
|
+
var notFound, filepath_1, headers, body, modulesFromManager, match, extension, foundMimetype, responseMessage, err_1;
|
|
756
|
+
return __generator(this, function (_a) {
|
|
757
|
+
switch (_a.label) {
|
|
758
|
+
case 0:
|
|
759
|
+
notFound = function () {
|
|
760
|
+
var responseMessage = {
|
|
761
|
+
$channel: CHANNEL_NAME,
|
|
762
|
+
$type: "preview/response",
|
|
763
|
+
id: request.id,
|
|
764
|
+
headers: {
|
|
765
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
766
|
+
},
|
|
767
|
+
status: 404,
|
|
768
|
+
body: "File not found",
|
|
769
|
+
};
|
|
770
|
+
port.postMessage(responseMessage);
|
|
771
|
+
};
|
|
772
|
+
_a.label = 1;
|
|
773
|
+
case 1:
|
|
774
|
+
_a.trys.push([1, 7, , 8]);
|
|
775
|
+
filepath_1 = new URL(request.url, this.bundlerURL).pathname;
|
|
776
|
+
headers = {};
|
|
777
|
+
body = void 0;
|
|
778
|
+
return [4 /*yield*/, this.sandboxSetup.fs.exists(filepath_1)];
|
|
779
|
+
case 2:
|
|
780
|
+
if (!_a.sent()) return [3 /*break*/, 4];
|
|
781
|
+
return [4 /*yield*/, this.sandboxSetup.fs.readFile(filepath_1)];
|
|
782
|
+
case 3:
|
|
783
|
+
body = _a.sent();
|
|
784
|
+
return [3 /*break*/, 6];
|
|
785
|
+
case 4: return [4 /*yield*/, this.getTranspiledFiles()];
|
|
786
|
+
case 5:
|
|
787
|
+
modulesFromManager = _a.sent();
|
|
788
|
+
match = modulesFromManager.find(function (item) {
|
|
789
|
+
return item.path.endsWith(filepath_1);
|
|
790
|
+
});
|
|
791
|
+
if (match) {
|
|
792
|
+
body = match.code;
|
|
793
|
+
}
|
|
794
|
+
_a.label = 6;
|
|
795
|
+
case 6:
|
|
796
|
+
if (body === undefined) {
|
|
797
|
+
notFound();
|
|
798
|
+
return [2 /*return*/];
|
|
799
|
+
}
|
|
800
|
+
if (!headers["Content-Type"]) {
|
|
801
|
+
extension = getExtension(filepath_1);
|
|
802
|
+
foundMimetype = EXTENSIONS_MAP.get(extension);
|
|
803
|
+
if (foundMimetype) {
|
|
804
|
+
headers["Content-Type"] = foundMimetype;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
responseMessage = {
|
|
808
|
+
$channel: CHANNEL_NAME,
|
|
809
|
+
$type: "preview/response",
|
|
810
|
+
id: request.id,
|
|
811
|
+
headers: headers,
|
|
812
|
+
status: 200,
|
|
813
|
+
body: body,
|
|
814
|
+
};
|
|
815
|
+
port.postMessage(responseMessage);
|
|
816
|
+
return [3 /*break*/, 8];
|
|
817
|
+
case 7:
|
|
818
|
+
err_1 = _a.sent();
|
|
819
|
+
console.error(err_1);
|
|
820
|
+
notFound();
|
|
821
|
+
return [3 /*break*/, 8];
|
|
822
|
+
case 8: return [2 /*return*/];
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
});
|
|
826
|
+
};
|
|
827
|
+
SandpackRuntime.prototype.setLocationURLIntoIFrame = function () {
|
|
828
|
+
var _a;
|
|
829
|
+
var urlSource = this.options.startRoute
|
|
830
|
+
? new URL(this.options.startRoute, this.bundlerURL).toString()
|
|
831
|
+
: this.bundlerURL;
|
|
832
|
+
(_a = this.iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.location.replace(urlSource);
|
|
833
|
+
this.iframe.src = urlSource;
|
|
834
|
+
};
|
|
835
|
+
SandpackRuntime.prototype.destroy = function () {
|
|
836
|
+
var _a, _b, _c, _d;
|
|
837
|
+
this.unsubscribeChannelListener();
|
|
838
|
+
this.unsubscribeGlobalListener();
|
|
839
|
+
(_a = this.unsubscribeFsWatcher) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
840
|
+
(_b = this.fileResolverProtocol) === null || _b === void 0 ? void 0 : _b.dispose();
|
|
841
|
+
(_c = this.immutableFetchProtocol) === null || _c === void 0 ? void 0 : _c.dispose();
|
|
842
|
+
(_d = this.babelWorker) === null || _d === void 0 ? void 0 : _d.terminate();
|
|
843
|
+
this.iframeProtocol.cleanup();
|
|
844
|
+
};
|
|
845
|
+
SandpackRuntime.prototype.updateOptions = function (options) {
|
|
846
|
+
if (!dequal(this.options, options)) {
|
|
847
|
+
this.options = options;
|
|
848
|
+
this.updateSandbox();
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
/**
|
|
852
|
+
* Updates the local sandbox state. The bundler watches the shared filesystem
|
|
853
|
+
* itself, so there is nothing to push to the iframe here — a file mutation
|
|
854
|
+
* triggers a rebuild on the bundler side without a `compile` message. A
|
|
855
|
+
* template/environment change is handled by re-registering the client (see
|
|
856
|
+
* `useClient`'s `watchFileChanges` effect), which re-runs `computeInitConfig`.
|
|
857
|
+
*/
|
|
858
|
+
SandpackRuntime.prototype.updateSandbox = function (sandboxSetup) {
|
|
859
|
+
if (sandboxSetup === void 0) { sandboxSetup = this.sandboxSetup; }
|
|
860
|
+
this.sandboxSetup = __assign(__assign({}, this.sandboxSetup), sandboxSetup);
|
|
861
|
+
};
|
|
862
|
+
/**
|
|
863
|
+
* Computes the bundler's bootstrap config. Delivered once via the
|
|
864
|
+
* `register-frame` handshake (see the `initialized` handler) instead of a
|
|
865
|
+
* `compile` message, since the bundler now self-watches the filesystem.
|
|
866
|
+
*/
|
|
867
|
+
SandpackRuntime.prototype.computeInitConfig = function () {
|
|
868
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
869
|
+
var fs, packageJSON, _a, _b, e_1, fileNames, fileNameMap;
|
|
870
|
+
var _c;
|
|
871
|
+
return __generator(this, function (_d) {
|
|
872
|
+
switch (_d.label) {
|
|
873
|
+
case 0:
|
|
874
|
+
fs = this.sandboxSetup.fs;
|
|
875
|
+
packageJSON = JSON.parse(createPackageJSON(this.sandboxSetup.dependencies, this.sandboxSetup.devDependencies, this.sandboxSetup.entry));
|
|
876
|
+
_d.label = 1;
|
|
877
|
+
case 1:
|
|
878
|
+
_d.trys.push([1, 5, , 6]);
|
|
879
|
+
return [4 /*yield*/, fs.exists("/package.json")];
|
|
880
|
+
case 2:
|
|
881
|
+
if (!_d.sent()) return [3 /*break*/, 4];
|
|
882
|
+
_b = (_a = JSON).parse;
|
|
883
|
+
return [4 /*yield*/, fs.readFile("/package.json")];
|
|
884
|
+
case 3:
|
|
885
|
+
packageJSON = _b.apply(_a, [_d.sent()]);
|
|
886
|
+
_d.label = 4;
|
|
887
|
+
case 4: return [3 /*break*/, 6];
|
|
888
|
+
case 5:
|
|
889
|
+
e_1 = _d.sent();
|
|
890
|
+
console.error(createError("could not parse package.json file: " + e_1.message));
|
|
891
|
+
return [3 /*break*/, 6];
|
|
892
|
+
case 6: return [4 /*yield*/, fs.list()];
|
|
893
|
+
case 7:
|
|
894
|
+
fileNames = _d.sent();
|
|
895
|
+
fileNameMap = Object.fromEntries(fileNames.map(function (p) { return [p, true]; }));
|
|
896
|
+
return [2 /*return*/, {
|
|
897
|
+
template: this.sandboxSetup.template || getTemplate(packageJSON, fileNameMap),
|
|
898
|
+
logLevel: (_c = this.options.logLevel) !== null && _c !== void 0 ? _c : SandpackLogLevel.Info,
|
|
899
|
+
// Host-pinned SDK integrity hashes (SDK_PACKAGING_SPEC §5.2), forwarded
|
|
900
|
+
// verbatim into register-frame for the bundler to verify against. The host
|
|
901
|
+
// sets it via client options; absent → the bundler skips verification.
|
|
902
|
+
sdkIntegrity: this.options.sdkIntegrity,
|
|
903
|
+
// The §5.2 dirty set, forwarded verbatim into register-frame so the bundler
|
|
904
|
+
// skips seeding artifacts for paths edited in a previous session. Absent ⇒
|
|
905
|
+
// nothing dirty.
|
|
906
|
+
dirtyPaths: this.options.dirtyPaths,
|
|
907
|
+
// R3-49b batch-hydration snapshot, forwarded verbatim into register-frame so
|
|
908
|
+
// the bundler hydrates its read caches before the first compile. Absent ⇒
|
|
909
|
+
// reads cross the Port as before.
|
|
910
|
+
fsSnapshot: this.options.fsSnapshot,
|
|
911
|
+
// The chrome region this frame occupies (R3-114), forwarded verbatim into
|
|
912
|
+
// register-frame so the bundler surfaces it on the runtime globalThis for the
|
|
913
|
+
// SDK's getRegion(). Absent ⇒ the app reads no region.
|
|
914
|
+
region: this.options.region,
|
|
915
|
+
// BOOT_SCAFFOLDING_SPEC §3 — the resolved root package.json, forwarded
|
|
916
|
+
// out-of-band so the bundler reads it from config instead of the FS and no
|
|
917
|
+
// synthesized `package.json` is written into the CoW writable layer. This
|
|
918
|
+
// is the same object `getTemplate` consumes above (the repo's file when
|
|
919
|
+
// present, else the setup-derived default).
|
|
920
|
+
packageJSON: packageJSON,
|
|
921
|
+
}];
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
};
|
|
926
|
+
/**
|
|
927
|
+
* Relays the set of changed file paths to the bundler so it can re-bundle.
|
|
928
|
+
* The bundler can't observe parent-side writes to the shared filesystem on
|
|
929
|
+
* its own: zenfs's `Port` backend doesn't forward watch events across the
|
|
930
|
+
* iframe boundary. This lightweight signal replaces the old per-change
|
|
931
|
+
* `compile` message — it carries only paths, not template/options/config.
|
|
932
|
+
*/
|
|
933
|
+
SandpackRuntime.prototype.notifyFilesChanged = function (paths) {
|
|
934
|
+
if (!paths.length) {
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
this.dispatch({ type: "fs-change", paths: paths });
|
|
938
|
+
};
|
|
939
|
+
SandpackRuntime.prototype.dispatch = function (message) {
|
|
940
|
+
/**
|
|
941
|
+
* Intercept "refresh" dispatch: this will make sure
|
|
942
|
+
* that the iframe is still in the location it's supposed to be.
|
|
943
|
+
* External links inside the iframe will change the location and
|
|
944
|
+
* prevent the user from navigating back.
|
|
945
|
+
*/
|
|
946
|
+
if (message.type === "refresh") {
|
|
947
|
+
this.setLocationURLIntoIFrame();
|
|
948
|
+
if (this.options.experimental_enableServiceWorker) {
|
|
949
|
+
this.serviceWorkerHandshake();
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
this.iframeProtocol.dispatch(message);
|
|
953
|
+
};
|
|
954
|
+
SandpackRuntime.prototype.listen = function (listener) {
|
|
955
|
+
return this.iframeProtocol.channelListen(listener);
|
|
956
|
+
};
|
|
957
|
+
/**
|
|
958
|
+
* Get the URL of the contents of the current sandbox
|
|
959
|
+
*/
|
|
960
|
+
SandpackRuntime.prototype.getCodeSandboxURL = function () {
|
|
961
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
962
|
+
var snapshot, paramFiles, res, sandboxId;
|
|
963
|
+
return __generator(this, function (_a) {
|
|
964
|
+
switch (_a.label) {
|
|
965
|
+
case 0: return [4 /*yield*/, snapshotFS(this.sandboxSetup.fs)];
|
|
966
|
+
case 1:
|
|
967
|
+
snapshot = _a.sent();
|
|
968
|
+
paramFiles = Object.keys(snapshot).reduce(function (prev, next) {
|
|
969
|
+
var _a;
|
|
970
|
+
return (__assign(__assign({}, prev), (_a = {}, _a[next.replace("/", "")] = {
|
|
971
|
+
content: snapshot[next],
|
|
972
|
+
isBinary: false,
|
|
973
|
+
}, _a)));
|
|
974
|
+
}, {});
|
|
975
|
+
return [4 /*yield*/, fetch("https://codesandbox.io/api/v1/sandboxes/define?json=1", {
|
|
976
|
+
method: "POST",
|
|
977
|
+
body: JSON.stringify({ files: paramFiles }),
|
|
978
|
+
headers: {
|
|
979
|
+
Accept: "application/json",
|
|
980
|
+
"Content-Type": "application/json",
|
|
981
|
+
},
|
|
982
|
+
})];
|
|
983
|
+
case 2:
|
|
984
|
+
res = _a.sent();
|
|
985
|
+
return [4 /*yield*/, res.json()];
|
|
986
|
+
case 3:
|
|
987
|
+
sandboxId = (_a.sent()).sandbox_id;
|
|
988
|
+
return [2 /*return*/, {
|
|
989
|
+
sandboxId: sandboxId,
|
|
990
|
+
editorUrl: "https://codesandbox.io/s/".concat(sandboxId),
|
|
991
|
+
embedUrl: "https://codesandbox.io/embed/".concat(sandboxId),
|
|
992
|
+
}];
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
});
|
|
996
|
+
};
|
|
997
|
+
SandpackRuntime.prototype.initializeElement = function () {
|
|
998
|
+
this.iframe.style.border = "0";
|
|
999
|
+
this.iframe.style.width = this.options.width || "100%";
|
|
1000
|
+
this.iframe.style.height = this.options.height || "100%";
|
|
1001
|
+
this.iframe.style.overflow = "hidden";
|
|
1002
|
+
nullthrows(this.element.parentNode, "The given iframe does not have a parent.");
|
|
1003
|
+
this.element.parentNode.replaceChild(this.iframe, this.element);
|
|
1004
|
+
};
|
|
1005
|
+
return SandpackRuntime;
|
|
1006
|
+
}(SandpackClient));
|
|
1007
|
+
/**
|
|
1008
|
+
* Read every tracked file from the filesystem into a plain `{ path: code }`
|
|
1009
|
+
* snapshot. Used wherever the bundler protocol still expects a flat module
|
|
1010
|
+
* map (the iframe `compile` payload, Open-in-CodeSandbox, etc.).
|
|
1011
|
+
*/
|
|
1012
|
+
function snapshotFS(fs) {
|
|
1013
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1014
|
+
var paths, out;
|
|
1015
|
+
var _this = this;
|
|
1016
|
+
return __generator(this, function (_a) {
|
|
1017
|
+
switch (_a.label) {
|
|
1018
|
+
case 0: return [4 /*yield*/, fs.list()];
|
|
1019
|
+
case 1:
|
|
1020
|
+
paths = _a.sent();
|
|
1021
|
+
out = {};
|
|
1022
|
+
return [4 /*yield*/, Promise.all(paths.map(function (path) { return __awaiter(_this, void 0, void 0, function () {
|
|
1023
|
+
var _a, _b;
|
|
1024
|
+
return __generator(this, function (_c) {
|
|
1025
|
+
switch (_c.label) {
|
|
1026
|
+
case 0:
|
|
1027
|
+
_a = out;
|
|
1028
|
+
_b = path;
|
|
1029
|
+
return [4 /*yield*/, fs.readFile(path)];
|
|
1030
|
+
case 1:
|
|
1031
|
+
_a[_b] = _c.sent();
|
|
1032
|
+
return [2 /*return*/];
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
}); }))];
|
|
1036
|
+
case 2:
|
|
1037
|
+
_a.sent();
|
|
1038
|
+
return [2 /*return*/, out];
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
export { SandpackRuntime };
|