bun-plugin-stx 0.2.316 → 0.2.318
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-71hprtbd.js → chunk-37vp8yms.js} +43 -5
- package/dist/serve.d.ts +9 -0
- package/dist/serve.js +27 -7
- package/package.json +1 -1
|
@@ -205,10 +205,25 @@ class Router {
|
|
|
205
205
|
this.pagesDirs = rawDirs.map((d) => path4.resolve(baseDir, d));
|
|
206
206
|
this.pagesDir = this.pagesDirs[0];
|
|
207
207
|
const extensions = config.extensions || [".stx"];
|
|
208
|
+
const canonical = (entry) => {
|
|
209
|
+
const resolved = path4.resolve(baseDir, entry);
|
|
210
|
+
try {
|
|
211
|
+
return fs3.realpathSync(resolved);
|
|
212
|
+
} catch {
|
|
213
|
+
return resolved;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const excluded = (config.exclude ?? []).filter((entry) => typeof entry === "string" && entry.trim() !== "").map(canonical);
|
|
217
|
+
const isExcluded = (file) => {
|
|
218
|
+
if (excluded.length === 0)
|
|
219
|
+
return false;
|
|
220
|
+
const real = canonical(file);
|
|
221
|
+
return excluded.some((root) => real === root || real.startsWith(`${root}${path4.sep}`));
|
|
222
|
+
};
|
|
208
223
|
const seenPatterns = new Set;
|
|
209
224
|
this.routes = [];
|
|
210
225
|
for (const dir of this.pagesDirs) {
|
|
211
|
-
const files = scanDirectory(dir, extensions);
|
|
226
|
+
const files = scanDirectory(dir, extensions).filter((file) => !isExcluded(file));
|
|
212
227
|
const localPatterns = new Map;
|
|
213
228
|
for (const filePath of files) {
|
|
214
229
|
const pattern = filePathToPattern(filePath, dir);
|
|
@@ -964,6 +979,15 @@ function getRouterScript() {
|
|
|
964
979
|
// navigation, leaking a listener and an observer each time and resetting the
|
|
965
980
|
// instance registry \u2014 trading a silent missing component for a silent leak.
|
|
966
981
|
var REGISTERS_SCOPE=/window\\.stx\\.mount|_scopes\\s*\\[|\\.initScope\\s*\\(|__stxComponentFactories\\s*\\[/;
|
|
982
|
+
// The page's module registry (#1957): the bundle every component that
|
|
983
|
+
// imports a local module reads from, so on navigation it has to run before
|
|
984
|
+
// any of them. Marked data-stx-modules; the text test also finds it where
|
|
985
|
+
// only a script's text survives. Its wrapper names __stxModuleBundles, which
|
|
986
|
+
// no component script does -- they read __stxModules.
|
|
987
|
+
var REGISTRY_TEXT=/__stxModuleBundles/;
|
|
988
|
+
function isModuleRegistryScript(s){
|
|
989
|
+
return !!s&&((s.hasAttribute&&s.hasAttribute('data-stx-modules'))||REGISTRY_TEXT.test(s.textContent||''));
|
|
990
|
+
}
|
|
967
991
|
function runsAlways(declared, code){
|
|
968
992
|
if(declared==='always')return true;
|
|
969
993
|
if(declared==='once')return false;
|
|
@@ -1968,7 +1992,7 @@ else {
|
|
|
1968
1992
|
var slot='document-'+(++routedBodyScriptId);
|
|
1969
1993
|
var setupName=generatedSetupName(text);
|
|
1970
1994
|
if(setupName)incomingSetupName=setupName;
|
|
1971
|
-
routedBodyScripts.push({text:text,runAlways:true,slot:slot,setupName:setupName,run:s.getAttribute('data-stx-run')||'',owner:s.getAttribute('data-stx-owner')||''});
|
|
1995
|
+
routedBodyScripts.push({text:text,runAlways:true,slot:slot,setupName:setupName,run:s.getAttribute('data-stx-run')||'',owner:s.getAttribute('data-stx-owner')||'',registry:isModuleRegistryScript(s)});
|
|
1972
1996
|
s.textContent='';
|
|
1973
1997
|
s.setAttribute('type','application/stx-pending');
|
|
1974
1998
|
s.setAttribute('data-stx-route-script',slot);
|
|
@@ -2050,16 +2074,24 @@ else {
|
|
|
2050
2074
|
|
|
2051
2075
|
var scripts=routedBodyScripts.slice();
|
|
2052
2076
|
function addScript(text, runAlways, slot, owner){
|
|
2053
|
-
scripts.push({text:text,runAlways:!!runAlways,slot:slot||'',owner:owner||''});
|
|
2077
|
+
scripts.push({text:text,runAlways:!!runAlways,slot:slot||'',owner:owner||'',registry:REGISTRY_TEXT.test(text)});
|
|
2054
2078
|
}
|
|
2055
2079
|
if(isLayoutChange){
|
|
2056
|
-
// Also collect setup functions from <head
|
|
2080
|
+
// Also collect setup functions from <head>, and the page's module
|
|
2081
|
+
// registry (#1957). The registry is anchored to the signals runtime,
|
|
2082
|
+
// and a layout with its own <head> script (analytics, say) pulls the
|
|
2083
|
+
// runtime -- and the registry with it -- into <head>. Collecting only
|
|
2084
|
+
// setups there dropped it, so every component that imports a local
|
|
2085
|
+
// module threw "is not registered on this page" and its template
|
|
2086
|
+
// hydrated against globals: an <input id="email"> bound to
|
|
2087
|
+
// :model="email" showed "[object HTMLInputElement]".
|
|
2057
2088
|
doc.querySelectorAll('head script').forEach(function(s){
|
|
2058
2089
|
var text=s.textContent||'';
|
|
2059
2090
|
if(s.hasAttribute('src'))return;
|
|
2060
2091
|
if(!text.trim())return;
|
|
2061
2092
|
if(isSignalsRuntimeScript(s,text))return;
|
|
2062
|
-
if(
|
|
2093
|
+
if(isModuleRegistryScript(s))addScript(text,true,'','');
|
|
2094
|
+
else if(text.indexOf('__stx_setup_')!==-1)addScript(text,true);
|
|
2063
2095
|
});
|
|
2064
2096
|
} else {
|
|
2065
2097
|
// Collect page scripts from <head> AND <body> (outside container).
|
|
@@ -2107,6 +2139,12 @@ else {
|
|
|
2107
2139
|
return aPage-bPage;
|
|
2108
2140
|
});
|
|
2109
2141
|
}
|
|
2142
|
+
// The module registry runs before anything that reads it (#1957). The
|
|
2143
|
+
// container's own scripts are collected first and head scripts after,
|
|
2144
|
+
// so without this a component in the page body could run ahead of the
|
|
2145
|
+
// registry it imports from. Stable: the order within each group holds.
|
|
2146
|
+
var registryFirst=scripts.filter(function(e){return e.registry});
|
|
2147
|
+
if(registryFirst.length)scripts=registryFirst.concat(scripts.filter(function(e){return !e.registry}));
|
|
2110
2148
|
|
|
2111
2149
|
// Push history state (before active link updates so location.pathname is current)
|
|
2112
2150
|
if(pushState!==false)writeHistory(pushState,url+(hash||''));
|
package/dist/serve.d.ts
CHANGED
|
@@ -175,6 +175,14 @@ export declare function boundedCache<T>(limit: number): {
|
|
|
175
175
|
clear: () => void
|
|
176
176
|
readonly size: number
|
|
177
177
|
};
|
|
178
|
+
/**
|
|
179
|
+
* A predicate over discovered page files for {@link ServeOptions.exclude}.
|
|
180
|
+
*
|
|
181
|
+
* Paths are compared resolved, because patterns and exclusions reach serve()
|
|
182
|
+
* spelled however the caller built them - relative, absolute, with a trailing
|
|
183
|
+
* slash - and a spelling mismatch must not quietly put a page back.
|
|
184
|
+
*/
|
|
185
|
+
export declare function pageExcluder(exclude: readonly string[] | undefined, cwd?: string): (file: string) => boolean;
|
|
178
186
|
export declare function resolveServeOpenUrl(port: number, openPath?: string): string;
|
|
179
187
|
/**
|
|
180
188
|
* Did rendering fail?
|
|
@@ -271,6 +279,7 @@ export declare interface ServeRequestContext {
|
|
|
271
279
|
}
|
|
272
280
|
export declare interface ServeOptions {
|
|
273
281
|
patterns: string[]
|
|
282
|
+
exclude?: string[]
|
|
274
283
|
port?: number
|
|
275
284
|
openPath?: string
|
|
276
285
|
componentsDir?: string
|
package/dist/serve.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/serve.ts
|
|
11
11
|
var {serve: bunServe, Glob } = globalThis.Bun;
|
|
12
|
-
import { existsSync as existsSync2, watch as fsWatch, statSync as statSync3 } from "fs";
|
|
12
|
+
import { existsSync as existsSync2, watch as fsWatch, realpathSync, statSync as statSync3 } from "fs";
|
|
13
13
|
import nodeFs from "fs/promises";
|
|
14
14
|
import nodePath from "path";
|
|
15
15
|
import process19 from "process";
|
|
@@ -9084,6 +9084,23 @@ function boundedCache(limit) {
|
|
|
9084
9084
|
}
|
|
9085
9085
|
};
|
|
9086
9086
|
}
|
|
9087
|
+
function pageExcluder(exclude, cwd = process19.cwd()) {
|
|
9088
|
+
const canonical = (entry) => {
|
|
9089
|
+
const resolved = nodePath.resolve(cwd, entry);
|
|
9090
|
+
try {
|
|
9091
|
+
return realpathSync(resolved);
|
|
9092
|
+
} catch {
|
|
9093
|
+
return resolved;
|
|
9094
|
+
}
|
|
9095
|
+
};
|
|
9096
|
+
const roots = (exclude ?? []).filter((entry) => typeof entry === "string" && entry.trim() !== "").map(canonical);
|
|
9097
|
+
if (roots.length === 0)
|
|
9098
|
+
return () => false;
|
|
9099
|
+
return (file) => {
|
|
9100
|
+
const resolved = canonical(file);
|
|
9101
|
+
return roots.some((root) => resolved === root || resolved.startsWith(`${root}${nodePath.sep}`));
|
|
9102
|
+
};
|
|
9103
|
+
}
|
|
9087
9104
|
function resolveServeOpenUrl(port, openPath = "/") {
|
|
9088
9105
|
const baseUrl = `http://localhost:${port}`;
|
|
9089
9106
|
try {
|
|
@@ -9267,6 +9284,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9267
9284
|
throw new Error("No file patterns provided");
|
|
9268
9285
|
}
|
|
9269
9286
|
let sourceFiles = null;
|
|
9287
|
+
const isExcludedPage = pageExcluder(options.exclude);
|
|
9270
9288
|
let discoveredPagePaths = null;
|
|
9271
9289
|
let assetsInitialized = false;
|
|
9272
9290
|
const htmlCache = new Map;
|
|
@@ -9718,19 +9736,20 @@ function __stxOverlay(errs){
|
|
|
9718
9736
|
console.error(`Error processing pattern "${pattern}":`, error);
|
|
9719
9737
|
}
|
|
9720
9738
|
}
|
|
9721
|
-
|
|
9722
|
-
|
|
9739
|
+
const kept = files.filter((f) => !isExcludedPage(f));
|
|
9740
|
+
sourceFiles = kept;
|
|
9741
|
+
rebuildDiscoveredPagePaths(kept);
|
|
9723
9742
|
pageMiddlewareByPath.clear();
|
|
9724
9743
|
pageMiddlewarePatterns.length = 0;
|
|
9725
|
-
await Promise.all(
|
|
9744
|
+
await Promise.all(kept.map((f) => detectPageMiddleware(f)));
|
|
9726
9745
|
try {
|
|
9727
|
-
const { Router } = await import("./chunk-
|
|
9746
|
+
const { Router } = await import("./chunk-37vp8yms.js");
|
|
9728
9747
|
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
9729
|
-
const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName() });
|
|
9748
|
+
const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
|
|
9730
9749
|
if (!options.quiet)
|
|
9731
9750
|
console.log(`[stx] Generated ${router.routes.length} routes \u2192 ${nodePath.join(stateDirName(), "routes.ts")}`);
|
|
9732
9751
|
} catch (e) {}
|
|
9733
|
-
return
|
|
9752
|
+
return kept;
|
|
9734
9753
|
}
|
|
9735
9754
|
async function ensureAssets() {
|
|
9736
9755
|
if (assetsInitialized)
|
|
@@ -11185,6 +11204,7 @@ export {
|
|
|
11185
11204
|
render404Page,
|
|
11186
11205
|
publicFileExists,
|
|
11187
11206
|
projectUsesImageBuiltins,
|
|
11207
|
+
pageExcluder,
|
|
11188
11208
|
isStaticAssetPath,
|
|
11189
11209
|
isRenderableCacheCandidate,
|
|
11190
11210
|
isRenderFailure,
|
package/package.json
CHANGED