@react-router/dev 7.16.0 → 8.0.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -2
- package/bin.cjs +20 -0
- package/dist/build-DM91F_L-.js +41 -0
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.js +378 -2638
- package/dist/config-DvmRcD4Z.d.ts +279 -0
- package/dist/config.d.ts +2 -280
- package/dist/config.js +2 -19
- package/dist/dev-CNEgIjT-.js +53 -0
- package/dist/routes-DXogguGb.js +194 -0
- package/dist/{routes-CZR-bKRt.d.ts → routes-Kx8VZRs3.d.ts} +63 -62
- package/dist/routes.d.ts +3 -2
- package/dist/routes.js +3 -190
- package/dist/typegen-BLMwBSoM.js +859 -0
- package/dist/vite.d.ts +7 -6
- package/dist/vite.js +3225 -6539
- package/module-sync-enabled/index.mjs +2 -2
- package/package.json +53 -59
- package/bin.js +0 -15
- package/dist/vite/cloudflare.d.ts +0 -24
- package/dist/vite/cloudflare.js +0 -938
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @react-router/dev v8.0.0-pre.0
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Remix Software Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*/
|
|
11
|
+
import { c as setAppDirectory, l as validateRouteConfig, t as configRoutesToRouteManifest, u as invariant } from "./routes-DXogguGb.js";
|
|
12
|
+
import { createRequire } from "node:module";
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import colors from "picocolors";
|
|
15
|
+
import fs$1 from "node:fs/promises";
|
|
16
|
+
import { readPackageJSON, sortPackage, updatePackage } from "pkg-types";
|
|
17
|
+
import { execSync } from "node:child_process";
|
|
18
|
+
import * as Path from "pathe";
|
|
19
|
+
import path from "pathe";
|
|
20
|
+
import chokidar from "chokidar";
|
|
21
|
+
import pick from "lodash/pick.js";
|
|
22
|
+
import omit from "lodash/omit.js";
|
|
23
|
+
import cloneDeep from "lodash/cloneDeep.js";
|
|
24
|
+
import isEqual from "lodash/isEqual.js";
|
|
25
|
+
import ts from "dedent";
|
|
26
|
+
import * as Pathe from "pathe/utils";
|
|
27
|
+
import { parse as parse$1 } from "@babel/parser";
|
|
28
|
+
import * as t$1 from "@babel/types";
|
|
29
|
+
import _traverse from "@babel/traverse";
|
|
30
|
+
import _generate from "@babel/generator";
|
|
31
|
+
//#region \0rolldown/runtime.js
|
|
32
|
+
var __defProp = Object.defineProperty;
|
|
33
|
+
var __exportAll = (all, no_symbols) => {
|
|
34
|
+
let target = {};
|
|
35
|
+
for (var name in all) __defProp(target, name, {
|
|
36
|
+
get: all[name],
|
|
37
|
+
enumerable: true
|
|
38
|
+
});
|
|
39
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
40
|
+
return target;
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region config/is-react-router-repo.ts
|
|
44
|
+
const nodeRequire$2 = createRequire(import.meta.url);
|
|
45
|
+
function isReactRouterRepo() {
|
|
46
|
+
let serverRuntimePath = path.dirname(nodeRequire$2.resolve("@react-router/node/package.json"));
|
|
47
|
+
return path.basename(path.resolve(serverRuntimePath, "..")) === "packages";
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region vite/vite.ts
|
|
51
|
+
const nodeRequire$1 = createRequire(import.meta.url);
|
|
52
|
+
let vite;
|
|
53
|
+
const viteImportSpecifier = isReactRouterRepo() ? `file:///${path.normalize(nodeRequire$1.resolve("vite/package.json", { paths: [process.cwd()] })).replace("package.json", "dist/node/index.js")}` : "vite";
|
|
54
|
+
async function preloadVite() {
|
|
55
|
+
vite = await import(viteImportSpecifier);
|
|
56
|
+
}
|
|
57
|
+
function getVite() {
|
|
58
|
+
invariant(vite, "getVite() called before preloadVite()");
|
|
59
|
+
return vite;
|
|
60
|
+
}
|
|
61
|
+
function defineCompilerOptions(options) {
|
|
62
|
+
let vite = getVite();
|
|
63
|
+
return parseInt(vite.version.split(".")[0], 10) >= 8 ? { oxc: options.oxc } : { esbuild: options.esbuild };
|
|
64
|
+
}
|
|
65
|
+
function defineOptimizeDepsCompilerOptions(options) {
|
|
66
|
+
let vite = getVite();
|
|
67
|
+
return parseInt(vite.version.split(".")[0], 10) >= 8 ? { rolldownOptions: options.rolldown } : { esbuildOptions: options.esbuild };
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region vite/ssr-externals.ts
|
|
71
|
+
const ssrExternals = isReactRouterRepo() ? [
|
|
72
|
+
"react-router",
|
|
73
|
+
"@react-router/architect",
|
|
74
|
+
"@react-router/cloudflare",
|
|
75
|
+
"@react-router/dev",
|
|
76
|
+
"@react-router/express",
|
|
77
|
+
"@react-router/node",
|
|
78
|
+
"@react-router/serve"
|
|
79
|
+
] : void 0;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region vite/vite-runner.ts
|
|
82
|
+
async function createContext$1({ root, mode, customLogger }) {
|
|
83
|
+
await preloadVite();
|
|
84
|
+
const vite = getVite();
|
|
85
|
+
const devServer = await vite.createServer({
|
|
86
|
+
root,
|
|
87
|
+
mode,
|
|
88
|
+
customLogger,
|
|
89
|
+
server: {
|
|
90
|
+
preTransformRequests: false,
|
|
91
|
+
hmr: false,
|
|
92
|
+
watch: null
|
|
93
|
+
},
|
|
94
|
+
ssr: { external: ssrExternals },
|
|
95
|
+
optimizeDeps: { noDiscovery: true },
|
|
96
|
+
css: { postcss: {} },
|
|
97
|
+
configFile: false,
|
|
98
|
+
envFile: false,
|
|
99
|
+
plugins: [],
|
|
100
|
+
environments: { __config_loader: {
|
|
101
|
+
consumer: "server",
|
|
102
|
+
dev: { createEnvironment: (name, config, context) => vite.createRunnableDevEnvironment(name, config) }
|
|
103
|
+
} }
|
|
104
|
+
});
|
|
105
|
+
const environment = devServer.environments.__config_loader;
|
|
106
|
+
if (!vite.isRunnableDevEnvironment(environment)) {
|
|
107
|
+
await devServer.close();
|
|
108
|
+
throw new Error("React Router config loading requires Vite's __config_loader environment to be runnable.");
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
devServer,
|
|
112
|
+
environment,
|
|
113
|
+
runner: environment.runner
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region cli/detectPackageManager.ts
|
|
118
|
+
/**
|
|
119
|
+
* Determine which package manager the user prefers.
|
|
120
|
+
*
|
|
121
|
+
* npm, pnpm and Yarn set the user agent environment variable
|
|
122
|
+
* that can be used to determine which package manager ran
|
|
123
|
+
* the command.
|
|
124
|
+
*/
|
|
125
|
+
const detectPackageManager = () => {
|
|
126
|
+
let { npm_config_user_agent } = process.env;
|
|
127
|
+
if (!npm_config_user_agent) return void 0;
|
|
128
|
+
try {
|
|
129
|
+
let pkgManager = npm_config_user_agent.split("/")[0];
|
|
130
|
+
if (pkgManager === "npm") return "npm";
|
|
131
|
+
if (pkgManager === "pnpm") return "pnpm";
|
|
132
|
+
if (pkgManager === "yarn") return "yarn";
|
|
133
|
+
if (pkgManager === "bun") return "bun";
|
|
134
|
+
return;
|
|
135
|
+
} catch {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region config/config.ts
|
|
141
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
142
|
+
const excludedConfigPresetKeys = ["presets"];
|
|
143
|
+
const branchRouteProperties = [
|
|
144
|
+
"id",
|
|
145
|
+
"path",
|
|
146
|
+
"file",
|
|
147
|
+
"index"
|
|
148
|
+
];
|
|
149
|
+
const configRouteToBranchRoute = (configRoute) => pick(configRoute, branchRouteProperties);
|
|
150
|
+
let mergeReactRouterConfig = (...configs) => {
|
|
151
|
+
let reducer = (configA, configB) => {
|
|
152
|
+
let mergeRequired = (key) => configA[key] !== void 0 && configB[key] !== void 0;
|
|
153
|
+
return {
|
|
154
|
+
...configA,
|
|
155
|
+
...configB,
|
|
156
|
+
...mergeRequired("buildEnd") ? { buildEnd: async (...args) => {
|
|
157
|
+
await Promise.all([configA.buildEnd?.(...args), configB.buildEnd?.(...args)]);
|
|
158
|
+
} } : {},
|
|
159
|
+
...mergeRequired("future") ? { future: {
|
|
160
|
+
...configA.future,
|
|
161
|
+
...configB.future
|
|
162
|
+
} } : {},
|
|
163
|
+
...mergeRequired("presets") ? { presets: [...configA.presets ?? [], ...configB.presets ?? []] } : {}
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
return configs.reduce(reducer, {});
|
|
167
|
+
};
|
|
168
|
+
let deepFreeze = (o) => {
|
|
169
|
+
Object.freeze(o);
|
|
170
|
+
let oIsFunction = typeof o === "function";
|
|
171
|
+
let hasOwnProp = Object.prototype.hasOwnProperty;
|
|
172
|
+
Object.getOwnPropertyNames(o).forEach(function(prop) {
|
|
173
|
+
if (hasOwnProp.call(o, prop) && (oIsFunction ? prop !== "caller" && prop !== "callee" && prop !== "arguments" : true) && o[prop] !== null && (typeof o[prop] === "object" || typeof o[prop] === "function") && !Object.isFrozen(o[prop])) deepFreeze(o[prop]);
|
|
174
|
+
});
|
|
175
|
+
return o;
|
|
176
|
+
};
|
|
177
|
+
function ok(value) {
|
|
178
|
+
return {
|
|
179
|
+
ok: true,
|
|
180
|
+
value
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function err(error) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
error
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
async function resolveConfig({ root, viteRunnerContext, reactRouterConfigFile, skipRoutes, validateConfig }) {
|
|
190
|
+
let reactRouterUserConfig = {};
|
|
191
|
+
if (reactRouterConfigFile) try {
|
|
192
|
+
if (!fs.existsSync(reactRouterConfigFile)) return err(`${reactRouterConfigFile} no longer exists`);
|
|
193
|
+
let configModule = await viteRunnerContext.runner.import(reactRouterConfigFile);
|
|
194
|
+
if (configModule.default === void 0) return err(`${reactRouterConfigFile} must provide a default export`);
|
|
195
|
+
if (typeof configModule.default !== "object") return err(`${reactRouterConfigFile} must export a config`);
|
|
196
|
+
reactRouterUserConfig = configModule.default;
|
|
197
|
+
if (validateConfig) {
|
|
198
|
+
const error = validateConfig(reactRouterUserConfig);
|
|
199
|
+
if (error) return err(error);
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
return err(`Error loading ${reactRouterConfigFile}: ${error}`);
|
|
203
|
+
}
|
|
204
|
+
reactRouterUserConfig = deepFreeze(cloneDeep(reactRouterUserConfig));
|
|
205
|
+
let presets = (await Promise.all((reactRouterUserConfig.presets ?? []).map(async (preset) => {
|
|
206
|
+
if (!preset.name) throw new Error("React Router presets must have a `name` property defined.");
|
|
207
|
+
if (!preset.reactRouterConfig) return null;
|
|
208
|
+
return omit(await preset.reactRouterConfig({ reactRouterUserConfig }), excludedConfigPresetKeys);
|
|
209
|
+
}))).filter(function isNotNull(value) {
|
|
210
|
+
return value !== null;
|
|
211
|
+
});
|
|
212
|
+
let defaults = {
|
|
213
|
+
basename: "/",
|
|
214
|
+
buildDirectory: "build",
|
|
215
|
+
serverBuildFile: "index.js",
|
|
216
|
+
serverModuleFormat: "esm",
|
|
217
|
+
ssr: true
|
|
218
|
+
};
|
|
219
|
+
let userAndPresetConfigs = mergeReactRouterConfig(...presets, reactRouterUserConfig);
|
|
220
|
+
let { appDirectory: userAppDirectory, basename, buildDirectory: userBuildDirectory, buildEnd, prerender, routeDiscovery: userRouteDiscovery, serverBuildFile, serverBundles, serverModuleFormat, ssr } = {
|
|
221
|
+
...defaults,
|
|
222
|
+
...userAndPresetConfigs
|
|
223
|
+
};
|
|
224
|
+
if (!ssr && serverBundles) serverBundles = void 0;
|
|
225
|
+
if (prerender) {
|
|
226
|
+
let isValidPrerenderPathsConfig = (p) => typeof p === "boolean" || typeof p === "function" || Array.isArray(p);
|
|
227
|
+
if (!(isValidPrerenderPathsConfig(prerender) || typeof prerender === "object" && "paths" in prerender && isValidPrerenderPathsConfig(prerender.paths))) return err("The `prerender`/`prerender.paths` config must be a boolean, an array of string paths, or a function returning a boolean or array of string paths.");
|
|
228
|
+
if (typeof prerender === "object" && "unstable_concurrency" in prerender) return err("The `prerender.unstable_concurrency` config field has been stabilized as `prerender.concurrency`");
|
|
229
|
+
if (!(typeof prerender != "object" || !("concurrency" in prerender) || typeof prerender.concurrency === "number" && Number.isInteger(prerender.concurrency) && prerender.concurrency > 0)) return err("The `prerender.concurrency` config must be a positive integer if specified.");
|
|
230
|
+
}
|
|
231
|
+
let routeDiscovery;
|
|
232
|
+
if (userRouteDiscovery == null) if (ssr) routeDiscovery = {
|
|
233
|
+
mode: "lazy",
|
|
234
|
+
manifestPath: "/__manifest"
|
|
235
|
+
};
|
|
236
|
+
else routeDiscovery = { mode: "initial" };
|
|
237
|
+
else if (userRouteDiscovery.mode === "initial") routeDiscovery = userRouteDiscovery;
|
|
238
|
+
else if (userRouteDiscovery.mode === "lazy") {
|
|
239
|
+
if (!ssr) return err("The `routeDiscovery.mode` config cannot be set to \"lazy\" when setting `ssr:false`");
|
|
240
|
+
let { manifestPath } = userRouteDiscovery;
|
|
241
|
+
if (manifestPath != null && !manifestPath.startsWith("/")) return err("The `routeDiscovery.manifestPath` config must be a root-relative pathname beginning with a slash (i.e., \"/__manifest\")");
|
|
242
|
+
routeDiscovery = userRouteDiscovery;
|
|
243
|
+
}
|
|
244
|
+
let appDirectory = path.resolve(root, userAppDirectory || "app");
|
|
245
|
+
let buildDirectory = path.resolve(root, userBuildDirectory);
|
|
246
|
+
let rootRouteFile = findEntry(appDirectory, "root", { absolute: true });
|
|
247
|
+
if (!rootRouteFile) return err(`Could not find a root route module in the app directory as "${path.relative(root, path.join(appDirectory, "root.tsx"))}"`);
|
|
248
|
+
let routes;
|
|
249
|
+
let routeConfig = [];
|
|
250
|
+
if (skipRoutes) routes = {};
|
|
251
|
+
else {
|
|
252
|
+
let routeConfigFile = findEntry(appDirectory, "routes");
|
|
253
|
+
try {
|
|
254
|
+
if (!routeConfigFile) return err(`Route config file not found at "${path.relative(root, path.join(appDirectory, "routes.ts"))}".`);
|
|
255
|
+
setAppDirectory(appDirectory);
|
|
256
|
+
let routeConfigExport = (await viteRunnerContext.runner.import(path.join(appDirectory, routeConfigFile))).default;
|
|
257
|
+
let result = validateRouteConfig({
|
|
258
|
+
routeConfigFile,
|
|
259
|
+
routeConfig: await routeConfigExport
|
|
260
|
+
});
|
|
261
|
+
if (!result.valid) return err(result.message);
|
|
262
|
+
routeConfig = [{
|
|
263
|
+
id: "root",
|
|
264
|
+
path: "",
|
|
265
|
+
file: path.relative(appDirectory, rootRouteFile),
|
|
266
|
+
children: result.routeConfig
|
|
267
|
+
}];
|
|
268
|
+
routes = configRoutesToRouteManifest(appDirectory, routeConfig);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return err([
|
|
271
|
+
colors.red(`Route config in "${routeConfigFile}" is invalid.`),
|
|
272
|
+
"",
|
|
273
|
+
error.loc?.file && error.loc?.column && error.frame ? [path.relative(appDirectory, error.loc.file) + ":" + error.loc.line + ":" + error.loc.column, error.frame.trim?.()] : error.stack
|
|
274
|
+
].flat().join("\n"));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
let futureConfig = userAndPresetConfigs.future;
|
|
278
|
+
if (futureConfig) {
|
|
279
|
+
if ("unstable_splitRouteModules" in futureConfig || "v8_splitRouteModules" in futureConfig) return err("The `future.v8_splitRouteModules` flag has been moved to a top-level `config.splitRouteModules` field (default `true`)");
|
|
280
|
+
if ("unstable_viteEnvironmentApi" in futureConfig || "v8_viteEnvironmentApi" in futureConfig) return err("The `future.v8_viteEnvironmentApi` flag has been removed because Vite Environment API usage is now always enabled");
|
|
281
|
+
if ("unstable_passThroughRequests" in futureConfig || "v8_passThroughRequests" in futureConfig) return err("The `future.v8_passThroughRequests` flag has been removed because pass-through requests are now the default behavior");
|
|
282
|
+
if ("unstable_middleware" in futureConfig || "v8_middleware" in futureConfig) return err("The `future.v8_middleware` flag has been removed because middleware is now always enabled");
|
|
283
|
+
if ("unstable_trailingSlashAwareDataRequests" in futureConfig || "v8_trailingSlashAwareDataRequests" in futureConfig) return err("The `future.v8_trailingSlashAwareDataRequests` flag has been removed because trailing slash-aware data requests are now the default behavior");
|
|
284
|
+
if ("unstable_subResourceIntegrity" in futureConfig) return err("The `future.unstable_subResourceIntegrity` flag has been stabilized and moved to a top-level `config.subResourceIntegrity` field");
|
|
285
|
+
}
|
|
286
|
+
let future = { unstable_optimizeDeps: userAndPresetConfigs.future?.unstable_optimizeDeps ?? false };
|
|
287
|
+
let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;
|
|
288
|
+
let splitRouteModules = userAndPresetConfigs.splitRouteModules ?? true;
|
|
289
|
+
let subResourceIntegrity = userAndPresetConfigs.subResourceIntegrity ?? false;
|
|
290
|
+
let reactRouterConfig = deepFreeze({
|
|
291
|
+
appDirectory,
|
|
292
|
+
basename,
|
|
293
|
+
buildDirectory,
|
|
294
|
+
buildEnd,
|
|
295
|
+
future,
|
|
296
|
+
prerender,
|
|
297
|
+
routes,
|
|
298
|
+
routeDiscovery,
|
|
299
|
+
serverBuildFile,
|
|
300
|
+
serverBundles,
|
|
301
|
+
serverModuleFormat,
|
|
302
|
+
ssr,
|
|
303
|
+
splitRouteModules,
|
|
304
|
+
subResourceIntegrity,
|
|
305
|
+
allowedActionOrigins,
|
|
306
|
+
unstable_routeConfig: routeConfig
|
|
307
|
+
});
|
|
308
|
+
for (let preset of reactRouterUserConfig.presets ?? []) await preset.reactRouterConfigResolved?.({ reactRouterConfig });
|
|
309
|
+
return ok(reactRouterConfig);
|
|
310
|
+
}
|
|
311
|
+
async function createConfigLoader({ rootDirectory: root, watch, mode, skipRoutes, validateConfig }) {
|
|
312
|
+
root = path.normalize(root ?? process.env.REACT_ROUTER_ROOT ?? process.cwd());
|
|
313
|
+
let vite = await import("vite");
|
|
314
|
+
let viteRunnerContext = await createContext$1({
|
|
315
|
+
root,
|
|
316
|
+
mode,
|
|
317
|
+
customLogger: vite.createLogger("warn", { prefix: "[react-router]" })
|
|
318
|
+
});
|
|
319
|
+
let reactRouterConfigFile;
|
|
320
|
+
let updateReactRouterConfigFile = () => {
|
|
321
|
+
reactRouterConfigFile = findEntry(root, "react-router.config", { absolute: true });
|
|
322
|
+
};
|
|
323
|
+
updateReactRouterConfigFile();
|
|
324
|
+
let getConfig = () => resolveConfig({
|
|
325
|
+
root,
|
|
326
|
+
viteRunnerContext,
|
|
327
|
+
reactRouterConfigFile,
|
|
328
|
+
skipRoutes,
|
|
329
|
+
validateConfig
|
|
330
|
+
});
|
|
331
|
+
let appDirectory;
|
|
332
|
+
let initialConfigResult = await getConfig();
|
|
333
|
+
if (!initialConfigResult.ok) throw new Error(initialConfigResult.error);
|
|
334
|
+
appDirectory = path.normalize(initialConfigResult.value.appDirectory);
|
|
335
|
+
let currentConfig = initialConfigResult.value;
|
|
336
|
+
let fsWatcher;
|
|
337
|
+
let changeHandlers = [];
|
|
338
|
+
return {
|
|
339
|
+
getConfig,
|
|
340
|
+
onChange: (handler) => {
|
|
341
|
+
if (!watch) throw new Error("onChange is not supported when watch mode is disabled");
|
|
342
|
+
changeHandlers.push(handler);
|
|
343
|
+
if (!fsWatcher) {
|
|
344
|
+
fsWatcher = chokidar.watch([root, appDirectory], {
|
|
345
|
+
ignoreInitial: true,
|
|
346
|
+
ignored: (path) => isIgnoredByWatcher(path, {
|
|
347
|
+
root,
|
|
348
|
+
appDirectory
|
|
349
|
+
})
|
|
350
|
+
});
|
|
351
|
+
fsWatcher.on("error", (error) => {
|
|
352
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
353
|
+
console.warn(colors.yellow(`File watcher error: ${message}`));
|
|
354
|
+
});
|
|
355
|
+
fsWatcher.on("all", async (...args) => {
|
|
356
|
+
let [event, rawFilepath] = args;
|
|
357
|
+
let filepath = path.normalize(rawFilepath);
|
|
358
|
+
let fileAddedOrRemoved = event === "add" || event === "unlink";
|
|
359
|
+
let appFileAddedOrRemoved = fileAddedOrRemoved && filepath.startsWith(path.normalize(appDirectory));
|
|
360
|
+
let rootRelativeFilepath = path.relative(root, filepath);
|
|
361
|
+
let configFileAddedOrRemoved = fileAddedOrRemoved && isEntryFile("react-router.config", rootRelativeFilepath);
|
|
362
|
+
if (configFileAddedOrRemoved) updateReactRouterConfigFile();
|
|
363
|
+
if (!(configFileAddedOrRemoved || Boolean(viteRunnerContext.environment.moduleGraph.getModuleById(filepath))) && !appFileAddedOrRemoved) return;
|
|
364
|
+
viteRunnerContext.environment.moduleGraph.invalidateAll();
|
|
365
|
+
viteRunnerContext.runner.clearCache();
|
|
366
|
+
let result = await getConfig();
|
|
367
|
+
let prevAppDirectory = appDirectory;
|
|
368
|
+
appDirectory = path.normalize((result.value ?? currentConfig).appDirectory);
|
|
369
|
+
if (appDirectory !== prevAppDirectory) {
|
|
370
|
+
fsWatcher.unwatch(prevAppDirectory);
|
|
371
|
+
fsWatcher.add(appDirectory);
|
|
372
|
+
}
|
|
373
|
+
let configCodeChanged = configFileAddedOrRemoved || reactRouterConfigFile !== void 0 && isEntryFileDependency(viteRunnerContext.environment.moduleGraph, reactRouterConfigFile, filepath);
|
|
374
|
+
let routeConfigFile = !skipRoutes ? findEntry(appDirectory, "routes", { absolute: true }) : void 0;
|
|
375
|
+
let routeConfigCodeChanged = routeConfigFile !== void 0 && isEntryFileDependency(viteRunnerContext.environment.moduleGraph, routeConfigFile, filepath);
|
|
376
|
+
let configChanged = result.ok && !isEqual(omitRoutes(currentConfig), omitRoutes(result.value));
|
|
377
|
+
let routeConfigChanged = result.ok && !isEqual(currentConfig?.routes, result.value.routes);
|
|
378
|
+
for (let handler of changeHandlers) handler({
|
|
379
|
+
result,
|
|
380
|
+
configCodeChanged,
|
|
381
|
+
routeConfigCodeChanged,
|
|
382
|
+
configChanged,
|
|
383
|
+
routeConfigChanged,
|
|
384
|
+
path: filepath,
|
|
385
|
+
event
|
|
386
|
+
});
|
|
387
|
+
if (result.ok) currentConfig = result.value;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
return () => {
|
|
391
|
+
changeHandlers = changeHandlers.filter((changeHandler) => changeHandler !== handler);
|
|
392
|
+
};
|
|
393
|
+
},
|
|
394
|
+
close: async () => {
|
|
395
|
+
changeHandlers = [];
|
|
396
|
+
await viteRunnerContext.devServer.close();
|
|
397
|
+
await fsWatcher?.close();
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
async function loadConfig({ rootDirectory, mode, skipRoutes }) {
|
|
402
|
+
let configLoader = await createConfigLoader({
|
|
403
|
+
rootDirectory,
|
|
404
|
+
mode,
|
|
405
|
+
skipRoutes,
|
|
406
|
+
watch: false
|
|
407
|
+
});
|
|
408
|
+
let config = await configLoader.getConfig();
|
|
409
|
+
await configLoader.close();
|
|
410
|
+
return config;
|
|
411
|
+
}
|
|
412
|
+
async function resolveEntryFiles({ rootDirectory, reactRouterConfig }) {
|
|
413
|
+
let { appDirectory } = reactRouterConfig;
|
|
414
|
+
let defaultsDirectory = path.resolve(path.dirname(nodeRequire.resolve("@react-router/dev/package.json")), "dist", "config", "defaults");
|
|
415
|
+
let userEntryClientFile = findEntry(appDirectory, "entry.client");
|
|
416
|
+
let userEntryServerFile = findEntry(appDirectory, "entry.server");
|
|
417
|
+
let entryServerFile;
|
|
418
|
+
let entryClientFile = userEntryClientFile || "entry.client.tsx";
|
|
419
|
+
if (userEntryServerFile) entryServerFile = userEntryServerFile;
|
|
420
|
+
else {
|
|
421
|
+
let packageJsonPath = findEntry(rootDirectory, "package", {
|
|
422
|
+
extensions: [".json"],
|
|
423
|
+
absolute: true,
|
|
424
|
+
walkParents: true
|
|
425
|
+
});
|
|
426
|
+
if (!packageJsonPath) throw new Error(`Could not find package.json in ${rootDirectory} or any of its parent directories. Please add a package.json, or provide a custom entry.server.tsx/jsx file in your app directory.`);
|
|
427
|
+
let packageJsonDirectory = path.dirname(packageJsonPath);
|
|
428
|
+
let deps = (await readPackageJSON(packageJsonDirectory)).dependencies ?? {};
|
|
429
|
+
if (!deps["@react-router/node"]) throw new Error(`Could not determine server runtime. Please install @react-router/node, or provide a custom entry.server.tsx/jsx file in your app directory.`);
|
|
430
|
+
if (!deps["isbot"]) {
|
|
431
|
+
console.log("adding `isbot@5` to your package.json, you should commit this change");
|
|
432
|
+
await updatePackage(packageJsonPath, (pkg) => {
|
|
433
|
+
pkg.dependencies ??= {};
|
|
434
|
+
pkg.dependencies.isbot = "^5";
|
|
435
|
+
sortPackage(pkg);
|
|
436
|
+
});
|
|
437
|
+
execSync(`${detectPackageManager() ?? "npm"} install`, {
|
|
438
|
+
cwd: packageJsonDirectory,
|
|
439
|
+
stdio: "inherit"
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
entryServerFile = `entry.server.node.tsx`;
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
entryClientFilePath: userEntryClientFile ? path.resolve(reactRouterConfig.appDirectory, userEntryClientFile) : path.resolve(defaultsDirectory, entryClientFile),
|
|
446
|
+
entryServerFilePath: userEntryServerFile ? path.resolve(reactRouterConfig.appDirectory, userEntryServerFile) : path.resolve(defaultsDirectory, entryServerFile)
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
async function resolveRSCEntryFiles({ reactRouterConfig }) {
|
|
450
|
+
let { appDirectory } = reactRouterConfig;
|
|
451
|
+
let defaultsDirectory = path.resolve(path.dirname(nodeRequire.resolve("@react-router/dev/package.json")), "dist", "config", "default-rsc-entries");
|
|
452
|
+
let userEntryClientFile = findEntry(appDirectory, "entry.client", { absolute: true });
|
|
453
|
+
let userEntryRSCFile = findEntry(appDirectory, "entry.rsc", { absolute: true });
|
|
454
|
+
let userEntrySSRFile = findEntry(appDirectory, "entry.ssr", { absolute: true });
|
|
455
|
+
return {
|
|
456
|
+
client: userEntryClientFile ?? path.join(defaultsDirectory, "entry.client.tsx"),
|
|
457
|
+
rsc: userEntryRSCFile ?? path.join(defaultsDirectory, "entry.rsc.tsx"),
|
|
458
|
+
ssr: userEntrySSRFile ?? path.join(defaultsDirectory, "entry.ssr.tsx")
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function omitRoutes(config) {
|
|
462
|
+
return {
|
|
463
|
+
...config,
|
|
464
|
+
routes: {}
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
const entryExts = [
|
|
468
|
+
".js",
|
|
469
|
+
".jsx",
|
|
470
|
+
".ts",
|
|
471
|
+
".tsx",
|
|
472
|
+
".mjs",
|
|
473
|
+
".mts"
|
|
474
|
+
];
|
|
475
|
+
function isEntryFile(entryBasename, filename) {
|
|
476
|
+
return entryExts.some((ext) => filename === `${entryBasename}${ext}`);
|
|
477
|
+
}
|
|
478
|
+
function findEntry(dir, basename, options) {
|
|
479
|
+
let currentDir = path.resolve(dir);
|
|
480
|
+
let { root } = path.parse(currentDir);
|
|
481
|
+
while (true) {
|
|
482
|
+
for (let ext of options?.extensions ?? entryExts) {
|
|
483
|
+
let file = path.resolve(currentDir, basename + ext);
|
|
484
|
+
if (fs.existsSync(file)) return options?.absolute ?? false ? file : path.relative(dir, file);
|
|
485
|
+
}
|
|
486
|
+
if (!options?.walkParents) return;
|
|
487
|
+
let parentDir = path.dirname(currentDir);
|
|
488
|
+
if (currentDir === root || parentDir === currentDir) return;
|
|
489
|
+
currentDir = parentDir;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function isEntryFileDependency(moduleGraph, entryFilepath, filepath, visited = /* @__PURE__ */ new Set()) {
|
|
493
|
+
entryFilepath = path.normalize(entryFilepath);
|
|
494
|
+
filepath = path.normalize(filepath);
|
|
495
|
+
if (visited.has(filepath)) return false;
|
|
496
|
+
visited.add(filepath);
|
|
497
|
+
if (filepath === entryFilepath) return true;
|
|
498
|
+
let mod = moduleGraph.getModuleById(filepath);
|
|
499
|
+
if (!mod) return false;
|
|
500
|
+
for (let importer of mod.importers) {
|
|
501
|
+
if (!importer.id) continue;
|
|
502
|
+
if (importer.id === entryFilepath || isEntryFileDependency(moduleGraph, entryFilepath, importer.id, visited)) return true;
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
function isIgnoredByWatcher(path$1, { root, appDirectory }) {
|
|
507
|
+
let dirname = path.dirname(path$1);
|
|
508
|
+
if (!dirname.startsWith(appDirectory) && path$1 !== root && dirname !== root) return true;
|
|
509
|
+
try {
|
|
510
|
+
let stat = fs.statSync(path$1, { throwIfNoEntry: false });
|
|
511
|
+
if (stat && !stat.isFile() && !stat.isDirectory()) return true;
|
|
512
|
+
} catch {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
//#endregion
|
|
518
|
+
//#region typegen/context.ts
|
|
519
|
+
async function createContext({ rootDirectory, watch, mode, rsc }) {
|
|
520
|
+
const configLoader = await createConfigLoader({
|
|
521
|
+
rootDirectory,
|
|
522
|
+
mode,
|
|
523
|
+
watch
|
|
524
|
+
});
|
|
525
|
+
const configResult = await configLoader.getConfig();
|
|
526
|
+
if (!configResult.ok) throw new Error(configResult.error);
|
|
527
|
+
return {
|
|
528
|
+
configLoader,
|
|
529
|
+
rootDirectory,
|
|
530
|
+
config: configResult.value,
|
|
531
|
+
rsc
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
//#endregion
|
|
535
|
+
//#region vite/babel.ts
|
|
536
|
+
var babel_exports = /* @__PURE__ */ __exportAll({
|
|
537
|
+
generate: () => generate,
|
|
538
|
+
parse: () => parse$1,
|
|
539
|
+
t: () => t$1,
|
|
540
|
+
traverse: () => traverse
|
|
541
|
+
});
|
|
542
|
+
const traverse = _traverse.default;
|
|
543
|
+
const generate = _generate.default;
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region typegen/params.ts
|
|
546
|
+
function parse(fullpath) {
|
|
547
|
+
const result = {};
|
|
548
|
+
let segments = fullpath.split("/");
|
|
549
|
+
segments.forEach((segment) => {
|
|
550
|
+
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
551
|
+
if (!match) return;
|
|
552
|
+
const param = match[1];
|
|
553
|
+
const isRequired = match[2] === void 0;
|
|
554
|
+
result[param] ||= isRequired;
|
|
555
|
+
});
|
|
556
|
+
if (segments.at(-1) === "*") result["*"] = true;
|
|
557
|
+
return result;
|
|
558
|
+
}
|
|
559
|
+
//#endregion
|
|
560
|
+
//#region typegen/route.ts
|
|
561
|
+
function lineage(routes, route) {
|
|
562
|
+
const result = [];
|
|
563
|
+
while (route) {
|
|
564
|
+
result.push(route);
|
|
565
|
+
if (!route.parentId) break;
|
|
566
|
+
route = routes[route.parentId];
|
|
567
|
+
}
|
|
568
|
+
result.reverse();
|
|
569
|
+
return result;
|
|
570
|
+
}
|
|
571
|
+
function fullpath(lineage) {
|
|
572
|
+
const route = lineage.at(-1);
|
|
573
|
+
if (lineage.length === 1 && route?.id === "root") return "/";
|
|
574
|
+
if (route && route.index !== true && route.path === void 0) return void 0;
|
|
575
|
+
return "/" + lineage.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path) => path !== void 0 && path !== "").join("/");
|
|
576
|
+
}
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region typegen/generate.ts
|
|
579
|
+
function typesDirectory(ctx) {
|
|
580
|
+
return Path.join(ctx.rootDirectory, ".react-router/types");
|
|
581
|
+
}
|
|
582
|
+
function generateServerBuild(ctx) {
|
|
583
|
+
return {
|
|
584
|
+
filename: Path.join(typesDirectory(ctx), "+server-build.d.ts"),
|
|
585
|
+
content: ts`
|
|
586
|
+
// Generated by React Router
|
|
587
|
+
|
|
588
|
+
declare module "virtual:react-router/server-build" {
|
|
589
|
+
import { ServerBuild } from "react-router";
|
|
590
|
+
export const assets: ServerBuild["assets"];
|
|
591
|
+
export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
|
|
592
|
+
export const basename: ServerBuild["basename"];
|
|
593
|
+
export const entry: ServerBuild["entry"];
|
|
594
|
+
export const future: ServerBuild["future"];
|
|
595
|
+
export const isSpaMode: ServerBuild["isSpaMode"];
|
|
596
|
+
export const prerender: ServerBuild["prerender"];
|
|
597
|
+
export const publicPath: ServerBuild["publicPath"];
|
|
598
|
+
export const routeDiscovery: ServerBuild["routeDiscovery"];
|
|
599
|
+
export const routes: ServerBuild["routes"];
|
|
600
|
+
export const ssr: ServerBuild["ssr"];
|
|
601
|
+
export const allowedActionOrigins: ServerBuild["allowedActionOrigins"];
|
|
602
|
+
export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
|
|
603
|
+
}
|
|
604
|
+
`
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
const { t } = babel_exports;
|
|
608
|
+
function generateRoutes(ctx) {
|
|
609
|
+
const fileToRoutes = /* @__PURE__ */ new Map();
|
|
610
|
+
const lineages = /* @__PURE__ */ new Map();
|
|
611
|
+
const allPages = /* @__PURE__ */ new Set();
|
|
612
|
+
const routeToPages = /* @__PURE__ */ new Map();
|
|
613
|
+
for (const route of Object.values(ctx.config.routes)) {
|
|
614
|
+
let routeIds = fileToRoutes.get(route.file);
|
|
615
|
+
if (!routeIds) {
|
|
616
|
+
routeIds = /* @__PURE__ */ new Set();
|
|
617
|
+
fileToRoutes.set(route.file, routeIds);
|
|
618
|
+
}
|
|
619
|
+
routeIds.add(route.id);
|
|
620
|
+
const lineage$1 = lineage(ctx.config.routes, route);
|
|
621
|
+
lineages.set(route.id, lineage$1);
|
|
622
|
+
const fullpath$1 = fullpath(lineage$1);
|
|
623
|
+
if (!fullpath$1) continue;
|
|
624
|
+
const pages = expand(fullpath$1);
|
|
625
|
+
pages.forEach((page) => allPages.add(page));
|
|
626
|
+
lineage$1.forEach(({ id }) => {
|
|
627
|
+
let routePages = routeToPages.get(id);
|
|
628
|
+
if (!routePages) {
|
|
629
|
+
routePages = /* @__PURE__ */ new Set();
|
|
630
|
+
routeToPages.set(id, routePages);
|
|
631
|
+
}
|
|
632
|
+
pages.forEach((page) => routePages.add(page));
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
return [{
|
|
636
|
+
filename: Path.join(typesDirectory(ctx), "+routes.ts"),
|
|
637
|
+
content: ts`
|
|
638
|
+
// Generated by React Router
|
|
639
|
+
|
|
640
|
+
import "react-router"
|
|
641
|
+
|
|
642
|
+
declare module "react-router" {
|
|
643
|
+
interface Register {
|
|
644
|
+
pages: Pages
|
|
645
|
+
routeFiles: RouteFiles
|
|
646
|
+
routeModules: RouteModules
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
` + "\n\n" + generate(pagesType(allPages)).code + "\n\n" + generate(routeFilesType({
|
|
650
|
+
fileToRoutes,
|
|
651
|
+
routeToPages
|
|
652
|
+
})).code + "\n\n" + generate(routeModulesType(ctx)).code
|
|
653
|
+
}, ...Array.from(fileToRoutes.entries()).filter(([file]) => isInAppDirectory(ctx, file)).map(([file, routeIds]) => getRouteAnnotations({
|
|
654
|
+
ctx,
|
|
655
|
+
file,
|
|
656
|
+
routeIds,
|
|
657
|
+
lineages
|
|
658
|
+
}))];
|
|
659
|
+
}
|
|
660
|
+
function pagesType(pages) {
|
|
661
|
+
return t.tsTypeAliasDeclaration(t.identifier("Pages"), null, t.tsTypeLiteral(Array.from(pages).map((page) => {
|
|
662
|
+
return t.tsPropertySignature(t.stringLiteral(page), t.tsTypeAnnotation(t.tsTypeLiteral([t.tsPropertySignature(t.identifier("params"), t.tsTypeAnnotation(paramsType(page)))])));
|
|
663
|
+
})));
|
|
664
|
+
}
|
|
665
|
+
function routeFilesType({ fileToRoutes, routeToPages }) {
|
|
666
|
+
return t.tsTypeAliasDeclaration(t.identifier("RouteFiles"), null, t.tsTypeLiteral(Array.from(fileToRoutes).map(([file, routeIds]) => t.tsPropertySignature(t.stringLiteral(file), t.tsTypeAnnotation(t.tsUnionType(Array.from(routeIds).map((routeId) => {
|
|
667
|
+
const pages = routeToPages.get(routeId) ?? /* @__PURE__ */ new Set();
|
|
668
|
+
return t.tsTypeLiteral([t.tsPropertySignature(t.identifier("id"), t.tsTypeAnnotation(t.tsLiteralType(t.stringLiteral(routeId)))), t.tsPropertySignature(t.identifier("page"), t.tsTypeAnnotation(pages.size > 0 ? t.tsUnionType(Array.from(pages).map((page) => t.tsLiteralType(t.stringLiteral(page)))) : t.tsNeverKeyword()))]);
|
|
669
|
+
})))))));
|
|
670
|
+
}
|
|
671
|
+
function routeModulesType(ctx) {
|
|
672
|
+
return t.tsTypeAliasDeclaration(t.identifier("RouteModules"), null, t.tsTypeLiteral(Object.values(ctx.config.routes).map((route) => t.tsPropertySignature(t.stringLiteral(route.id), t.tsTypeAnnotation(isInAppDirectory(ctx, route.file) ? t.tsTypeQuery(t.tsImportType(t.stringLiteral(`./${Path.relative(ctx.rootDirectory, ctx.config.appDirectory)}/${route.file}`))) : t.tsUnknownKeyword())))));
|
|
673
|
+
}
|
|
674
|
+
function isInAppDirectory(ctx, routeFile) {
|
|
675
|
+
return Path.resolve(ctx.config.appDirectory, routeFile).startsWith(ctx.config.appDirectory);
|
|
676
|
+
}
|
|
677
|
+
function getRouteAnnotations({ ctx, file, routeIds, lineages }) {
|
|
678
|
+
const filename = Path.join(typesDirectory(ctx), Path.relative(ctx.rootDirectory, ctx.config.appDirectory), Path.dirname(file), "+types", Pathe.filename(file) + ".ts");
|
|
679
|
+
const matchesType = t.tsTypeAliasDeclaration(t.identifier("Matches"), null, t.tsUnionType(Array.from(routeIds).map((routeId) => {
|
|
680
|
+
const lineage = lineages.get(routeId);
|
|
681
|
+
return t.tsTupleType(lineage.map((route) => t.tsTypeLiteral([t.tsPropertySignature(t.identifier("id"), t.tsTypeAnnotation(t.tsLiteralType(t.stringLiteral(route.id)))), t.tsPropertySignature(t.identifier("module"), t.tsTypeAnnotation(t.tsTypeQuery(t.tsImportType(t.stringLiteral(relativeImportSource(rootDirsPath(ctx, filename), Path.resolve(ctx.config.appDirectory, route.file)))))))])));
|
|
682
|
+
})));
|
|
683
|
+
return {
|
|
684
|
+
filename,
|
|
685
|
+
content: ts`
|
|
686
|
+
// Generated by React Router
|
|
687
|
+
|
|
688
|
+
import type { GetInfo, GetAnnotations } from "react-router/internal";
|
|
689
|
+
|
|
690
|
+
type Module = typeof import("${relativeImportSource(rootDirsPath(ctx, filename), Path.resolve(ctx.config.appDirectory, file))}")
|
|
691
|
+
|
|
692
|
+
type Info = GetInfo<{
|
|
693
|
+
file: "${file}",
|
|
694
|
+
module: Module
|
|
695
|
+
}>
|
|
696
|
+
` + "\n\n" + generate(matchesType).code + "\n\n" + ts`
|
|
697
|
+
type Annotations = GetAnnotations<Info & { module: Module, matches: Matches }>;
|
|
698
|
+
|
|
699
|
+
export namespace Route {
|
|
700
|
+
// links
|
|
701
|
+
export type LinkDescriptors = Annotations["LinkDescriptors"];
|
|
702
|
+
export type LinksFunction = Annotations["LinksFunction"];
|
|
703
|
+
|
|
704
|
+
// meta
|
|
705
|
+
export type MetaArgs = Annotations["MetaArgs"];
|
|
706
|
+
export type MetaDescriptors = Annotations["MetaDescriptors"];
|
|
707
|
+
export type MetaFunction = Annotations["MetaFunction"];
|
|
708
|
+
|
|
709
|
+
// headers
|
|
710
|
+
export type HeadersArgs = Annotations["HeadersArgs"];
|
|
711
|
+
export type HeadersFunction = Annotations["HeadersFunction"];
|
|
712
|
+
|
|
713
|
+
// middleware
|
|
714
|
+
export type MiddlewareFunction = Annotations["MiddlewareFunction"];
|
|
715
|
+
|
|
716
|
+
// clientMiddleware
|
|
717
|
+
export type ClientMiddlewareFunction = Annotations["ClientMiddlewareFunction"];
|
|
718
|
+
|
|
719
|
+
// loader
|
|
720
|
+
export type LoaderArgs = Annotations["LoaderArgs"];
|
|
721
|
+
|
|
722
|
+
// clientLoader
|
|
723
|
+
export type ClientLoaderArgs = Annotations["ClientLoaderArgs"];
|
|
724
|
+
|
|
725
|
+
// action
|
|
726
|
+
export type ActionArgs = Annotations["ActionArgs"];
|
|
727
|
+
|
|
728
|
+
// clientAction
|
|
729
|
+
export type ClientActionArgs = Annotations["ClientActionArgs"];
|
|
730
|
+
|
|
731
|
+
// HydrateFallback
|
|
732
|
+
export type HydrateFallbackProps = Annotations["HydrateFallbackProps"];
|
|
733
|
+
|
|
734
|
+
// ServerHydrateFallback
|
|
735
|
+
export type ServerHydrateFallbackProps = Annotations["ServerHydrateFallbackProps"];
|
|
736
|
+
|
|
737
|
+
// Component
|
|
738
|
+
export type ComponentProps = Annotations["ComponentProps"];
|
|
739
|
+
|
|
740
|
+
// ServerComponent
|
|
741
|
+
export type ServerComponentProps = Annotations["ServerComponentProps"];
|
|
742
|
+
|
|
743
|
+
// ErrorBoundary
|
|
744
|
+
export type ErrorBoundaryProps = Annotations["ErrorBoundaryProps"];
|
|
745
|
+
|
|
746
|
+
// ServerErrorBoundary
|
|
747
|
+
export type ServerErrorBoundaryProps = Annotations["ServerErrorBoundaryProps"];
|
|
748
|
+
}
|
|
749
|
+
`
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function relativeImportSource(from, to) {
|
|
753
|
+
let path = Path.relative(Path.dirname(from), to);
|
|
754
|
+
let extension = Path.extname(path);
|
|
755
|
+
path = Path.join(Path.dirname(path), Path.basename(path, extension));
|
|
756
|
+
if (!path.startsWith("../")) path = "./" + path;
|
|
757
|
+
if (!extension || /\.(js|ts)x?$/.test(extension)) extension = ".js";
|
|
758
|
+
return path + extension;
|
|
759
|
+
}
|
|
760
|
+
function rootDirsPath(ctx, typesPath) {
|
|
761
|
+
const rel = Path.relative(typesDirectory(ctx), typesPath);
|
|
762
|
+
return Path.join(ctx.rootDirectory, rel);
|
|
763
|
+
}
|
|
764
|
+
function paramsType(path) {
|
|
765
|
+
const params = parse(path);
|
|
766
|
+
return t.tsTypeLiteral(Object.entries(params).map(([param, isRequired]) => {
|
|
767
|
+
const property = t.tsPropertySignature(t.stringLiteral(param), t.tsTypeAnnotation(t.tsStringKeyword()));
|
|
768
|
+
property.optional = !isRequired;
|
|
769
|
+
return property;
|
|
770
|
+
}));
|
|
771
|
+
}
|
|
772
|
+
function expand(fullpath) {
|
|
773
|
+
function recurse(segments, index) {
|
|
774
|
+
if (index === segments.length) return [""];
|
|
775
|
+
const segment = segments[index];
|
|
776
|
+
const isOptional = segment.endsWith("?");
|
|
777
|
+
const isDynamic = segment.startsWith(":");
|
|
778
|
+
const required = segment.replace(/\?$/, "");
|
|
779
|
+
const keep = !isOptional || isDynamic;
|
|
780
|
+
const kept = isDynamic ? segment : required;
|
|
781
|
+
const withoutSegment = recurse(segments, index + 1);
|
|
782
|
+
const withSegment = withoutSegment.map((rest) => [kept, rest].join("/"));
|
|
783
|
+
if (keep) return withSegment;
|
|
784
|
+
return [...withoutSegment, ...withSegment];
|
|
785
|
+
}
|
|
786
|
+
const segments = fullpath.split("/");
|
|
787
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
788
|
+
for (let result of recurse(segments, 0)) {
|
|
789
|
+
if (result !== "/") result = result.replace(/\/$/, "");
|
|
790
|
+
expanded.add(result);
|
|
791
|
+
}
|
|
792
|
+
return expanded;
|
|
793
|
+
}
|
|
794
|
+
//#endregion
|
|
795
|
+
//#region typegen/index.ts
|
|
796
|
+
const { green, red } = colors;
|
|
797
|
+
async function clearRouteModuleAnnotations(ctx) {
|
|
798
|
+
await fs$1.rm(Path.join(typesDirectory(ctx), Path.basename(ctx.config.appDirectory)), {
|
|
799
|
+
recursive: true,
|
|
800
|
+
force: true
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
async function write(...files) {
|
|
804
|
+
return Promise.all(files.map(async ({ filename, content }) => {
|
|
805
|
+
await fs$1.mkdir(Path.dirname(filename), { recursive: true });
|
|
806
|
+
await fs$1.writeFile(filename, content);
|
|
807
|
+
}));
|
|
808
|
+
}
|
|
809
|
+
async function run(rootDirectory, { mode, rsc }) {
|
|
810
|
+
const ctx = await createContext({
|
|
811
|
+
rootDirectory,
|
|
812
|
+
mode,
|
|
813
|
+
rsc,
|
|
814
|
+
watch: false
|
|
815
|
+
});
|
|
816
|
+
await fs$1.rm(typesDirectory(ctx), {
|
|
817
|
+
recursive: true,
|
|
818
|
+
force: true
|
|
819
|
+
});
|
|
820
|
+
await write(generateServerBuild(ctx), ...generateRoutes(ctx));
|
|
821
|
+
}
|
|
822
|
+
async function watch(rootDirectory, { mode, logger, rsc }) {
|
|
823
|
+
const ctx = await createContext({
|
|
824
|
+
rootDirectory,
|
|
825
|
+
mode,
|
|
826
|
+
rsc,
|
|
827
|
+
watch: true
|
|
828
|
+
});
|
|
829
|
+
await fs$1.rm(typesDirectory(ctx), {
|
|
830
|
+
recursive: true,
|
|
831
|
+
force: true
|
|
832
|
+
});
|
|
833
|
+
await write(generateServerBuild(ctx), ...generateRoutes(ctx));
|
|
834
|
+
logger?.info(green("generated types"), {
|
|
835
|
+
timestamp: true,
|
|
836
|
+
clear: true
|
|
837
|
+
});
|
|
838
|
+
ctx.configLoader.onChange(async ({ result, routeConfigChanged }) => {
|
|
839
|
+
if (!result.ok) {
|
|
840
|
+
logger?.error(red(result.error), {
|
|
841
|
+
timestamp: true,
|
|
842
|
+
clear: true
|
|
843
|
+
});
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
ctx.config = result.value;
|
|
847
|
+
if (routeConfigChanged) {
|
|
848
|
+
await clearRouteModuleAnnotations(ctx);
|
|
849
|
+
await write(...generateRoutes(ctx));
|
|
850
|
+
logger?.info(green("regenerated types"), {
|
|
851
|
+
timestamp: true,
|
|
852
|
+
clear: true
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
return { close: async () => await ctx.configLoader.close() };
|
|
857
|
+
}
|
|
858
|
+
//#endregion
|
|
859
|
+
export { t$1 as a, createConfigLoader as c, resolveRSCEntryFiles as d, ssrExternals as f, preloadVite as g, getVite as h, parse$1 as i, loadConfig as l, defineOptimizeDepsCompilerOptions as m, watch as n, traverse as o, defineCompilerOptions as p, generate as r, configRouteToBranchRoute as s, run as t, resolveEntryFiles as u };
|