reroute-js 0.0.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 +144 -0
- package/cli/bin.d.ts +3 -0
- package/cli/bin.d.ts.map +1 -0
- package/cli/bin.js +812 -0
- package/cli/bin.js.map +15 -0
- package/cli/src/commands/build.d.ts +8 -0
- package/cli/src/commands/build.d.ts.map +1 -0
- package/cli/src/commands/dev.d.ts +8 -0
- package/cli/src/commands/dev.d.ts.map +1 -0
- package/cli/src/commands/gen.d.ts +3 -0
- package/cli/src/commands/gen.d.ts.map +1 -0
- package/cli/src/commands/init.d.ts +8 -0
- package/cli/src/commands/init.d.ts.map +1 -0
- package/cli/src/index.d.ts +8 -0
- package/cli/src/index.d.ts.map +1 -0
- package/cli/src/libs/tailwind.d.ts +18 -0
- package/cli/src/libs/tailwind.d.ts.map +1 -0
- package/core/index.d.ts +2 -0
- package/core/index.d.ts.map +1 -0
- package/core/index.js +1174 -0
- package/core/index.js.map +25 -0
- package/core/src/bundler/hash.d.ts +2 -0
- package/core/src/bundler/hash.d.ts.map +1 -0
- package/core/src/bundler/index.d.ts +3 -0
- package/core/src/bundler/index.d.ts.map +1 -0
- package/core/src/bundler/transpile.d.ts +4 -0
- package/core/src/bundler/transpile.d.ts.map +1 -0
- package/core/src/content/builder.d.ts +2 -0
- package/core/src/content/builder.d.ts.map +1 -0
- package/core/src/content/discovery.d.ts +5 -0
- package/core/src/content/discovery.d.ts.map +1 -0
- package/core/src/content/index.d.ts +5 -0
- package/core/src/content/index.d.ts.map +1 -0
- package/core/src/content/metadata.d.ts +9 -0
- package/core/src/content/metadata.d.ts.map +1 -0
- package/core/src/content/registry.d.ts +2 -0
- package/core/src/content/registry.d.ts.map +1 -0
- package/core/src/index.d.ts +7 -0
- package/core/src/index.d.ts.map +1 -0
- package/core/src/ssr/data.d.ts +9 -0
- package/core/src/ssr/data.d.ts.map +1 -0
- package/core/src/ssr/index.d.ts +4 -0
- package/core/src/ssr/index.d.ts.map +1 -0
- package/core/src/ssr/modules.d.ts +8 -0
- package/core/src/ssr/modules.d.ts.map +1 -0
- package/core/src/ssr/render.d.ts +20 -0
- package/core/src/ssr/render.d.ts.map +1 -0
- package/core/src/ssr/seed.d.ts +2 -0
- package/core/src/ssr/seed.d.ts.map +1 -0
- package/core/src/template/html.d.ts +4 -0
- package/core/src/template/html.d.ts.map +1 -0
- package/core/src/template/index.d.ts +2 -0
- package/core/src/template/index.d.ts.map +1 -0
- package/core/src/types.d.ts +50 -0
- package/core/src/types.d.ts.map +1 -0
- package/core/src/utils/cache.d.ts +12 -0
- package/core/src/utils/cache.d.ts.map +1 -0
- package/core/src/utils/compression.d.ts +5 -0
- package/core/src/utils/compression.d.ts.map +1 -0
- package/core/src/utils/index.d.ts +5 -0
- package/core/src/utils/index.d.ts.map +1 -0
- package/core/src/utils/mime.d.ts +3 -0
- package/core/src/utils/mime.d.ts.map +1 -0
- package/core/src/utils/path.d.ts +6 -0
- package/core/src/utils/path.d.ts.map +1 -0
- package/elysia/index.d.ts +2 -0
- package/elysia/index.d.ts.map +1 -0
- package/elysia/index.js +1829 -0
- package/elysia/index.js.map +32 -0
- package/elysia/src/index.d.ts +3 -0
- package/elysia/src/index.d.ts.map +1 -0
- package/elysia/src/plugin.d.ts +32 -0
- package/elysia/src/plugin.d.ts.map +1 -0
- package/elysia/src/routes/artifacts.d.ts +3 -0
- package/elysia/src/routes/artifacts.d.ts.map +1 -0
- package/elysia/src/routes/content.d.ts +3 -0
- package/elysia/src/routes/content.d.ts.map +1 -0
- package/elysia/src/routes/dev.d.ts +7 -0
- package/elysia/src/routes/dev.d.ts.map +1 -0
- package/elysia/src/routes/ssr.d.ts +18 -0
- package/elysia/src/routes/ssr.d.ts.map +1 -0
- package/elysia/src/routes/static.d.ts +19 -0
- package/elysia/src/routes/static.d.ts.map +1 -0
- package/elysia/src/types.d.ts +31 -0
- package/elysia/src/types.d.ts.map +1 -0
- package/elysia/src/utils/http.d.ts +5 -0
- package/elysia/src/utils/http.d.ts.map +1 -0
- package/package.json +74 -0
- package/react/index.d.ts +2 -0
- package/react/index.d.ts.map +1 -0
- package/react/index.js +1152 -0
- package/react/index.js.map +23 -0
- package/react/src/components/ContentRoute.d.ts +13 -0
- package/react/src/components/ContentRoute.d.ts.map +1 -0
- package/react/src/components/Link.d.ts +8 -0
- package/react/src/components/Link.d.ts.map +1 -0
- package/react/src/components/Outlet.d.ts +7 -0
- package/react/src/components/Outlet.d.ts.map +1 -0
- package/react/src/components/index.d.ts +4 -0
- package/react/src/components/index.d.ts.map +1 -0
- package/react/src/hooks/index.d.ts +7 -0
- package/react/src/hooks/index.d.ts.map +1 -0
- package/react/src/hooks/useContent.d.ts +26 -0
- package/react/src/hooks/useContent.d.ts.map +1 -0
- package/react/src/hooks/useData.d.ts +10 -0
- package/react/src/hooks/useData.d.ts.map +1 -0
- package/react/src/hooks/useNavigate.d.ts +6 -0
- package/react/src/hooks/useNavigate.d.ts.map +1 -0
- package/react/src/hooks/useParams.d.ts +6 -0
- package/react/src/hooks/useParams.d.ts.map +1 -0
- package/react/src/hooks/useRouter.d.ts +7 -0
- package/react/src/hooks/useRouter.d.ts.map +1 -0
- package/react/src/hooks/useSearchParams.d.ts +6 -0
- package/react/src/hooks/useSearchParams.d.ts.map +1 -0
- package/react/src/index.d.ts +6 -0
- package/react/src/index.d.ts.map +1 -0
- package/react/src/providers/ContentProvider.d.ts +35 -0
- package/react/src/providers/ContentProvider.d.ts.map +1 -0
- package/react/src/providers/RerouteProvider.d.ts +25 -0
- package/react/src/providers/RerouteProvider.d.ts.map +1 -0
- package/react/src/providers/RouterProvider.d.ts +23 -0
- package/react/src/providers/RouterProvider.d.ts.map +1 -0
- package/react/src/providers/index.d.ts +4 -0
- package/react/src/providers/index.d.ts.map +1 -0
- package/react/src/types/any.d.ts +3 -0
- package/react/src/types/any.d.ts.map +1 -0
- package/react/src/types/index.d.ts +3 -0
- package/react/src/types/index.d.ts.map +1 -0
- package/react/src/types/router.d.ts +32 -0
- package/react/src/types/router.d.ts.map +1 -0
- package/react/src/utils/content.d.ts +8 -0
- package/react/src/utils/content.d.ts.map +1 -0
- package/react/src/utils/head.d.ts +6 -0
- package/react/src/utils/head.d.ts.map +1 -0
- package/react/src/utils/index.d.ts +3 -0
- package/react/src/utils/index.d.ts.map +1 -0
package/cli/bin.js
ADDED
|
@@ -0,0 +1,812 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
set: (newValue) => all[name] = () => newValue
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
14
|
+
|
|
15
|
+
// packages/cli/src/commands/init.ts
|
|
16
|
+
var exports_init = {};
|
|
17
|
+
__export(exports_init, {
|
|
18
|
+
default: () => init
|
|
19
|
+
});
|
|
20
|
+
import { existsSync } from "node:fs";
|
|
21
|
+
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
async function init(args) {
|
|
24
|
+
const options = parseArgs(args);
|
|
25
|
+
if (!options) {
|
|
26
|
+
printHelp();
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
await scaffoldProject(options);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error("Error scaffolding project:", error);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function parseArgs(args) {
|
|
37
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const projectName = args[0];
|
|
41
|
+
if (!projectName || projectName.startsWith("-")) {
|
|
42
|
+
console.error("Error: Project name is required");
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (!/^[a-z0-9-_]+$/i.test(projectName)) {
|
|
46
|
+
console.error("Error: Project name can only contain letters, numbers, hyphens, and underscores");
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
let template = "basic";
|
|
50
|
+
const templateIndex = args.indexOf("--template");
|
|
51
|
+
if (templateIndex !== -1 && args[templateIndex + 1]) {
|
|
52
|
+
const templateArg = args[templateIndex + 1];
|
|
53
|
+
if (templateArg === "basic" || templateArg === "blog") {
|
|
54
|
+
template = templateArg;
|
|
55
|
+
} else {
|
|
56
|
+
console.error(`Error: Unknown template "${templateArg}". Available templates: basic, blog`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { projectName, template };
|
|
61
|
+
}
|
|
62
|
+
async function scaffoldProject(options) {
|
|
63
|
+
const { projectName, template } = options;
|
|
64
|
+
const projectPath = join(process.cwd(), projectName);
|
|
65
|
+
if (existsSync(projectPath)) {
|
|
66
|
+
console.error(`Error: Directory "${projectName}" already exists`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
console.log(`
|
|
70
|
+
\uD83D\uDE80 Creating new Reroute project: ${projectName}`);
|
|
71
|
+
console.log(`\uD83D\uDCE6 Template: ${template}
|
|
72
|
+
`);
|
|
73
|
+
const templatePath = join(import.meta.dir, "..", "_", template);
|
|
74
|
+
if (!existsSync(templatePath)) {
|
|
75
|
+
console.error(`Error: Template directory not found at ${templatePath}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
await mkdir(projectPath, { recursive: true });
|
|
79
|
+
await copyTemplateFiles(templatePath, projectPath, {
|
|
80
|
+
PROJECT_NAME: projectName
|
|
81
|
+
});
|
|
82
|
+
console.log(`\uD83D\uDCE5 Installing dependencies...
|
|
83
|
+
`);
|
|
84
|
+
const proc = Bun.spawn(["bun", "install"], {
|
|
85
|
+
cwd: projectPath,
|
|
86
|
+
stdout: "inherit",
|
|
87
|
+
stderr: "inherit"
|
|
88
|
+
});
|
|
89
|
+
await proc.exited;
|
|
90
|
+
printSuccess(projectName, template);
|
|
91
|
+
}
|
|
92
|
+
async function copyTemplateFiles(templatePath, targetPath, variables) {
|
|
93
|
+
const entries = await readdir(templatePath, { withFileTypes: true });
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const sourcePath = join(templatePath, entry.name);
|
|
96
|
+
const destPath = join(targetPath, entry.name);
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
await mkdir(destPath, { recursive: true });
|
|
99
|
+
await copyTemplateFiles(sourcePath, destPath, variables);
|
|
100
|
+
} else if (entry.isFile()) {
|
|
101
|
+
const content = await readFile(sourcePath, "utf-8");
|
|
102
|
+
let processedContent = content;
|
|
103
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
104
|
+
const placeholder = `{{${key}}}`;
|
|
105
|
+
processedContent = processedContent.split(placeholder).join(value);
|
|
106
|
+
}
|
|
107
|
+
await writeFile(destPath, processedContent);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function printSuccess(projectName, template) {
|
|
112
|
+
console.log(`
|
|
113
|
+
✅ Project created successfully!
|
|
114
|
+
`);
|
|
115
|
+
console.log(`Next steps:
|
|
116
|
+
`);
|
|
117
|
+
console.log(` cd ${projectName}`);
|
|
118
|
+
console.log(` bun dev
|
|
119
|
+
`);
|
|
120
|
+
console.log(`Your app will be running at http://localhost:3000
|
|
121
|
+
`);
|
|
122
|
+
console.log("Project structure:");
|
|
123
|
+
console.log(" src/");
|
|
124
|
+
console.log(" ├── index.ts # Server entry point");
|
|
125
|
+
console.log(" └── client/");
|
|
126
|
+
console.log(" ├── App.tsx # Root React component");
|
|
127
|
+
console.log(" ├── index.tsx # Client entry point");
|
|
128
|
+
console.log(" ├── index.html # HTML template");
|
|
129
|
+
console.log(" ├── routes/ # File-based routes");
|
|
130
|
+
if (template === "blog") {
|
|
131
|
+
console.log(" │ ├── blog/");
|
|
132
|
+
console.log(" │ │ ├── content/ # Blog posts");
|
|
133
|
+
console.log(" │ │ ├── [slug].tsx");
|
|
134
|
+
console.log(" │ │ └── index.tsx");
|
|
135
|
+
}
|
|
136
|
+
console.log(" │ ├── index.tsx");
|
|
137
|
+
console.log(" │ └── about.tsx");
|
|
138
|
+
console.log(` └── components/ # React components
|
|
139
|
+
`);
|
|
140
|
+
console.log("Learn more at https://github.com/stewones/reroute");
|
|
141
|
+
}
|
|
142
|
+
function printHelp() {
|
|
143
|
+
console.log("reroute init - Scaffold a new Reroute project");
|
|
144
|
+
console.log("");
|
|
145
|
+
console.log("Usage:");
|
|
146
|
+
console.log(" reroute init <project-name> [options]");
|
|
147
|
+
console.log("");
|
|
148
|
+
console.log("Options:");
|
|
149
|
+
console.log(" --template <name> Template to use (basic, blog)");
|
|
150
|
+
console.log(" -h, --help Show help");
|
|
151
|
+
console.log("");
|
|
152
|
+
console.log("Examples:");
|
|
153
|
+
console.log(" reroute init my-app");
|
|
154
|
+
console.log(" reroute init my-blog --template blog");
|
|
155
|
+
}
|
|
156
|
+
var init_init = () => {};
|
|
157
|
+
|
|
158
|
+
// packages/cli/src/commands/build.ts
|
|
159
|
+
var exports_build = {};
|
|
160
|
+
__export(exports_build, {
|
|
161
|
+
default: () => build
|
|
162
|
+
});
|
|
163
|
+
async function build(_args) {
|
|
164
|
+
console.log("reroute build - Coming Soon");
|
|
165
|
+
console.log("");
|
|
166
|
+
console.log("This command will build your Reroute application for production.");
|
|
167
|
+
console.log("");
|
|
168
|
+
console.log("Planned usage:");
|
|
169
|
+
console.log(" reroute build");
|
|
170
|
+
console.log(" reroute build --minify");
|
|
171
|
+
console.log(" reroute build --analyze");
|
|
172
|
+
console.log("");
|
|
173
|
+
console.log("For now, please use your own build setup or check the examples.");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// packages/cli/src/commands/dev.ts
|
|
177
|
+
var exports_dev = {};
|
|
178
|
+
__export(exports_dev, {
|
|
179
|
+
default: () => dev
|
|
180
|
+
});
|
|
181
|
+
async function dev(_args) {
|
|
182
|
+
console.log("reroute dev - Coming Soon");
|
|
183
|
+
console.log("");
|
|
184
|
+
console.log("This command will start a development server with live reload.");
|
|
185
|
+
console.log("");
|
|
186
|
+
console.log("Planned usage:");
|
|
187
|
+
console.log(" reroute dev");
|
|
188
|
+
console.log(" reroute dev --port 3000");
|
|
189
|
+
console.log(" reroute dev --host 0.0.0.0");
|
|
190
|
+
console.log("");
|
|
191
|
+
console.log("Note: dev already generates content registry and static assets");
|
|
192
|
+
console.log("");
|
|
193
|
+
console.log("For now, please use your own dev server setup or check the examples.");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// packages/cli/src/libs/tailwind.ts
|
|
197
|
+
import { spawn } from "node:child_process";
|
|
198
|
+
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
199
|
+
import { join as join2 } from "node:path";
|
|
200
|
+
function isTailwindAvailable(cwd) {
|
|
201
|
+
const packageJsonPath = join2(cwd, "package.json");
|
|
202
|
+
if (!existsSync2(packageJsonPath)) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
207
|
+
const deps = {
|
|
208
|
+
...packageJson.dependencies,
|
|
209
|
+
...packageJson.devDependencies
|
|
210
|
+
};
|
|
211
|
+
return "@tailwindcss/cli" in deps;
|
|
212
|
+
} catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function getTailwindPaths(cwd) {
|
|
217
|
+
const input = join2(cwd, "src/client/theme.css");
|
|
218
|
+
const output = join2(cwd, ".reroute/theme.css");
|
|
219
|
+
return { input, output };
|
|
220
|
+
}
|
|
221
|
+
function hasTailwindInput(cwd) {
|
|
222
|
+
const { input } = getTailwindPaths(cwd);
|
|
223
|
+
if (!existsSync2(input)) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
const content = readFileSync(input, "utf-8");
|
|
228
|
+
return content.includes('@import "tailwindcss"');
|
|
229
|
+
} catch {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function resolveTailwindBin(cwd) {
|
|
234
|
+
const pathsToTry = [
|
|
235
|
+
join2(cwd, "node_modules/.bin/tailwindcss"),
|
|
236
|
+
join2(cwd, "../node_modules/.bin/tailwindcss"),
|
|
237
|
+
join2(cwd, "../../node_modules/.bin/tailwindcss"),
|
|
238
|
+
join2(cwd, "../../../node_modules/.bin/tailwindcss")
|
|
239
|
+
];
|
|
240
|
+
for (const binPath of pathsToTry) {
|
|
241
|
+
if (existsSync2(binPath)) {
|
|
242
|
+
return binPath;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return join2(cwd, "node_modules/.bin/tailwindcss");
|
|
246
|
+
}
|
|
247
|
+
async function buildTailwind(cwd) {
|
|
248
|
+
const { input, output } = getTailwindPaths(cwd);
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
const tailwindBin = resolveTailwindBin(cwd);
|
|
251
|
+
const args = ["-i", input, "-o", output];
|
|
252
|
+
const tailwind = spawn(tailwindBin, args, {
|
|
253
|
+
cwd,
|
|
254
|
+
stdio: "inherit"
|
|
255
|
+
});
|
|
256
|
+
tailwind.on("close", (code) => {
|
|
257
|
+
if (code === 0) {
|
|
258
|
+
resolve();
|
|
259
|
+
} else {
|
|
260
|
+
reject(new Error(`Tailwind CSS build failed with code ${code}`));
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
tailwind.on("error", (error) => {
|
|
264
|
+
reject(error);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
function watchTailwind(cwd) {
|
|
269
|
+
const { input, output } = getTailwindPaths(cwd);
|
|
270
|
+
const tailwindBin = resolveTailwindBin(cwd);
|
|
271
|
+
const args = ["-i", input, "-o", output, "--watch"];
|
|
272
|
+
console.log("[reroute/tailwind] Starting Tailwind CSS v4 in watch mode...");
|
|
273
|
+
const tailwind = spawn(tailwindBin, args, {
|
|
274
|
+
cwd,
|
|
275
|
+
stdio: "inherit"
|
|
276
|
+
});
|
|
277
|
+
tailwind.on("error", (error) => {
|
|
278
|
+
console.error("[reroute/tailwind] Error:", error);
|
|
279
|
+
});
|
|
280
|
+
const stop = () => {
|
|
281
|
+
console.log("[reroute/tailwind] Stopping Tailwind CSS...");
|
|
282
|
+
tailwind.kill();
|
|
283
|
+
};
|
|
284
|
+
return {
|
|
285
|
+
process: tailwind,
|
|
286
|
+
stop
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function initTailwind(cwd, watch = false) {
|
|
290
|
+
if (!isTailwindAvailable(cwd)) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
if (!hasTailwindInput(cwd)) {
|
|
294
|
+
console.log('[reroute/tailwind] theme.css not found or missing @import "tailwindcss", skipping...');
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
console.log("[reroute/tailwind] Detected Tailwind CSS v4");
|
|
298
|
+
if (watch) {
|
|
299
|
+
return watchTailwind(cwd);
|
|
300
|
+
}
|
|
301
|
+
buildTailwind(cwd).then(() => {
|
|
302
|
+
console.log("[reroute/tailwind] Built successfully");
|
|
303
|
+
}).catch((error) => {
|
|
304
|
+
console.error("[reroute/tailwind] Build failed:", error);
|
|
305
|
+
});
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
var init_tailwind = () => {};
|
|
309
|
+
|
|
310
|
+
// packages/cli/src/commands/gen.ts
|
|
311
|
+
var exports_gen = {};
|
|
312
|
+
__export(exports_gen, {
|
|
313
|
+
default: () => gen
|
|
314
|
+
});
|
|
315
|
+
import { watch } from "node:fs";
|
|
316
|
+
import { mkdir as mkdir2, readdir as readdir2, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
317
|
+
import { join as join3 } from "node:path";
|
|
318
|
+
import { pathToFileURL } from "node:url";
|
|
319
|
+
async function cleanupOutputDir(cwd) {
|
|
320
|
+
const outputPath = join3(cwd, OUTPUT_DIR);
|
|
321
|
+
try {
|
|
322
|
+
await rm(outputPath, { recursive: true, force: true });
|
|
323
|
+
console.log(`[reroute/gen] Cleaned up ${outputPath}`);
|
|
324
|
+
} catch {}
|
|
325
|
+
}
|
|
326
|
+
async function scanDirectory(dir, base = "") {
|
|
327
|
+
const files = [];
|
|
328
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
329
|
+
for (const entry of entries) {
|
|
330
|
+
const fullPath = join3(dir, entry.name);
|
|
331
|
+
const relativePath = join3(base, entry.name);
|
|
332
|
+
if (entry.isDirectory()) {
|
|
333
|
+
if (entry.name === "content")
|
|
334
|
+
continue;
|
|
335
|
+
const nested = await scanDirectory(fullPath, relativePath);
|
|
336
|
+
files.push(...nested);
|
|
337
|
+
} else if (entry.isFile() && (entry.name.endsWith(".tsx") || entry.name.endsWith(".ts"))) {
|
|
338
|
+
if (relativePath.includes("/content/") || relativePath.startsWith("content/")) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (!entry.name.startsWith("_") || entry.name === "[layout].tsx") {
|
|
342
|
+
files.push(relativePath);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return files;
|
|
347
|
+
}
|
|
348
|
+
async function scan404Files(dir, base = "") {
|
|
349
|
+
const files = [];
|
|
350
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
351
|
+
for (const entry of entries) {
|
|
352
|
+
const fullPath = join3(dir, entry.name);
|
|
353
|
+
const relativePath = join3(base, entry.name);
|
|
354
|
+
if (entry.isDirectory()) {
|
|
355
|
+
const nested = await scan404Files(fullPath, relativePath);
|
|
356
|
+
files.push(...nested);
|
|
357
|
+
} else if (entry.isFile()) {
|
|
358
|
+
if (/^\[404]\.(tsx|ts)$/.test(entry.name))
|
|
359
|
+
files.push(relativePath);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return files;
|
|
363
|
+
}
|
|
364
|
+
function fileToRoute(filePath) {
|
|
365
|
+
const isLayout = filePath.endsWith("[layout].tsx") || filePath.endsWith("[layout].ts");
|
|
366
|
+
let routePath = filePath.replace(/\.(tsx|ts)$/, "");
|
|
367
|
+
if (isLayout) {
|
|
368
|
+
routePath = routePath.replace(/[layout]$/, "").replace(/\/$/, "");
|
|
369
|
+
}
|
|
370
|
+
routePath = routePath.replace(/\/index$/, "").replace(/^index$/, "");
|
|
371
|
+
const params = [];
|
|
372
|
+
const pattern = routePath.replace(/\[([^\]]+)\]/g, (_, param) => {
|
|
373
|
+
params.push(param);
|
|
374
|
+
return `:${param}`;
|
|
375
|
+
});
|
|
376
|
+
const normalizedPattern = pattern === "" ? "/" : `/${pattern}`;
|
|
377
|
+
const isNotFound = /(^|\/)\[404\]$/.test(routePath);
|
|
378
|
+
let notFoundBasePattern;
|
|
379
|
+
if (isNotFound) {
|
|
380
|
+
const base = routePath.replace(/(^|\/)\[404\]$/, "").replace(/\/$/, "");
|
|
381
|
+
notFoundBasePattern = base ? `/${base}` : "/";
|
|
382
|
+
}
|
|
383
|
+
return {
|
|
384
|
+
path: routePath,
|
|
385
|
+
pattern: normalizedPattern,
|
|
386
|
+
filePath,
|
|
387
|
+
isLayout,
|
|
388
|
+
isDynamic: params.length > 0,
|
|
389
|
+
params,
|
|
390
|
+
isNotFound,
|
|
391
|
+
notFoundBasePattern
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function sortRoutes(routes) {
|
|
395
|
+
return routes.sort((a, b) => {
|
|
396
|
+
const aDepth = a.pattern.split("/").length;
|
|
397
|
+
const bDepth = b.pattern.split("/").length;
|
|
398
|
+
if (aDepth !== bDepth)
|
|
399
|
+
return bDepth - aDepth;
|
|
400
|
+
if (!a.isDynamic && b.isDynamic)
|
|
401
|
+
return -1;
|
|
402
|
+
if (a.isDynamic && !b.isDynamic)
|
|
403
|
+
return 1;
|
|
404
|
+
return a.pattern.localeCompare(b.pattern);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function generateRouteTree(files) {
|
|
408
|
+
const routes = [];
|
|
409
|
+
const layouts = [];
|
|
410
|
+
const notFoundRoutes = [];
|
|
411
|
+
for (const file of files) {
|
|
412
|
+
const route = fileToRoute(file);
|
|
413
|
+
if (route.isLayout) {
|
|
414
|
+
layouts.push(route);
|
|
415
|
+
} else if (route.isNotFound) {
|
|
416
|
+
notFoundRoutes.push(route);
|
|
417
|
+
} else {
|
|
418
|
+
routes.push(route);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
routes: sortRoutes(routes),
|
|
423
|
+
layouts,
|
|
424
|
+
notFoundRoutes
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function generateTypeScript(tree) {
|
|
428
|
+
const imports = [
|
|
429
|
+
...tree.routes.map((r, i) => `import Route${i} from '../src/client/routes/${r.filePath.replace(/\.(tsx|ts)$/, "")}';`),
|
|
430
|
+
...tree.layouts.map((l, i) => `import Layout${i} from '../src/client/routes/${l.filePath.replace(/\.(tsx|ts)$/, "")}';`),
|
|
431
|
+
...tree.notFoundRoutes.map((nf, i) => `import NotFound${i} from '../src/client/routes/${nf.filePath.replace(/\.(tsx|ts)$/, "")}';`)
|
|
432
|
+
].join(`
|
|
433
|
+
`);
|
|
434
|
+
const routesArray = tree.routes.map((r, i) => {
|
|
435
|
+
return ` {
|
|
436
|
+
pattern: "${r.pattern}",
|
|
437
|
+
path: "${r.path}",
|
|
438
|
+
component: Route${i},
|
|
439
|
+
params: ${JSON.stringify(r.params)},
|
|
440
|
+
isDynamic: ${r.isDynamic},
|
|
441
|
+
} as const`;
|
|
442
|
+
}).join(`,
|
|
443
|
+
`);
|
|
444
|
+
const routePatterns = tree.routes.map((r) => ` | "${r.pattern}"`).join(`
|
|
445
|
+
`);
|
|
446
|
+
const routeParamsUnion = tree.routes.filter((r) => r.isDynamic).map((r) => {
|
|
447
|
+
const params = r.params.map((p) => `${p}: string`).join("; ");
|
|
448
|
+
return ` T extends "${r.pattern}" ? { ${params} } :`;
|
|
449
|
+
}).join(`
|
|
450
|
+
`);
|
|
451
|
+
const layoutsArray = tree.layouts.map((l, i) => {
|
|
452
|
+
return ` {
|
|
453
|
+
pattern: "${l.pattern}",
|
|
454
|
+
path: "${l.path}",
|
|
455
|
+
component: Layout${i},
|
|
456
|
+
} as const`;
|
|
457
|
+
}).join(`,
|
|
458
|
+
`);
|
|
459
|
+
const notFoundRoutesArray = tree.notFoundRoutes.map((nf, i) => {
|
|
460
|
+
return ` {
|
|
461
|
+
pattern: "${nf.notFoundBasePattern || "/"}",
|
|
462
|
+
path: "${nf.path}",
|
|
463
|
+
component: NotFound${i},
|
|
464
|
+
} as const`;
|
|
465
|
+
}).join(`,
|
|
466
|
+
`);
|
|
467
|
+
return `// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8
|
|
468
|
+
/* eslint-disable */
|
|
469
|
+
// @ts-nocheck
|
|
470
|
+
|
|
471
|
+
${imports}
|
|
472
|
+
|
|
473
|
+
export const routes: RouteInfo = [
|
|
474
|
+
${routesArray}
|
|
475
|
+
] as const;
|
|
476
|
+
|
|
477
|
+
export const layouts = [
|
|
478
|
+
${layoutsArray || ""}
|
|
479
|
+
] as const;
|
|
480
|
+
|
|
481
|
+
export const notFoundRoutes = [
|
|
482
|
+
${notFoundRoutesArray || ""}
|
|
483
|
+
] as const;
|
|
484
|
+
|
|
485
|
+
export type RoutePath =
|
|
486
|
+
${routePatterns || ' | "/"'};
|
|
487
|
+
|
|
488
|
+
export type RouteParams<T extends RoutePath> = ${routeParamsUnion ? `
|
|
489
|
+
${routeParamsUnion}
|
|
490
|
+
Record<string, never>;` : "Record<string, never>;"}
|
|
491
|
+
|
|
492
|
+
export interface Route {
|
|
493
|
+
pattern: string;
|
|
494
|
+
path: string;
|
|
495
|
+
component: any;
|
|
496
|
+
params: string[];
|
|
497
|
+
isDynamic: boolean;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export function matchRoute(pathname: string): { route: Route; params: Record<string, string> } | null {
|
|
501
|
+
for (const route of routes) {
|
|
502
|
+
const match = matchPattern(route.pattern, pathname);
|
|
503
|
+
if (match) {
|
|
504
|
+
return { route, params: match };
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function matchPattern(pattern: string, pathname: string): Record<string, string> | null {
|
|
511
|
+
const patternParts = pattern.split('/').filter(Boolean);
|
|
512
|
+
const pathnameParts = pathname.split('/').filter(Boolean);
|
|
513
|
+
|
|
514
|
+
if (patternParts.length !== pathnameParts.length) {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const params: Record<string, string> = {};
|
|
519
|
+
|
|
520
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
521
|
+
const patternPart = patternParts[i];
|
|
522
|
+
const pathnamePart = pathnameParts[i];
|
|
523
|
+
|
|
524
|
+
if (patternPart.startsWith(':')) {
|
|
525
|
+
params[patternPart.slice(1)] = pathnamePart;
|
|
526
|
+
} else if (patternPart !== pathnamePart) {
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return params;
|
|
532
|
+
}
|
|
533
|
+
`;
|
|
534
|
+
}
|
|
535
|
+
async function listContentFiles(collectionDir) {
|
|
536
|
+
try {
|
|
537
|
+
const entries = await readdir2(collectionDir, { withFileTypes: true });
|
|
538
|
+
return entries.filter((e) => e.isFile() && /\.(tsx|ts)$/.test(e.name) && !e.name.startsWith("_")).map((e) => e.name);
|
|
539
|
+
} catch {
|
|
540
|
+
return [];
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
async function sha8(text) {
|
|
544
|
+
const data = new TextEncoder().encode(text);
|
|
545
|
+
const buf = await crypto.subtle.digest("SHA-256", data);
|
|
546
|
+
let hex = "";
|
|
547
|
+
for (const b of new Uint8Array(buf))
|
|
548
|
+
hex += b.toString(16).padStart(2, "0");
|
|
549
|
+
return hex.slice(0, 8);
|
|
550
|
+
}
|
|
551
|
+
async function buildContentChunks(cwd) {
|
|
552
|
+
const routesRoot = join3(cwd, ROUTES_DIR);
|
|
553
|
+
console.log(`[reroute/content] scan ${routesRoot}`);
|
|
554
|
+
const collections = await readdir2(routesRoot, { withFileTypes: true });
|
|
555
|
+
const results = [];
|
|
556
|
+
for (const c of collections) {
|
|
557
|
+
if (!c.isDirectory())
|
|
558
|
+
continue;
|
|
559
|
+
const collection = c.name;
|
|
560
|
+
const contentDir = join3(routesRoot, collection, "content");
|
|
561
|
+
console.log(`[reroute/content] collection ${collection} dir ${contentDir}`);
|
|
562
|
+
const files = await listContentFiles(contentDir);
|
|
563
|
+
console.log(`[reroute/content] files ${files.join(",")}`);
|
|
564
|
+
if (!files.length)
|
|
565
|
+
continue;
|
|
566
|
+
for (const file of files) {
|
|
567
|
+
const name = file.replace(/\.(tsx|ts)$/, "");
|
|
568
|
+
const absSrc = join3(contentDir, file);
|
|
569
|
+
let code = "";
|
|
570
|
+
try {
|
|
571
|
+
console.log(`[reroute/content] build ${absSrc}`);
|
|
572
|
+
const result = await Bun.build({
|
|
573
|
+
entrypoints: [absSrc],
|
|
574
|
+
target: "browser",
|
|
575
|
+
format: "esm",
|
|
576
|
+
splitting: false,
|
|
577
|
+
sourcemap: "none",
|
|
578
|
+
minify: false,
|
|
579
|
+
define: { "process.env.NODE_ENV": '"production"' }
|
|
580
|
+
});
|
|
581
|
+
if (!result.success)
|
|
582
|
+
throw new Error("build failed");
|
|
583
|
+
code = await result.outputs[0].text();
|
|
584
|
+
} catch (e) {
|
|
585
|
+
console.error("[reroute/gen] Failed to build content chunk:", absSrc, e);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
const hash = await sha8(code);
|
|
589
|
+
const chunkRelDir = join3(".reroute", "chunks", collection);
|
|
590
|
+
const chunkAbsDir = join3(cwd, chunkRelDir);
|
|
591
|
+
const outFile = `${name}.${hash}.js`;
|
|
592
|
+
const absOut = join3(chunkAbsDir, outFile);
|
|
593
|
+
await mkdir2(chunkAbsDir, { recursive: true });
|
|
594
|
+
try {
|
|
595
|
+
const exists = await Bun.file(absOut).exists();
|
|
596
|
+
if (!exists)
|
|
597
|
+
await writeFile2(absOut, code, "utf-8");
|
|
598
|
+
} catch {}
|
|
599
|
+
let meta = {};
|
|
600
|
+
try {
|
|
601
|
+
console.log(`[reroute/content] meta ${absSrc}`);
|
|
602
|
+
const url = `${pathToFileURL(absSrc).href}?t=${Date.now()}`;
|
|
603
|
+
const m = await import(url);
|
|
604
|
+
meta = m.meta || {};
|
|
605
|
+
} catch {}
|
|
606
|
+
results.push({
|
|
607
|
+
collection,
|
|
608
|
+
name,
|
|
609
|
+
slug: name,
|
|
610
|
+
href: `/${collection}/${name}`,
|
|
611
|
+
moduleUrl: ("/" + chunkRelDir.replace(/\\/g, "/") + "/" + outFile).replace(/\\+/g, "/"),
|
|
612
|
+
meta
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
const lines = [];
|
|
617
|
+
lines.push("// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8");
|
|
618
|
+
lines.push("/* eslint-disable */");
|
|
619
|
+
lines.push("// @ts-nocheck");
|
|
620
|
+
lines.push("");
|
|
621
|
+
lines.push("export const contents = [");
|
|
622
|
+
for (const e of results) {
|
|
623
|
+
lines.push(" { collection: '" + e.collection + "', slug: '" + e.slug + "', name: '" + e.name + "', href: '" + e.href + "', module: '" + e.moduleUrl + "', meta: " + JSON.stringify(e.meta || {}) + " },");
|
|
624
|
+
}
|
|
625
|
+
lines.push("] as const;");
|
|
626
|
+
lines.push("");
|
|
627
|
+
lines.push("export const byCollection: Record<string, any[]> = {};");
|
|
628
|
+
lines.push("for (const c of contents) { (byCollection[c.collection] ||= []).push(c as any); }");
|
|
629
|
+
lines.push("");
|
|
630
|
+
lines.push("export const byCollectionAndName: Record<string, Record<string, any>> = {};");
|
|
631
|
+
lines.push("for (const c of contents) { ((byCollectionAndName[c.collection] ||= {})[c.name] = c as any); }");
|
|
632
|
+
lines.push("");
|
|
633
|
+
lines.push("export type Collections = keyof typeof byCollection;");
|
|
634
|
+
lines.push("export type Names<C extends Collections> = keyof (typeof byCollectionAndName)[C];");
|
|
635
|
+
lines.push("export type ContentEntry = (typeof contents)[number];");
|
|
636
|
+
lines.push("");
|
|
637
|
+
lines.push("export function getContentEntry<C extends string, N extends string>(collection: C, name: N) {");
|
|
638
|
+
lines.push(" const m = (byCollectionAndName as any)[collection];");
|
|
639
|
+
lines.push(" return m ? (m as Record<string, any>)[name] : undefined;");
|
|
640
|
+
lines.push("}");
|
|
641
|
+
lines.push("");
|
|
642
|
+
await mkdir2(join3(cwd, ".reroute"), { recursive: true });
|
|
643
|
+
await writeFile2(join3(cwd, OUTPUT_CONTENT_TS), lines.join(`
|
|
644
|
+
`), "utf-8");
|
|
645
|
+
console.log(`[reroute/content] wrote ${join3(cwd, OUTPUT_CONTENT_TS)}`);
|
|
646
|
+
const collectionsSet = new Set(results.map((r) => r.collection));
|
|
647
|
+
await mkdir2(join3(cwd, OUTPUT_COLLECTIONS_DIR), { recursive: true });
|
|
648
|
+
for (const collection of collectionsSet) {
|
|
649
|
+
const items = results.filter((r) => r.collection === collection);
|
|
650
|
+
const js = [];
|
|
651
|
+
js.push("// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8");
|
|
652
|
+
js.push("");
|
|
653
|
+
js.push("export const items = [");
|
|
654
|
+
for (const e of items) {
|
|
655
|
+
js.push(` { collection: '${e.collection}', slug: '${e.slug}', name: '${e.name}', href: '${e.href}', module: '${e.moduleUrl}', meta: ${JSON.stringify(e.meta || {})} },`);
|
|
656
|
+
}
|
|
657
|
+
js.push("];");
|
|
658
|
+
js.push("");
|
|
659
|
+
js.push("export const byName = {};");
|
|
660
|
+
js.push("for (const it of items) { byName[it.name] = it; }");
|
|
661
|
+
js.push("");
|
|
662
|
+
js.push("export function get(collectionName, name) {");
|
|
663
|
+
js.push(` if (collectionName !== '${collection}') return undefined;`);
|
|
664
|
+
js.push(" return byName[name];");
|
|
665
|
+
js.push("}");
|
|
666
|
+
js.push("");
|
|
667
|
+
await writeFile2(join3(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`), js.join(`
|
|
668
|
+
`), "utf-8");
|
|
669
|
+
console.log(`[reroute/content] wrote ${join3(cwd, OUTPUT_COLLECTIONS_DIR, `${collection}.js`)}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
async function generate(cwd) {
|
|
673
|
+
console.log("[reroute/gen] Starting generation...");
|
|
674
|
+
await cleanupOutputDir(cwd);
|
|
675
|
+
const routesPath = join3(cwd, ROUTES_DIR);
|
|
676
|
+
try {
|
|
677
|
+
const files = await scanDirectory(routesPath);
|
|
678
|
+
const nfFiles = await scan404Files(routesPath);
|
|
679
|
+
const all = Array.from(new Set([...files, ...nfFiles]));
|
|
680
|
+
const tree = generateRouteTree(all.map((f) => f.replace(/\\/g, "/")));
|
|
681
|
+
const ts = generateTypeScript(tree);
|
|
682
|
+
await mkdir2(join3(cwd, ".reroute"), { recursive: true });
|
|
683
|
+
await writeFile2(join3(cwd, OUTPUT_ROUTES), ts, "utf-8");
|
|
684
|
+
console.log(`[reroute/gen] Generated routes: ${join3(cwd, OUTPUT_ROUTES)}`);
|
|
685
|
+
} catch (error) {
|
|
686
|
+
console.error("[reroute/gen] Failed to generate routes:", error);
|
|
687
|
+
throw error;
|
|
688
|
+
}
|
|
689
|
+
try {
|
|
690
|
+
await buildContentChunks(cwd);
|
|
691
|
+
console.log(`[reroute/gen] Generated content: ${join3(cwd, OUTPUT_CONTENT_TS)} + collections/*.js`);
|
|
692
|
+
} catch (error) {
|
|
693
|
+
console.error("[reroute/gen] Failed to generate content:", error);
|
|
694
|
+
throw error;
|
|
695
|
+
}
|
|
696
|
+
const indexLines = [];
|
|
697
|
+
indexLines.push("// \uD83D\uDEA8 Auto-generated by Reroute - DO NOT EDIT \uD83D\uDEA8");
|
|
698
|
+
indexLines.push("/* eslint-disable */");
|
|
699
|
+
indexLines.push("// @ts-nocheck");
|
|
700
|
+
indexLines.push("");
|
|
701
|
+
indexLines.push("import { layouts, matchRoute, notFoundRoutes } from './routes';");
|
|
702
|
+
indexLines.push("");
|
|
703
|
+
indexLines.push("export const artifacts = {");
|
|
704
|
+
indexLines.push(" layouts,");
|
|
705
|
+
indexLines.push(" matchRoute,");
|
|
706
|
+
indexLines.push(" notFoundRoutes,");
|
|
707
|
+
indexLines.push(" contentBaseUrl: '/.reroute/collections'");
|
|
708
|
+
indexLines.push("} as const;");
|
|
709
|
+
indexLines.push("");
|
|
710
|
+
indexLines.push("export type RerouteArtifacts = typeof artifacts;");
|
|
711
|
+
await writeFile2(join3(cwd, OUTPUT_INDEX), indexLines.join(`
|
|
712
|
+
`), "utf-8");
|
|
713
|
+
console.log(`[reroute/gen] Generated index: ${join3(cwd, OUTPUT_INDEX)}`);
|
|
714
|
+
console.log("[reroute/gen] ✅ Generation complete!");
|
|
715
|
+
}
|
|
716
|
+
async function gen(args) {
|
|
717
|
+
const watchMode = args.includes("--watch") || args.includes("-w");
|
|
718
|
+
const cwd = process.cwd();
|
|
719
|
+
if (watchMode) {
|
|
720
|
+
console.log("[reroute/gen] Watch mode enabled");
|
|
721
|
+
console.log("[reroute/gen] Initial generation...");
|
|
722
|
+
await generate(cwd);
|
|
723
|
+
const tailwindProcess = initTailwind(cwd, true);
|
|
724
|
+
const routesPath = join3(cwd, ROUTES_DIR);
|
|
725
|
+
console.log(`[reroute/gen] Watching ${routesPath} for changes...`);
|
|
726
|
+
let timeout = null;
|
|
727
|
+
const watcher = watch(routesPath, { recursive: true }, (_eventType, filename) => {
|
|
728
|
+
if (!filename)
|
|
729
|
+
return;
|
|
730
|
+
if (timeout)
|
|
731
|
+
clearTimeout(timeout);
|
|
732
|
+
timeout = setTimeout(async () => {
|
|
733
|
+
console.log("[reroute/gen] Change detected, regenerating...");
|
|
734
|
+
try {
|
|
735
|
+
await generate(cwd);
|
|
736
|
+
} catch (error) {
|
|
737
|
+
console.error("[reroute/gen] Error during regeneration:", error);
|
|
738
|
+
}
|
|
739
|
+
}, 300);
|
|
740
|
+
});
|
|
741
|
+
process.on("SIGINT", () => {
|
|
742
|
+
console.log(`
|
|
743
|
+
[reroute/gen] Stopping watch mode...`);
|
|
744
|
+
watcher.close();
|
|
745
|
+
if (tailwindProcess) {
|
|
746
|
+
tailwindProcess.stop();
|
|
747
|
+
}
|
|
748
|
+
process.exit(0);
|
|
749
|
+
});
|
|
750
|
+
} else {
|
|
751
|
+
await generate(cwd);
|
|
752
|
+
initTailwind(cwd, false);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
var ROUTES_DIR = "src/client/routes", OUTPUT_DIR = ".reroute", OUTPUT_ROUTES = ".reroute/routes.ts", OUTPUT_CONTENT_TS = ".reroute/content.ts", OUTPUT_COLLECTIONS_DIR = ".reroute/collections", OUTPUT_INDEX = ".reroute/index.ts";
|
|
756
|
+
var init_gen = __esm(() => {
|
|
757
|
+
init_tailwind();
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
// packages/cli/src/index.ts
|
|
761
|
+
var commands = {
|
|
762
|
+
init: () => Promise.resolve().then(() => (init_init(), exports_init)),
|
|
763
|
+
build: () => Promise.resolve().then(() => exports_build),
|
|
764
|
+
dev: () => Promise.resolve().then(() => exports_dev),
|
|
765
|
+
gen: () => Promise.resolve().then(() => (init_gen(), exports_gen))
|
|
766
|
+
};
|
|
767
|
+
async function main() {
|
|
768
|
+
const args = process.argv.slice(2);
|
|
769
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
|
|
770
|
+
printHelp2();
|
|
771
|
+
process.exit(0);
|
|
772
|
+
}
|
|
773
|
+
const command = args[0];
|
|
774
|
+
if (!commands[command]) {
|
|
775
|
+
console.error(`Unknown command: ${command}`);
|
|
776
|
+
console.error("");
|
|
777
|
+
printHelp2();
|
|
778
|
+
process.exit(1);
|
|
779
|
+
}
|
|
780
|
+
try {
|
|
781
|
+
const module = await commands[command]();
|
|
782
|
+
await module.default(args.slice(1));
|
|
783
|
+
} catch (error) {
|
|
784
|
+
console.error("Error executing command:", error);
|
|
785
|
+
process.exit(1);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
function printHelp2() {
|
|
789
|
+
console.log("Reroute CLI - File-based routing framework");
|
|
790
|
+
console.log("");
|
|
791
|
+
console.log("Usage:");
|
|
792
|
+
console.log(" reroute <command> [options]");
|
|
793
|
+
console.log("");
|
|
794
|
+
console.log("Commands:");
|
|
795
|
+
console.log(" gen Generate content registry and static assets");
|
|
796
|
+
console.log(" init Scaffold a new Reroute project");
|
|
797
|
+
console.log(" build Build for production");
|
|
798
|
+
console.log(" dev Start development server");
|
|
799
|
+
console.log("");
|
|
800
|
+
console.log("Options:");
|
|
801
|
+
console.log(" -h, --help Show help");
|
|
802
|
+
console.log("");
|
|
803
|
+
console.log("Examples:");
|
|
804
|
+
console.log(" reroute gen");
|
|
805
|
+
console.log(" reroute gen --watch");
|
|
806
|
+
console.log(" reroute init my-app");
|
|
807
|
+
console.log(" reroute build --minify");
|
|
808
|
+
console.log(" reroute dev --port 3000");
|
|
809
|
+
}
|
|
810
|
+
main();
|
|
811
|
+
|
|
812
|
+
//# debugId=EE3FCBAF7FD3057864756E2164756E21
|