bun-plugin-stx 0.2.413 → 0.2.414
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/dist/{chunk-anqecs1e.js → chunk-18kmm7vg.js} +10 -10
- package/dist/chunk-jmbnee6y.js +286 -0
- package/dist/{chunk-93ete56h.js → chunk-qcdy1k88.js} +1 -1
- package/dist/client.js +3 -5
- package/dist/index.js +16 -17
- package/dist/preload.js +1 -2
- package/dist/serve.js +100 -104
- package/package.json +3 -3
- package/dist/chunk-2mx7fq49.js +0 -4
- package/dist/chunk-g7br5ehx.js +0 -4292
|
@@ -33,7 +33,7 @@ function shouldWatch(filePath, options) {
|
|
|
33
33
|
}
|
|
34
34
|
return true;
|
|
35
35
|
}
|
|
36
|
-
function
|
|
36
|
+
function createWatcher2(options = {}) {
|
|
37
37
|
const watchedPaths = new Set;
|
|
38
38
|
const watchers = new Map;
|
|
39
39
|
let isActive = true;
|
|
@@ -127,7 +127,7 @@ function createWatcher(options = {}) {
|
|
|
127
127
|
isWatching: () => isActive && watchers.size > 0
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
async function
|
|
130
|
+
async function watchAndBuild2(options) {
|
|
131
131
|
const {
|
|
132
132
|
entrypoints,
|
|
133
133
|
outdir = "./dist",
|
|
@@ -145,7 +145,7 @@ async function watchAndBuild(options) {
|
|
|
145
145
|
const result = await Bun.build({
|
|
146
146
|
entrypoints,
|
|
147
147
|
outdir,
|
|
148
|
-
plugins: [
|
|
148
|
+
plugins: [stxPlugin2(stxOptions)],
|
|
149
149
|
...buildConfig
|
|
150
150
|
});
|
|
151
151
|
const duration = Date.now() - startTime;
|
|
@@ -193,7 +193,7 @@ async function watchAndBuild(options) {
|
|
|
193
193
|
dirsToWatch.add(fullPath);
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
-
const watcher =
|
|
196
|
+
const watcher = createWatcher2({
|
|
197
197
|
...watchOptions,
|
|
198
198
|
paths: watchOptions.paths || Array.from(dirsToWatch),
|
|
199
199
|
onChange: async (event) => {
|
|
@@ -215,9 +215,9 @@ async function watchAndBuild(options) {
|
|
|
215
215
|
}
|
|
216
216
|
return watcher;
|
|
217
217
|
}
|
|
218
|
-
async function
|
|
218
|
+
async function startWatchMode2(args) {
|
|
219
219
|
console.log("\x1B[36m[stx]\x1B[0m Starting watch mode...");
|
|
220
|
-
const watcher = await
|
|
220
|
+
const watcher = await watchAndBuild2({
|
|
221
221
|
entrypoints: args.entrypoints,
|
|
222
222
|
outdir: args.outdir,
|
|
223
223
|
verbose: args.verbose,
|
|
@@ -248,7 +248,7 @@ async function startWatchMode(args) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// src/index.ts
|
|
251
|
-
import { createMiddleware, createRoute, readMarkdownFile as readMarkdownFile2 } from "@stacksjs/stx";
|
|
251
|
+
import { createMiddleware as createMiddleware2, createRoute as createRoute2, readMarkdownFile as readMarkdownFile2 } from "@stacksjs/stx";
|
|
252
252
|
function escapeHtmlForError(str) {
|
|
253
253
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
254
254
|
}
|
|
@@ -273,7 +273,7 @@ function generateErrorPage(title, message, filePath) {
|
|
|
273
273
|
</body>
|
|
274
274
|
</html>`;
|
|
275
275
|
}
|
|
276
|
-
function
|
|
276
|
+
function stxPlugin2(userOptions) {
|
|
277
277
|
return {
|
|
278
278
|
name: "bun-plugin-stx",
|
|
279
279
|
async setup(build) {
|
|
@@ -462,6 +462,6 @@ ${scriptsHtml}`;
|
|
|
462
462
|
}
|
|
463
463
|
};
|
|
464
464
|
}
|
|
465
|
-
var src_default =
|
|
465
|
+
var src_default = stxPlugin2;
|
|
466
466
|
|
|
467
|
-
export {
|
|
467
|
+
export { createWatcher2, watchAndBuild2, startWatchMode2, stxPlugin2, createMiddleware2, createRoute2, readMarkdownFile2, src_default };
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../router/src/file-router.ts
|
|
3
|
+
import fs3 from "fs";
|
|
4
|
+
import path4 from "path";
|
|
5
|
+
|
|
6
|
+
// ../router/src/codegen.ts
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
|
|
10
|
+
// ../router/src/page-routes.ts
|
|
11
|
+
var NON_PAGE_DIRS = ["components", "layouts", "partials", "emails"];
|
|
12
|
+
function isNonPageRoutePath(relativePath) {
|
|
13
|
+
const segments = relativePath.split(/[\\/]/).filter(Boolean);
|
|
14
|
+
return segments.slice(0, -1).some((segment) => NON_PAGE_DIRS.includes(segment));
|
|
15
|
+
}
|
|
16
|
+
function isNonPageRoutePattern(pattern) {
|
|
17
|
+
return isNonPageRoutePath(pattern.replace(/^\//, ""));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ../router/src/codegen.ts
|
|
21
|
+
function generateRouteTypes(routes, outputDir) {
|
|
22
|
+
const pageRoutes = routes.filter((r) => !isNonPageRoutePattern(r.pattern));
|
|
23
|
+
const lines = ["// Auto-generated by STX - do not edit"];
|
|
24
|
+
if (pageRoutes.length === 0) {
|
|
25
|
+
lines.push("// No page routes found \u2014 route paths stay typed as string.", "export {}", "");
|
|
26
|
+
} else {
|
|
27
|
+
lines.push(`declare module '@stacksjs/stx' {`, " interface KnownRoutes {");
|
|
28
|
+
for (const route of pageRoutes) {
|
|
29
|
+
const paramEntries = [];
|
|
30
|
+
for (const p of route.params) {
|
|
31
|
+
const optional = route.pattern.includes(`:${p}?`) ? "?" : "";
|
|
32
|
+
paramEntries.push(`${p}${optional}: string`);
|
|
33
|
+
}
|
|
34
|
+
const paramsStr = paramEntries.join("; ");
|
|
35
|
+
lines.push(` '${route.pattern}': { ${paramsStr} }`);
|
|
36
|
+
}
|
|
37
|
+
lines.push(" }", "}", "", "export {}", "");
|
|
38
|
+
}
|
|
39
|
+
const contents = lines.join(`
|
|
40
|
+
`);
|
|
41
|
+
const target = path.join(outputDir, "route-types.d.ts");
|
|
42
|
+
try {
|
|
43
|
+
if (fs.existsSync(target) && fs.readFileSync(target, "utf8") === contents)
|
|
44
|
+
return;
|
|
45
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
46
|
+
fs.writeFileSync(target, contents);
|
|
47
|
+
} catch {}
|
|
48
|
+
}
|
|
49
|
+
function generateRouteManifest(routes, outputDir, pagesDir) {
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const relativePages = path.relative(cwd, pagesDir);
|
|
52
|
+
const pageRoutes = routes.filter((r) => !isNonPageRoutePattern(r.pattern));
|
|
53
|
+
const lines = [
|
|
54
|
+
"// Auto-generated by stx \u2014 do not edit",
|
|
55
|
+
`// Source: ${relativePages || "pages"}/`,
|
|
56
|
+
"",
|
|
57
|
+
"export const routes = ["
|
|
58
|
+
];
|
|
59
|
+
for (const route of pageRoutes) {
|
|
60
|
+
const relFile = path.relative(cwd, route.filePath).replace(/\\/g, "/");
|
|
61
|
+
const params = JSON.stringify(route.params);
|
|
62
|
+
const layoutStr = route.layout ? `, layout: '${path.relative(cwd, route.layout).replace(/\\/g, "/")}'` : "";
|
|
63
|
+
lines.push(` { pattern: '${route.pattern}', filePath: '${relFile}', isDynamic: ${route.isDynamic}, params: ${params}${layoutStr} },`);
|
|
64
|
+
}
|
|
65
|
+
lines.push("] as const", "");
|
|
66
|
+
lines.push("export type RouteName = typeof routes[number]['pattern']", "");
|
|
67
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
68
|
+
fs.writeFileSync(path.join(outputDir, "routes.ts"), lines.join(`
|
|
69
|
+
`));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ../router/src/matcher.ts
|
|
73
|
+
import path2 from "path";
|
|
74
|
+
function filePathToPattern(filePath, pagesDir) {
|
|
75
|
+
const relativePath = path2.relative(pagesDir, filePath);
|
|
76
|
+
let route = relativePath.replace(/\.(stx|md)$/, "");
|
|
77
|
+
route = route.split(path2.sep).join("/");
|
|
78
|
+
if (route === "index") {
|
|
79
|
+
return "/";
|
|
80
|
+
}
|
|
81
|
+
if (route.endsWith("/index")) {
|
|
82
|
+
route = route.slice(0, -6);
|
|
83
|
+
}
|
|
84
|
+
route = route.replace(/\[\[([^\]]+)\]\]/g, ":$1?");
|
|
85
|
+
route = route.replace(/\[([^\]]+)\]/g, ":$1");
|
|
86
|
+
route = route.replace(/:\.\.\.([^/]+)/g, ":$1*");
|
|
87
|
+
return `/${route}`;
|
|
88
|
+
}
|
|
89
|
+
function patternToRegex(pattern) {
|
|
90
|
+
const params = [];
|
|
91
|
+
let regexStr = "";
|
|
92
|
+
let i = 0;
|
|
93
|
+
while (i < pattern.length) {
|
|
94
|
+
const rest = pattern.slice(i);
|
|
95
|
+
const optional = /^\/:([^/?*]+)\?/.exec(rest);
|
|
96
|
+
if (optional) {
|
|
97
|
+
params.push(optional[1]);
|
|
98
|
+
regexStr += "(?:/([^/]+))?";
|
|
99
|
+
i += optional[0].length;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const catchAll = /^:([^/?*]+)\*/.exec(rest);
|
|
103
|
+
if (catchAll) {
|
|
104
|
+
params.push(catchAll[1]);
|
|
105
|
+
regexStr += "(.+)";
|
|
106
|
+
i += catchAll[0].length;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const required = /^:([^/?*]+)/.exec(rest);
|
|
110
|
+
if (required) {
|
|
111
|
+
params.push(required[1]);
|
|
112
|
+
regexStr += "([^/]+)";
|
|
113
|
+
i += required[0].length;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
regexStr += pattern[i].replace(/[.+^${}()|[\]\\*?]/g, "\\$&");
|
|
117
|
+
i += 1;
|
|
118
|
+
}
|
|
119
|
+
return { regex: new RegExp(`^${regexStr}$`), params };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ../router/src/nested-layouts.ts
|
|
123
|
+
import fs2 from "fs";
|
|
124
|
+
import path3 from "path";
|
|
125
|
+
function resolveLayoutChain(routeFilePath, pagesDir) {
|
|
126
|
+
const layouts = [];
|
|
127
|
+
let dir = path3.dirname(routeFilePath);
|
|
128
|
+
while (dir.startsWith(pagesDir) || dir === pagesDir) {
|
|
129
|
+
const layoutFile = path3.join(dir, "_layout.stx");
|
|
130
|
+
if (fs2.existsSync(layoutFile)) {
|
|
131
|
+
layouts.unshift(layoutFile);
|
|
132
|
+
}
|
|
133
|
+
if (dir === pagesDir)
|
|
134
|
+
break;
|
|
135
|
+
dir = path3.dirname(dir);
|
|
136
|
+
}
|
|
137
|
+
return layouts;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ../router/src/file-router.ts
|
|
141
|
+
function scanDirectory(dir, extensions) {
|
|
142
|
+
const files = [];
|
|
143
|
+
if (!fs3.existsSync(dir)) {
|
|
144
|
+
return files;
|
|
145
|
+
}
|
|
146
|
+
const entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
147
|
+
for (const entry of entries) {
|
|
148
|
+
const fullPath = path4.join(dir, entry.name);
|
|
149
|
+
if (entry.isDirectory()) {
|
|
150
|
+
if (entry.name.startsWith(".")) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (NON_PAGE_DIRS.includes(entry.name)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
files.push(...scanDirectory(fullPath, extensions));
|
|
157
|
+
} else if (entry.isFile()) {
|
|
158
|
+
const ext = path4.extname(entry.name);
|
|
159
|
+
if (extensions.includes(ext)) {
|
|
160
|
+
if (entry.name.startsWith("_") && entry.name !== "_layout.stx") {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (entry.name === "_layout.stx") {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
files.push(fullPath);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return files;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
class Router {
|
|
174
|
+
routes;
|
|
175
|
+
pagesDir;
|
|
176
|
+
pagesDirs;
|
|
177
|
+
config;
|
|
178
|
+
constructor(baseDir, config = {}) {
|
|
179
|
+
this.config = config;
|
|
180
|
+
const rawDirs = config.pagesDirs && config.pagesDirs.length > 0 ? config.pagesDirs : [config.pagesDir || "pages"];
|
|
181
|
+
this.pagesDirs = rawDirs.map((d) => path4.resolve(baseDir, d));
|
|
182
|
+
this.pagesDir = this.pagesDirs[0];
|
|
183
|
+
const extensions = config.extensions || [".stx"];
|
|
184
|
+
const canonical = (entry) => {
|
|
185
|
+
const resolved = path4.resolve(baseDir, entry);
|
|
186
|
+
try {
|
|
187
|
+
return fs3.realpathSync(resolved);
|
|
188
|
+
} catch {
|
|
189
|
+
return resolved;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const excluded = (config.exclude ?? []).filter((entry) => typeof entry === "string" && entry.trim() !== "").map(canonical);
|
|
193
|
+
const isExcluded = (file) => {
|
|
194
|
+
if (excluded.length === 0)
|
|
195
|
+
return false;
|
|
196
|
+
const real = canonical(file);
|
|
197
|
+
return excluded.some((root) => real === root || real.startsWith(`${root}${path4.sep}`));
|
|
198
|
+
};
|
|
199
|
+
const seenPatterns = new Set;
|
|
200
|
+
this.routes = [];
|
|
201
|
+
for (const dir of this.pagesDirs) {
|
|
202
|
+
const files = scanDirectory(dir, extensions).filter((file) => !isExcluded(file));
|
|
203
|
+
const localPatterns = new Map;
|
|
204
|
+
for (const filePath of files) {
|
|
205
|
+
const pattern = filePathToPattern(filePath, dir);
|
|
206
|
+
const identity = config.pagesDirs ? pattern.replace(/:[\w]+/g, ":param") : pattern;
|
|
207
|
+
if (config.pagesDirs && localPatterns.has(identity))
|
|
208
|
+
throw new Error(`Conflicting layer pages for ${pattern}: ${localPatterns.get(identity)} and ${filePath}`);
|
|
209
|
+
localPatterns.set(identity, filePath);
|
|
210
|
+
if (seenPatterns.has(identity))
|
|
211
|
+
continue;
|
|
212
|
+
seenPatterns.add(identity);
|
|
213
|
+
const { regex, params } = patternToRegex(pattern);
|
|
214
|
+
const layouts = config.layouts !== false ? resolveLayoutChain(filePath, dir) : [];
|
|
215
|
+
this.routes.push({
|
|
216
|
+
pattern,
|
|
217
|
+
regex,
|
|
218
|
+
params,
|
|
219
|
+
filePath,
|
|
220
|
+
isDynamic: params.length > 0,
|
|
221
|
+
layout: layouts.length > 0 ? layouts[layouts.length - 1] : undefined
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
this.routes.sort((a, b) => {
|
|
226
|
+
if (!a.isDynamic && b.isDynamic)
|
|
227
|
+
return -1;
|
|
228
|
+
if (a.isDynamic && !b.isDynamic)
|
|
229
|
+
return 1;
|
|
230
|
+
const aSegments = a.pattern.split("/").length;
|
|
231
|
+
const bSegments = b.pattern.split("/").length;
|
|
232
|
+
if (aSegments !== bSegments)
|
|
233
|
+
return bSegments - aSegments;
|
|
234
|
+
return a.pattern.localeCompare(b.pattern);
|
|
235
|
+
});
|
|
236
|
+
if (config.emit !== false) {
|
|
237
|
+
const stxDir = path4.resolve(baseDir, config.stateDir || process.env.STX_DIR?.trim() || ".stx");
|
|
238
|
+
generateRouteTypes(this.routes, stxDir);
|
|
239
|
+
generateRouteManifest(this.routes, stxDir, this.pagesDir);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
match(pathname) {
|
|
243
|
+
const normalizedPath = pathname === "" ? "/" : pathname;
|
|
244
|
+
for (const route of this.routes) {
|
|
245
|
+
const m = normalizedPath.match(route.regex);
|
|
246
|
+
if (m) {
|
|
247
|
+
const params = {};
|
|
248
|
+
route.params.forEach((name, index) => {
|
|
249
|
+
params[name] = m[index + 1];
|
|
250
|
+
});
|
|
251
|
+
return { route, params };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
resolve(name, params) {
|
|
257
|
+
const route = this.routes.find((r) => r.pattern === name || r.filePath.includes(name));
|
|
258
|
+
if (!route)
|
|
259
|
+
return "#not-found";
|
|
260
|
+
let resolved = route.pattern;
|
|
261
|
+
if (params) {
|
|
262
|
+
for (const [key, value] of Object.entries(params)) {
|
|
263
|
+
resolved = resolved.replace(`:${key}`, encodeURIComponent(value));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return resolved;
|
|
267
|
+
}
|
|
268
|
+
addRoute(route) {
|
|
269
|
+
this.routes.push(route);
|
|
270
|
+
this.routes.sort((a, b) => {
|
|
271
|
+
if (!a.isDynamic && b.isDynamic)
|
|
272
|
+
return -1;
|
|
273
|
+
if (a.isDynamic && !b.isDynamic)
|
|
274
|
+
return 1;
|
|
275
|
+
return a.pattern.localeCompare(b.pattern);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
getLayout(route) {
|
|
279
|
+
return route.layout ?? null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// ../router/src/middleware.ts
|
|
283
|
+
var middlewareRegistry = new Map;
|
|
284
|
+
export {
|
|
285
|
+
Router
|
|
286
|
+
};
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"./chunk-2mx7fq49.js";
|
|
3
|
-
|
|
4
2
|
// src/client.ts
|
|
5
3
|
var version = "1.0.0";
|
|
6
4
|
var isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
|
|
@@ -110,8 +108,8 @@ function initIslands(handlers, config = {}) {
|
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
110
|
export {
|
|
113
|
-
|
|
114
|
-
preloadIslandHandlers,
|
|
111
|
+
hydrateIslands,
|
|
115
112
|
initIslands,
|
|
116
|
-
|
|
113
|
+
preloadIslandHandlers,
|
|
114
|
+
version
|
|
117
115
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import"./chunk-2mx7fq49.js";
|
|
3
|
+
createWatcher2,
|
|
4
|
+
watchAndBuild2,
|
|
5
|
+
startWatchMode2,
|
|
6
|
+
stxPlugin2,
|
|
7
|
+
createMiddleware2,
|
|
8
|
+
createRoute2,
|
|
9
|
+
readMarkdownFile2,
|
|
10
|
+
src_default
|
|
11
|
+
} from "./chunk-18kmm7vg.js";
|
|
13
12
|
export {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readMarkdownFile,
|
|
13
|
+
createMiddleware2 as createMiddleware,
|
|
14
|
+
createRoute2 as createRoute,
|
|
15
|
+
createWatcher2 as createWatcher,
|
|
18
16
|
src_default as default,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
readMarkdownFile2 as readMarkdownFile,
|
|
18
|
+
startWatchMode2 as startWatchMode,
|
|
19
|
+
stxPlugin2 as stxPlugin,
|
|
20
|
+
watchAndBuild2 as watchAndBuild
|
|
22
21
|
};
|