mates-fullstack 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -0
- package/dist/arctic-auth.d.ts +101 -0
- package/dist/arctic-auth.d.ts.map +1 -0
- package/dist/arctic-auth.js +538 -0
- package/dist/arctic-auth.js.map +1 -0
- package/dist/asset-manifest.d.ts +14 -0
- package/dist/asset-manifest.d.ts.map +1 -0
- package/dist/asset-manifest.js +102 -0
- package/dist/asset-manifest.js.map +1 -0
- package/dist/browser.d.ts +18 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +25 -0
- package/dist/browser.js.map +1 -0
- package/dist/build-esbuild.d.ts +29 -0
- package/dist/build-esbuild.d.ts.map +1 -0
- package/dist/build-esbuild.js +699 -0
- package/dist/build-esbuild.js.map +1 -0
- package/dist/build-prod.d.ts +126 -0
- package/dist/build-prod.d.ts.map +1 -0
- package/dist/build-prod.js +1014 -0
- package/dist/build-prod.js.map +1 -0
- package/dist/cli-new.d.ts +14 -0
- package/dist/cli-new.d.ts.map +1 -0
- package/dist/cli-new.js +637 -0
- package/dist/cli-new.js.map +1 -0
- package/dist/client.d.ts +43 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +130 -0
- package/dist/client.js.map +1 -0
- package/dist/cors.d.ts +16 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +60 -0
- package/dist/cors.js.map +1 -0
- package/dist/ctx.d.ts +78 -0
- package/dist/ctx.d.ts.map +1 -0
- package/dist/ctx.js +280 -0
- package/dist/ctx.js.map +1 -0
- package/dist/dev-watcher.d.ts +23 -0
- package/dist/dev-watcher.d.ts.map +1 -0
- package/dist/dev-watcher.js +136 -0
- package/dist/dev-watcher.js.map +1 -0
- package/dist/docs-generator.d.ts +69 -0
- package/dist/docs-generator.d.ts.map +1 -0
- package/dist/docs-generator.js +557 -0
- package/dist/docs-generator.js.map +1 -0
- package/dist/docs-page.d.ts +20 -0
- package/dist/docs-page.d.ts.map +1 -0
- package/dist/docs-page.js +1152 -0
- package/dist/docs-page.js.map +1 -0
- package/dist/download.d.ts +78 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/download.js +202 -0
- package/dist/download.js.map +1 -0
- package/dist/env-loader.d.ts +76 -0
- package/dist/env-loader.d.ts.map +1 -0
- package/dist/env-loader.js +213 -0
- package/dist/env-loader.js.map +1 -0
- package/dist/errors.d.ts +146 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +386 -0
- package/dist/errors.js.map +1 -0
- package/dist/head.d.ts +31 -0
- package/dist/head.d.ts.map +1 -0
- package/dist/head.js +245 -0
- package/dist/head.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-prefixes.d.ts +16 -0
- package/dist/internal-prefixes.d.ts.map +1 -0
- package/dist/internal-prefixes.js +16 -0
- package/dist/internal-prefixes.js.map +1 -0
- package/dist/internal.d.ts +25 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +25 -0
- package/dist/internal.js.map +1 -0
- package/dist/jwt.d.ts +166 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +261 -0
- package/dist/jwt.js.map +1 -0
- package/dist/log.d.ts +44 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +66 -0
- package/dist/log.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +138 -0
- package/dist/logger.js.map +1 -0
- package/dist/main-runner.d.ts +59 -0
- package/dist/main-runner.d.ts.map +1 -0
- package/dist/main-runner.js +157 -0
- package/dist/main-runner.js.map +1 -0
- package/dist/mates-auth.d.ts +82 -0
- package/dist/mates-auth.d.ts.map +1 -0
- package/dist/mates-auth.js +323 -0
- package/dist/mates-auth.js.map +1 -0
- package/dist/middleware.d.ts +30 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +67 -0
- package/dist/middleware.js.map +1 -0
- package/dist/project-resolver.d.ts +102 -0
- package/dist/project-resolver.d.ts.map +1 -0
- package/dist/project-resolver.js +271 -0
- package/dist/project-resolver.js.map +1 -0
- package/dist/rate-limit.d.ts +37 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +109 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/redirect.d.ts +84 -0
- package/dist/redirect.d.ts.map +1 -0
- package/dist/redirect.js +105 -0
- package/dist/redirect.js.map +1 -0
- package/dist/renderer.d.ts +91 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +630 -0
- package/dist/renderer.js.map +1 -0
- package/dist/request-logger.d.ts +12 -0
- package/dist/request-logger.d.ts.map +1 -0
- package/dist/request-logger.js +55 -0
- package/dist/request-logger.js.map +1 -0
- package/dist/rest.d.ts +25 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +93 -0
- package/dist/rest.js.map +1 -0
- package/dist/router.d.ts +71 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +222 -0
- package/dist/router.js.map +1 -0
- package/dist/rpc-registry.d.ts +84 -0
- package/dist/rpc-registry.d.ts.map +1 -0
- package/dist/rpc-registry.js +271 -0
- package/dist/rpc-registry.js.map +1 -0
- package/dist/rpc-runner.d.ts +82 -0
- package/dist/rpc-runner.d.ts.map +1 -0
- package/dist/rpc-runner.js +564 -0
- package/dist/rpc-runner.js.map +1 -0
- package/dist/sanitize.d.ts +61 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +193 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/security-headers.d.ts +114 -0
- package/dist/security-headers.d.ts.map +1 -0
- package/dist/security-headers.js +121 -0
- package/dist/security-headers.js.map +1 -0
- package/dist/server-fn.d.ts +323 -0
- package/dist/server-fn.d.ts.map +1 -0
- package/dist/server-fn.js +373 -0
- package/dist/server-fn.js.map +1 -0
- package/dist/server-public.d.ts +13 -0
- package/dist/server-public.d.ts.map +1 -0
- package/dist/server-public.js +12 -0
- package/dist/server-public.js.map +1 -0
- package/dist/server-timeout.d.ts +38 -0
- package/dist/server-timeout.d.ts.map +1 -0
- package/dist/server-timeout.js +46 -0
- package/dist/server-timeout.js.map +1 -0
- package/dist/server.d.ts +100 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1218 -0
- package/dist/server.js.map +1 -0
- package/dist/socket-router.d.ts +153 -0
- package/dist/socket-router.d.ts.map +1 -0
- package/dist/socket-router.js +612 -0
- package/dist/socket-router.js.map +1 -0
- package/dist/sso.d.ts +90 -0
- package/dist/sso.d.ts.map +1 -0
- package/dist/sso.js +261 -0
- package/dist/sso.js.map +1 -0
- package/dist/ssr-context.d.ts +49 -0
- package/dist/ssr-context.d.ts.map +1 -0
- package/dist/ssr-context.js +85 -0
- package/dist/ssr-context.js.map +1 -0
- package/dist/ssr-globals.d.ts +32 -0
- package/dist/ssr-globals.d.ts.map +1 -0
- package/dist/ssr-globals.js +1010 -0
- package/dist/ssr-globals.js.map +1 -0
- package/dist/ssr-template.d.ts +73 -0
- package/dist/ssr-template.d.ts.map +1 -0
- package/dist/ssr-template.js +507 -0
- package/dist/ssr-template.js.map +1 -0
- package/dist/stack-mapper.d.ts +25 -0
- package/dist/stack-mapper.d.ts.map +1 -0
- package/dist/stack-mapper.js +139 -0
- package/dist/stack-mapper.js.map +1 -0
- package/dist/stream.d.ts +89 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +299 -0
- package/dist/stream.js.map +1 -0
- package/dist/upload.d.ts +69 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +110 -0
- package/dist/upload.js.map +1 -0
- package/dist/validate.d.ts +58 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +89 -0
- package/dist/validate.js.map +1 -0
- package/dist/verify-package.d.ts +3 -0
- package/dist/verify-package.d.ts.map +1 -0
- package/dist/verify-package.js +128 -0
- package/dist/verify-package.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { transform } from "esbuild";
|
|
4
|
+
import { BROWSER_ERRORS_JS } from "./errors.js";
|
|
5
|
+
import { CRASH_OVERLAY_MODULE, DOWNLOAD_MODULE, EMPTY_STYLE_MODULE, ERRORS_MODULE, INTERNAL_ASSET_PREFIX, INTERNAL_PKG_PREFIX, INTERNAL_SRC_PREFIX, NAV_MODULE, RPC_CLIENT_MODULE, STACK_MAP_MODULE, STREAM_MODULE, } from "./internal-prefixes.js";
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Cache
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const _transformCache = new Map();
|
|
10
|
+
export function clearTransformCache() {
|
|
11
|
+
_transformCache.clear();
|
|
12
|
+
}
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Reserved RPC export names (must not be stubbed)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const RESERVED_NAMES = new Set([
|
|
17
|
+
"default",
|
|
18
|
+
"loader",
|
|
19
|
+
"meta",
|
|
20
|
+
"layout",
|
|
21
|
+
"staticPaths",
|
|
22
|
+
"onConnect",
|
|
23
|
+
"onDisconnect",
|
|
24
|
+
"then",
|
|
25
|
+
"catch",
|
|
26
|
+
"finally",
|
|
27
|
+
]);
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// buildDefines
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
export function buildDefines(publicEnv) {
|
|
32
|
+
const defines = {
|
|
33
|
+
"import.meta.env.NODE_ENV": '"development"',
|
|
34
|
+
"process.env.NODE_ENV": '"development"',
|
|
35
|
+
};
|
|
36
|
+
for (const [key, value] of Object.entries(publicEnv)) {
|
|
37
|
+
defines[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
38
|
+
}
|
|
39
|
+
return defines;
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// RPC stub extraction
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
export function extractRpcStub(source, filePath, apiDir) {
|
|
45
|
+
const exportedNames = [];
|
|
46
|
+
// export async function NAME(
|
|
47
|
+
const funcPattern = /^export\s+async\s+function\s+(\w+)\s*\(/gm;
|
|
48
|
+
let m;
|
|
49
|
+
while ((m = funcPattern.exec(source)) !== null) {
|
|
50
|
+
exportedNames.push(m[1]);
|
|
51
|
+
}
|
|
52
|
+
// export const NAME = async
|
|
53
|
+
const constPattern = /^export\s+const\s+(\w+)\s*=\s*async\b/gm;
|
|
54
|
+
while ((m = constPattern.exec(source)) !== null) {
|
|
55
|
+
exportedNames.push(m[1]);
|
|
56
|
+
}
|
|
57
|
+
const unique = [...new Set(exportedNames)].filter((name) => !RESERVED_NAMES.has(name));
|
|
58
|
+
// Derive relative module path for URL construction: relative from apiDir
|
|
59
|
+
// e.g. apiDir = /project/server/api, filePath = /project/server/api/users.ts
|
|
60
|
+
// → moduleRelPath = "users"
|
|
61
|
+
const relFromApi = path.relative(apiDir, filePath);
|
|
62
|
+
let moduleRelPath = relFromApi
|
|
63
|
+
.replace(/\.(ts|js|tsx|jsx)$/, "")
|
|
64
|
+
.split(path.sep)
|
|
65
|
+
.join("/");
|
|
66
|
+
if (moduleRelPath.endsWith("/index"))
|
|
67
|
+
moduleRelPath = moduleRelPath.slice(0, -6);
|
|
68
|
+
if (moduleRelPath === "index")
|
|
69
|
+
moduleRelPath = "";
|
|
70
|
+
const lines = [
|
|
71
|
+
`// Generated RPC stub for ${filePath}`,
|
|
72
|
+
`import { __rpcCall } from ${JSON.stringify(RPC_CLIENT_MODULE)};`,
|
|
73
|
+
"",
|
|
74
|
+
];
|
|
75
|
+
for (const name of unique) {
|
|
76
|
+
const rpcUrl = moduleRelPath
|
|
77
|
+
? `/api/${moduleRelPath}/${name}`
|
|
78
|
+
: `/api/${name}`;
|
|
79
|
+
lines.push(`export async function ${name}(payload = {}) {`, ` return __rpcCall(${JSON.stringify(rpcUrl)}, payload);`, `}`, "");
|
|
80
|
+
}
|
|
81
|
+
return lines.join("\n");
|
|
82
|
+
}
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// transformFile
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
function loaderForExtension(ext) {
|
|
87
|
+
switch (ext) {
|
|
88
|
+
case ".ts":
|
|
89
|
+
return "ts";
|
|
90
|
+
case ".tsx":
|
|
91
|
+
return "tsx";
|
|
92
|
+
case ".js":
|
|
93
|
+
case ".mjs":
|
|
94
|
+
return "js";
|
|
95
|
+
case ".jsx":
|
|
96
|
+
return "jsx";
|
|
97
|
+
default:
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export async function transformFile(filePath, projectRoot, apiDir, publicEnv, sourceUrl) {
|
|
102
|
+
// File existence check
|
|
103
|
+
let stat;
|
|
104
|
+
try {
|
|
105
|
+
stat = fs.statSync(filePath);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const mtime = stat.mtimeMs;
|
|
111
|
+
// If this file lives inside the apiDir, return a generated RPC stub instead
|
|
112
|
+
// of transforming the real server-only source.
|
|
113
|
+
if (apiDir) {
|
|
114
|
+
const normalApi = path.resolve(apiDir);
|
|
115
|
+
const normalFile = path.resolve(filePath);
|
|
116
|
+
if (normalFile.startsWith(normalApi + path.sep) ||
|
|
117
|
+
normalFile === normalApi) {
|
|
118
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
119
|
+
const stub = extractRpcStub(source, filePath, normalApi);
|
|
120
|
+
return { code: stub };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Check cache
|
|
124
|
+
const cacheKey = `${filePath}::${sourceUrl ?? ""}`;
|
|
125
|
+
const cached = _transformCache.get(cacheKey);
|
|
126
|
+
if (cached && cached.mtime === mtime) {
|
|
127
|
+
return { code: cached.code };
|
|
128
|
+
}
|
|
129
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
130
|
+
// ── Stylesheet compatibility shim ───────────────────────────────────────
|
|
131
|
+
// CSS is bundled once into dist/assets/styles*.css and linked from <head>.
|
|
132
|
+
// If an old transformed module still requests a CSS file as JS, return a
|
|
133
|
+
// harmless no-op module instead of injecting styles from JavaScript.
|
|
134
|
+
if (ext === ".css") {
|
|
135
|
+
const code = "export default {};\n";
|
|
136
|
+
_transformCache.set(`${filePath}::${sourceUrl ?? ""}`, { mtime, code });
|
|
137
|
+
return { code };
|
|
138
|
+
}
|
|
139
|
+
const loader = loaderForExtension(ext);
|
|
140
|
+
if (!loader) {
|
|
141
|
+
// Unknown extension — serve as-is (plain text / JS passthrough)
|
|
142
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
143
|
+
return { code: raw };
|
|
144
|
+
}
|
|
145
|
+
let source;
|
|
146
|
+
try {
|
|
147
|
+
source = fs.readFileSync(filePath, "utf-8");
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const debugSource = sourceUrl ??
|
|
154
|
+
`/${path.relative(projectRoot, filePath).split(path.sep).join("/")}`;
|
|
155
|
+
const result = await transform(source, {
|
|
156
|
+
loader,
|
|
157
|
+
sourcemap: "inline",
|
|
158
|
+
sourcefile: debugSource,
|
|
159
|
+
target: "es2020",
|
|
160
|
+
format: "esm",
|
|
161
|
+
define: buildDefines(publicEnv),
|
|
162
|
+
sourcesContent: true,
|
|
163
|
+
});
|
|
164
|
+
const code = `${result.code}\n//# sourceURL=${debugSource}`;
|
|
165
|
+
_transformCache.set(cacheKey, { mtime, code });
|
|
166
|
+
return { code };
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
170
|
+
// Return a browser-safe error module rather than throwing
|
|
171
|
+
const errorModule = `export default null;\n` +
|
|
172
|
+
`console.error(${JSON.stringify(`[mates] transform error in ${filePath}: ${message}`)});\n` +
|
|
173
|
+
`//# sourceURL=${sourceUrl ?? filePath}\n`;
|
|
174
|
+
return { code: errorModule };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Dev no-bundle module serving
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
const CODE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".json"];
|
|
181
|
+
const STYLE_EXT_RE = /\.css$/i;
|
|
182
|
+
const ASSET_EXT_RE = /\.(png|jpe?g|gif|webp|avif|ico|bmp|tiff|svg|woff2?|ttf|otf|eot|mp4|webm|ogg|mov|avi|mkv|mp3|wav|flac|aac|m4a|opus|pdf|docx?|xlsx?|pptx?|txt|csv|glb|gltf|obj|fbx|wasm|json5|geojson|toml|ya?ml|zip|tar|gz)$/i;
|
|
183
|
+
/**
|
|
184
|
+
* Transform one source file for no-bundle dev mode.
|
|
185
|
+
*
|
|
186
|
+
* Unlike `transformFile()`, this rewrites ESM specifiers so the browser can load
|
|
187
|
+
* TypeScript and package files directly from the dev server. Stylesheets are
|
|
188
|
+
* bundled separately into one linked CSS file; CSS imports are rewritten to a
|
|
189
|
+
* no-op compatibility module.
|
|
190
|
+
*/
|
|
191
|
+
export async function transformDevModule(filePath, options) {
|
|
192
|
+
const transformed = await transformFile(filePath, options.projectRoot, options.apiDir, options.publicEnv, options.sourceUrl);
|
|
193
|
+
if (!transformed)
|
|
194
|
+
return null;
|
|
195
|
+
const sourceUrl = options.sourceUrl ?? filePath;
|
|
196
|
+
const code = injectDevHmrPrelude(appendComponentHmrRegistration(rewriteImportSpecifiers(transformed.code, filePath, options), sourceUrl), sourceUrl);
|
|
197
|
+
return { ...transformed, code };
|
|
198
|
+
}
|
|
199
|
+
function injectDevHmrPrelude(code, sourceUrl) {
|
|
200
|
+
return (`if (import.meta && window.__mates_hmr) import.meta.hot = window.__mates_hmr.createHotContext(${JSON.stringify(sourceUrl)});\n` +
|
|
201
|
+
code);
|
|
202
|
+
}
|
|
203
|
+
function appendComponentHmrRegistration(code, sourceUrl) {
|
|
204
|
+
const exports = extractComponentExportBindings(code);
|
|
205
|
+
if (exports.length === 0)
|
|
206
|
+
return code;
|
|
207
|
+
const entries = exports
|
|
208
|
+
.map(({ exported, local }) => `${JSON.stringify(exported)}: typeof ${local} === "function" ? ${local} : null`)
|
|
209
|
+
.join(",");
|
|
210
|
+
return `${code}\n;(() => {\n const __mates_exports = { ${entries} };\n if (window.__mates_hmr) {\n for (const [__name, __value] of Object.entries(__mates_exports)) {\n if (typeof __value !== "function") continue;\n const __file = ${JSON.stringify(sourceUrl)};\n const __id = __file + "::" + __name;\n try { Object.defineProperty(__value, "__mates_hmr_id", { value: __id, configurable: true }); } catch {}\n try { Object.defineProperty(__value, "__mates_hmr_file", { value: __file, configurable: true }); } catch {}\n try { Object.defineProperty(__value, "__mates_hmr_export", { value: __name, configurable: true }); } catch {}\n window.__mates_hmr.registerComponent(__id, __value, { file: __file, exportName: __name });\n }\n if (import.meta.hot) import.meta.hot.accept((mod) => window.__mates_hmr.updateModule(${JSON.stringify(sourceUrl)}, mod));\n }\n})();\n`;
|
|
211
|
+
}
|
|
212
|
+
function extractComponentExportBindings(code) {
|
|
213
|
+
const bindings = [];
|
|
214
|
+
const seen = new Set();
|
|
215
|
+
const add = (exported, local) => {
|
|
216
|
+
if (seen.has(exported))
|
|
217
|
+
return;
|
|
218
|
+
// Heuristic: components are PascalCase named exports or default exports.
|
|
219
|
+
if (exported !== "default" && !/^[A-Z]/.test(exported))
|
|
220
|
+
return;
|
|
221
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(local))
|
|
222
|
+
return;
|
|
223
|
+
seen.add(exported);
|
|
224
|
+
bindings.push({ exported, local });
|
|
225
|
+
};
|
|
226
|
+
const exportBlockRe = /export\s*\{([^}]+)\}/g;
|
|
227
|
+
let match;
|
|
228
|
+
while ((match = exportBlockRe.exec(code)) !== null) {
|
|
229
|
+
for (const raw of match[1].split(",")) {
|
|
230
|
+
const part = raw.trim();
|
|
231
|
+
if (!part)
|
|
232
|
+
continue;
|
|
233
|
+
const alias = part.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*|default)$/);
|
|
234
|
+
if (alias)
|
|
235
|
+
add(alias[2], alias[1]);
|
|
236
|
+
else
|
|
237
|
+
add(part, part);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const defaultRe = /export\s+default\s+([A-Za-z_$][\w$]*)/g;
|
|
241
|
+
while ((match = defaultRe.exec(code)) !== null)
|
|
242
|
+
add("default", match[1]);
|
|
243
|
+
return bindings;
|
|
244
|
+
}
|
|
245
|
+
function rewriteImportSpecifiers(code, filePath, options) {
|
|
246
|
+
const rewrite = (spec) => resolveDevSpecifier(spec, filePath, options);
|
|
247
|
+
// Helper: check if a resolved specifier is an asset URL that should become
|
|
248
|
+
// a const declaration instead of a live ESM import.
|
|
249
|
+
function isAssetResult(spec) {
|
|
250
|
+
const result = rewrite(spec);
|
|
251
|
+
if (!result.startsWith(INTERNAL_ASSET_PREFIX + "/"))
|
|
252
|
+
return null;
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
// Step 1: Replace default import statements for assets with const declarations.
|
|
256
|
+
// import s from "./s.svg" → const s = "/_asset/client/s.svg"
|
|
257
|
+
code = code.replace(/^import\s+([A-Za-z_$][\w$]*)\s+from\s*["']([^"']+)["'];?$/gm, (_m, binding, spec) => {
|
|
258
|
+
const assetUrl = isAssetResult(spec);
|
|
259
|
+
if (!assetUrl)
|
|
260
|
+
return _m;
|
|
261
|
+
return `const ${binding} = ${JSON.stringify(assetUrl)};`;
|
|
262
|
+
});
|
|
263
|
+
// Step 2: Replace namespace import statements for assets with const declarations.
|
|
264
|
+
// import * as s from "./s.svg" → const s = "/_asset/client/s.svg"
|
|
265
|
+
code = code.replace(/^import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["']([^"']+)["'];?$/gm, (_m, binding, spec) => {
|
|
266
|
+
const assetUrl = isAssetResult(spec);
|
|
267
|
+
if (!assetUrl)
|
|
268
|
+
return _m;
|
|
269
|
+
// Treat namespace import same as default for single-file assets.
|
|
270
|
+
return `const ${binding} = ${JSON.stringify(assetUrl)};`;
|
|
271
|
+
});
|
|
272
|
+
// Step 3: Rewrite remaining import/export/from specifiers that are not
|
|
273
|
+
// asset imports (those were already handled above).
|
|
274
|
+
code = code
|
|
275
|
+
.replace(/(\bfrom\s*["'])([^"']+)(["'])/g, (_m, a, spec, b) => {
|
|
276
|
+
return `${a}${rewrite(spec)}${b}`;
|
|
277
|
+
})
|
|
278
|
+
.replace(/(\bimport\s*["'])([^"']+)(["'])/g, (_m, a, spec, b) => {
|
|
279
|
+
return `${a}${rewrite(spec)}${b}`;
|
|
280
|
+
})
|
|
281
|
+
.replace(/(\bimport\s*\(\s*["'])([^"']+)(["']\s*\))/g, (_m, a, spec, b) => `${a}${rewrite(spec)}${b}`);
|
|
282
|
+
return code;
|
|
283
|
+
}
|
|
284
|
+
function resolveDevSpecifier(spec, importer, options) {
|
|
285
|
+
if (spec.startsWith("/") ||
|
|
286
|
+
spec.startsWith("http://") ||
|
|
287
|
+
spec.startsWith("https://") ||
|
|
288
|
+
spec.startsWith("data:") ||
|
|
289
|
+
spec.startsWith("blob:")) {
|
|
290
|
+
return spec;
|
|
291
|
+
}
|
|
292
|
+
if (spec.startsWith(".") || spec.startsWith("..")) {
|
|
293
|
+
const resolved = resolveRelativeSpecifier(importer, spec);
|
|
294
|
+
if (!resolved)
|
|
295
|
+
return spec;
|
|
296
|
+
const moduleRoot = path.resolve(options.moduleRoot ?? options.projectRoot);
|
|
297
|
+
const modulePrefix = options.modulePrefix ?? INTERNAL_SRC_PREFIX;
|
|
298
|
+
if (STYLE_EXT_RE.test(resolved)) {
|
|
299
|
+
return EMPTY_STYLE_MODULE;
|
|
300
|
+
}
|
|
301
|
+
if (ASSET_EXT_RE.test(resolved)) {
|
|
302
|
+
const rel = path
|
|
303
|
+
.relative(options.projectRoot, resolved)
|
|
304
|
+
.split(path.sep)
|
|
305
|
+
.join("/");
|
|
306
|
+
return `${INTERNAL_ASSET_PREFIX}/${rel}`;
|
|
307
|
+
}
|
|
308
|
+
if (path.resolve(resolved).startsWith(moduleRoot + path.sep)) {
|
|
309
|
+
const rel = path.relative(moduleRoot, resolved).split(path.sep).join("/");
|
|
310
|
+
return `${modulePrefix}/${rel}`;
|
|
311
|
+
}
|
|
312
|
+
const projectRel = path
|
|
313
|
+
.relative(options.projectRoot, resolved)
|
|
314
|
+
.split(path.sep)
|
|
315
|
+
.join("/");
|
|
316
|
+
if (!projectRel.startsWith(".."))
|
|
317
|
+
return `${INTERNAL_SRC_PREFIX}/${projectRel}`;
|
|
318
|
+
return spec;
|
|
319
|
+
}
|
|
320
|
+
if (options.importMap?.[spec])
|
|
321
|
+
return options.importMap[spec];
|
|
322
|
+
// Prefix import-map entries such as "lit-html/" support subpath imports.
|
|
323
|
+
for (const [key, value] of Object.entries(options.importMap ?? {})) {
|
|
324
|
+
if (key.endsWith("/") && spec.startsWith(key)) {
|
|
325
|
+
return value + spec.slice(key.length);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return `${INTERNAL_PKG_PREFIX}/${spec}`;
|
|
329
|
+
}
|
|
330
|
+
function resolveRelativeSpecifier(importer, spec) {
|
|
331
|
+
const base = path.resolve(path.dirname(importer), spec);
|
|
332
|
+
try {
|
|
333
|
+
if (fs.statSync(base).isFile())
|
|
334
|
+
return base;
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
/* try extensions */
|
|
338
|
+
}
|
|
339
|
+
for (const ext of CODE_EXTENSIONS) {
|
|
340
|
+
const candidate = base + ext;
|
|
341
|
+
try {
|
|
342
|
+
if (fs.statSync(candidate).isFile())
|
|
343
|
+
return candidate;
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
/* try next */
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
for (const ext of [".css"]) {
|
|
350
|
+
const candidate = base + ext;
|
|
351
|
+
try {
|
|
352
|
+
if (fs.statSync(candidate).isFile())
|
|
353
|
+
return candidate;
|
|
354
|
+
}
|
|
355
|
+
catch {
|
|
356
|
+
/* try next */
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// Try asset extensions (.svg, .png, .woff2, …) so extensionless imports like
|
|
360
|
+
// `import logo from "./logo"` resolve when the actual file is logo.svg.
|
|
361
|
+
const ASSET_EXT_LIST = [
|
|
362
|
+
".svg",
|
|
363
|
+
".png",
|
|
364
|
+
".jpg",
|
|
365
|
+
".jpeg",
|
|
366
|
+
".gif",
|
|
367
|
+
".webp",
|
|
368
|
+
".avif",
|
|
369
|
+
".ico",
|
|
370
|
+
".bmp",
|
|
371
|
+
".tiff",
|
|
372
|
+
".woff2",
|
|
373
|
+
".woff",
|
|
374
|
+
".ttf",
|
|
375
|
+
".otf",
|
|
376
|
+
".eot",
|
|
377
|
+
".mp4",
|
|
378
|
+
".webm",
|
|
379
|
+
".ogg",
|
|
380
|
+
".mov",
|
|
381
|
+
".avi",
|
|
382
|
+
".mkv",
|
|
383
|
+
".mp3",
|
|
384
|
+
".wav",
|
|
385
|
+
".flac",
|
|
386
|
+
".aac",
|
|
387
|
+
".m4a",
|
|
388
|
+
".opus",
|
|
389
|
+
".pdf",
|
|
390
|
+
".doc",
|
|
391
|
+
".docx",
|
|
392
|
+
".xls",
|
|
393
|
+
".xlsx",
|
|
394
|
+
".ppt",
|
|
395
|
+
".pptx",
|
|
396
|
+
".txt",
|
|
397
|
+
".csv",
|
|
398
|
+
".glb",
|
|
399
|
+
".gltf",
|
|
400
|
+
".obj",
|
|
401
|
+
".fbx",
|
|
402
|
+
".wasm",
|
|
403
|
+
".json5",
|
|
404
|
+
".geojson",
|
|
405
|
+
".toml",
|
|
406
|
+
".yaml",
|
|
407
|
+
".yml",
|
|
408
|
+
".zip",
|
|
409
|
+
".tar",
|
|
410
|
+
".gz",
|
|
411
|
+
];
|
|
412
|
+
for (const ext of ASSET_EXT_LIST) {
|
|
413
|
+
const candidate = base + ext;
|
|
414
|
+
try {
|
|
415
|
+
if (fs.statSync(candidate).isFile())
|
|
416
|
+
return candidate;
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
/* try next */
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
try {
|
|
423
|
+
if (fs.statSync(base).isDirectory()) {
|
|
424
|
+
for (const ext of CODE_EXTENSIONS) {
|
|
425
|
+
const candidate = path.join(base, `index${ext}`);
|
|
426
|
+
try {
|
|
427
|
+
if (fs.statSync(candidate).isFile())
|
|
428
|
+
return candidate;
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
/* try next */
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
/* not a directory */
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
// Virtual file registry
|
|
443
|
+
// ---------------------------------------------------------------------------
|
|
444
|
+
const RPC_CLIENT_JS = /* js */ `
|
|
445
|
+
export async function __rpcCall(url, payload) {
|
|
446
|
+
const isFile =
|
|
447
|
+
payload &&
|
|
448
|
+
typeof payload === "object" &&
|
|
449
|
+
Object.values(payload).some(v => v instanceof File || v instanceof Blob);
|
|
450
|
+
|
|
451
|
+
let body;
|
|
452
|
+
let headers = {};
|
|
453
|
+
|
|
454
|
+
if (isFile) {
|
|
455
|
+
const fd = new FormData();
|
|
456
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
457
|
+
if (v instanceof File || v instanceof Blob) fd.append(k, v);
|
|
458
|
+
else fd.append(k, JSON.stringify(v));
|
|
459
|
+
}
|
|
460
|
+
body = fd;
|
|
461
|
+
} else {
|
|
462
|
+
body = JSON.stringify(payload ?? {});
|
|
463
|
+
headers["Content-Type"] = "application/json";
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const res = await fetch(url, { method: "POST", headers, body });
|
|
467
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
468
|
+
|
|
469
|
+
if (res.status >= 300 && res.status < 400) {
|
|
470
|
+
const data = await res.json();
|
|
471
|
+
if (data.__type === "Redirect") {
|
|
472
|
+
const { isExternalUrl, navigateTo } = await import("${NAV_MODULE}");
|
|
473
|
+
if (isExternalUrl(data.url)) {
|
|
474
|
+
window.location.href = data.url;
|
|
475
|
+
} else {
|
|
476
|
+
navigateTo(data.url);
|
|
477
|
+
}
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (!res.ok) {
|
|
483
|
+
const data = await res.json().catch(() => ({}));
|
|
484
|
+
const { reconstructError, isMatesError } = await import("${ERRORS_MODULE}");
|
|
485
|
+
if (isMatesError(data)) throw reconstructError(data);
|
|
486
|
+
throw new Error(data.message ?? \`HTTP \${res.status}\`);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (ct.includes("text/event-stream")) {
|
|
490
|
+
const { readSseStream } = await import("${STREAM_MODULE}");
|
|
491
|
+
return readSseStream(res);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (/attachment/i.test(res.headers.get("content-disposition") ?? "")) {
|
|
495
|
+
const { triggerBrowserDownload } = await import("${DOWNLOAD_MODULE}");
|
|
496
|
+
triggerBrowserDownload(res);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return res.json();
|
|
501
|
+
}
|
|
502
|
+
`.trimStart();
|
|
503
|
+
const STREAM_JS = /* js */ `
|
|
504
|
+
export async function* readSseStream(res) {
|
|
505
|
+
const reader = res.body?.getReader();
|
|
506
|
+
if (!reader) return;
|
|
507
|
+
const decoder = new TextDecoder();
|
|
508
|
+
let buffer = "";
|
|
509
|
+
while (true) {
|
|
510
|
+
const { done, value } = await reader.read();
|
|
511
|
+
if (done) break;
|
|
512
|
+
buffer += decoder.decode(value, { stream: true });
|
|
513
|
+
const events = buffer.split("\n\n");
|
|
514
|
+
buffer = events.pop() ?? "";
|
|
515
|
+
for (const rawEvent of events) {
|
|
516
|
+
let event; const dataLines = [];
|
|
517
|
+
for (const line of rawEvent.split("\n")) {
|
|
518
|
+
if (line.startsWith("event:")) event = line.slice(6).trim();
|
|
519
|
+
else if (line.startsWith("data:")) dataLines.push(line.slice(5).trim());
|
|
520
|
+
}
|
|
521
|
+
if (dataLines.length === 0) continue;
|
|
522
|
+
const data = dataLines.join("\n");
|
|
523
|
+
if (event === "done") return;
|
|
524
|
+
if (event === "error") {
|
|
525
|
+
const { reconstructError, isMatesError } = await import("${ERRORS_MODULE}");
|
|
526
|
+
const parsed = JSON.parse(data);
|
|
527
|
+
throw isMatesError(parsed) ? reconstructError(parsed) : new Error(data);
|
|
528
|
+
}
|
|
529
|
+
try { yield JSON.parse(data); } catch { yield data; }
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
`.trimStart();
|
|
534
|
+
const STACK_MAP_JS = /* js */ `
|
|
535
|
+
import { TraceMap, originalPositionFor } from "@jridgewell/trace-mapping";
|
|
536
|
+
|
|
537
|
+
const INLINE_SOURCE_MAP_RE = /\/\/# sourceMappingURL=data:application\/json(?:;charset=[^;,]+)?;base64,([A-Za-z0-9+/=]+)/;
|
|
538
|
+
const traceMapCache = new Map();
|
|
539
|
+
|
|
540
|
+
export function parseStackFrames(stack) {
|
|
541
|
+
const frames = [];
|
|
542
|
+
for (const raw of String(stack || "").split(/\r?\n/)) {
|
|
543
|
+
const trimmed = raw.trim();
|
|
544
|
+
if (!trimmed.startsWith("at ")) continue;
|
|
545
|
+
const withFn = trimmed.match(/^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/);
|
|
546
|
+
const withoutFn = trimmed.match(/^at\s+(.+):(\d+):(\d+)$/);
|
|
547
|
+
if (withFn) {
|
|
548
|
+
frames.push({ raw, fnName: withFn[1], file: withFn[2], line: Number(withFn[3]), column: Number(withFn[4]) });
|
|
549
|
+
} else if (withoutFn) {
|
|
550
|
+
frames.push({ raw, fnName: null, file: withoutFn[1], line: Number(withoutFn[2]), column: Number(withoutFn[3]) });
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return frames;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function extractInlineSourceMap(code) {
|
|
557
|
+
const match = String(code || "").match(INLINE_SOURCE_MAP_RE);
|
|
558
|
+
if (!match) return null;
|
|
559
|
+
try { return JSON.parse(atob(match[1])); } catch { return null; }
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export async function mapStackTrace(stack) {
|
|
563
|
+
const frames = parseStackFrames(stack);
|
|
564
|
+
const mapped = [];
|
|
565
|
+
for (const frame of frames) {
|
|
566
|
+
const traceMap = await getTraceMap(frame.file);
|
|
567
|
+
if (!traceMap) {
|
|
568
|
+
mapped.push({ ...frame, mappedFile: null, mappedLine: null, mappedColumn: null, mappedName: null });
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
const original = originalPositionFor(traceMap, { line: frame.line, column: Math.max(0, frame.column - 1) });
|
|
572
|
+
if (!original.source || original.line == null || original.column == null) {
|
|
573
|
+
mapped.push({ ...frame, mappedFile: null, mappedLine: null, mappedColumn: null, mappedName: null });
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
mapped.push({
|
|
577
|
+
...frame,
|
|
578
|
+
mappedFile: original.source,
|
|
579
|
+
mappedLine: original.line,
|
|
580
|
+
mappedColumn: original.column + 1,
|
|
581
|
+
mappedName: original.name || frame.fnName,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
return mapped;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export function formatMappedStack(frames) {
|
|
588
|
+
return frames.map((frame) => {
|
|
589
|
+
const file = frame.mappedFile || frame.file;
|
|
590
|
+
const line = frame.mappedLine || frame.line;
|
|
591
|
+
const column = frame.mappedColumn || frame.column;
|
|
592
|
+
const name = frame.mappedName || frame.fnName;
|
|
593
|
+
const prefix = " at ";
|
|
594
|
+
return name
|
|
595
|
+
? prefix + name + " (" + file + ":" + line + ":" + column + ")"
|
|
596
|
+
: prefix + file + ":" + line + ":" + column;
|
|
597
|
+
}).join("\n");
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export async function renderMappedStack(container, error) {
|
|
601
|
+
const stack = error && (error.stack || error.message) || String(error);
|
|
602
|
+
const frames = await mapStackTrace(stack);
|
|
603
|
+
container.textContent = frames.length > 0 ? formatMappedStack(frames) : stack;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
async function getTraceMap(url) {
|
|
607
|
+
if (traceMapCache.has(url)) return traceMapCache.get(url);
|
|
608
|
+
try {
|
|
609
|
+
const res = await fetch(url);
|
|
610
|
+
if (!res.ok) throw new Error("HTTP " + res.status);
|
|
611
|
+
const code = await res.text();
|
|
612
|
+
const map = extractInlineSourceMap(code);
|
|
613
|
+
const traceMap = map ? new TraceMap(map) : null;
|
|
614
|
+
traceMapCache.set(url, traceMap);
|
|
615
|
+
return traceMap;
|
|
616
|
+
} catch {
|
|
617
|
+
traceMapCache.set(url, null);
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
`.trimStart();
|
|
622
|
+
const CRASH_OVERLAY_JS = /* js */ `
|
|
623
|
+
import { mapStackTrace, formatMappedStack } from "${STACK_MAP_MODULE}";
|
|
624
|
+
|
|
625
|
+
let overlay;
|
|
626
|
+
|
|
627
|
+
function ensureOverlay() {
|
|
628
|
+
if (overlay) return overlay;
|
|
629
|
+
overlay = document.createElement("div");
|
|
630
|
+
overlay.id = "mates-crash-overlay";
|
|
631
|
+
overlay.style.cssText = "position:fixed;inset:0;z-index:2147483647;background:rgba(15,23,42,.96);color:#f8fafc;font:13px ui-monospace,SFMono-Regular,Menlo,monospace;padding:24px;overflow:auto;white-space:pre-wrap";
|
|
632
|
+
document.body.appendChild(overlay);
|
|
633
|
+
return overlay;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export async function showCrashOverlay(error) {
|
|
637
|
+
const el = ensureOverlay();
|
|
638
|
+
const title = error && error.message ? error.message : String(error);
|
|
639
|
+
const frames = await mapStackTrace(error && error.stack ? error.stack : title);
|
|
640
|
+
const stackText = frames.length ? formatMappedStack(frames) : (error && error.stack || title);
|
|
641
|
+
el.textContent = "[mates-fullstack] " + title + "\n\n" + stackText;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
window.addEventListener("error", (event) => {
|
|
645
|
+
showCrashOverlay(event.error || new Error(event.message));
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
649
|
+
showCrashOverlay(event.reason || new Error("Unhandled rejection"));
|
|
650
|
+
});
|
|
651
|
+
`.trimStart();
|
|
652
|
+
const DOWNLOAD_JS = /* js */ `
|
|
653
|
+
export async function triggerBrowserDownload(res) {
|
|
654
|
+
const blob = await res.blob();
|
|
655
|
+
const disposition = res.headers.get("content-disposition") ?? "";
|
|
656
|
+
const quoted = disposition.match(/filename="([^"]+)"/);
|
|
657
|
+
const plain = disposition.match(/filename=([^;\s]+)/);
|
|
658
|
+
const filename = (quoted && quoted[1]) || (plain && plain[1]) || "download";
|
|
659
|
+
const url = URL.createObjectURL(blob);
|
|
660
|
+
const a = document.createElement("a");
|
|
661
|
+
a.href = url;
|
|
662
|
+
a.download = filename;
|
|
663
|
+
document.body.appendChild(a);
|
|
664
|
+
a.click();
|
|
665
|
+
a.remove();
|
|
666
|
+
URL.revokeObjectURL(url);
|
|
667
|
+
}
|
|
668
|
+
`.trimStart();
|
|
669
|
+
const NAV_JS = /* js */ `
|
|
670
|
+
export function isExternalUrl(url) {
|
|
671
|
+
return url.startsWith("http://") || url.startsWith("https://") || url.startsWith("//");
|
|
672
|
+
}
|
|
673
|
+
export function navigateTo(url) {
|
|
674
|
+
history.pushState(null, "", url);
|
|
675
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
676
|
+
}
|
|
677
|
+
`.trimStart();
|
|
678
|
+
const EMPTY_STYLE_JS = /* js */ `
|
|
679
|
+
// Compatibility shim. CSS imports are bundled into one linked stylesheet by
|
|
680
|
+
// mates-fullstack, so JS-side CSS imports intentionally have no side effects.
|
|
681
|
+
export default {};
|
|
682
|
+
`.trimStart();
|
|
683
|
+
const VIRTUAL_FILES = {
|
|
684
|
+
[RPC_CLIENT_MODULE]: RPC_CLIENT_JS,
|
|
685
|
+
[ERRORS_MODULE]: BROWSER_ERRORS_JS,
|
|
686
|
+
[STREAM_MODULE]: STREAM_JS,
|
|
687
|
+
[DOWNLOAD_MODULE]: DOWNLOAD_JS,
|
|
688
|
+
[NAV_MODULE]: NAV_JS,
|
|
689
|
+
[STACK_MAP_MODULE]: STACK_MAP_JS,
|
|
690
|
+
[CRASH_OVERLAY_MODULE]: CRASH_OVERLAY_JS,
|
|
691
|
+
[EMPTY_STYLE_MODULE]: EMPTY_STYLE_JS,
|
|
692
|
+
};
|
|
693
|
+
export function isVirtualFile(pathname) {
|
|
694
|
+
return Object.prototype.hasOwnProperty.call(VIRTUAL_FILES, pathname);
|
|
695
|
+
}
|
|
696
|
+
export async function serveVirtualFile(pathname) {
|
|
697
|
+
return VIRTUAL_FILES[pathname] ?? null;
|
|
698
|
+
}
|
|
699
|
+
//# sourceMappingURL=build-esbuild.js.map
|