@nifrajs/web 2.2.0 → 2.4.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/README.md +3 -3
- package/dist/build-vite.d.ts +4 -4
- package/dist/build-vite.d.ts.map +1 -1
- package/dist/build-vite.js +20 -74
- package/dist/build-vite.js.map +1 -1
- package/dist/build.d.ts +64 -42
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +100 -78
- package/dist/build.js.map +1 -1
- package/dist/bun-dev-entry.d.ts +1 -1
- package/dist/bun-dev-entry.js +1 -1
- package/dist/chunk-names.js +1 -1
- package/dist/client.d.ts +3 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +201 -29
- package/dist/client.js.map +1 -1
- package/dist/conformance.d.ts +2 -2
- package/dist/conformance.js +3 -3
- package/dist/deferred.d.ts +11 -11
- package/dist/deferred.d.ts.map +1 -1
- package/dist/deferred.js +16 -16
- package/dist/dev-diagnostics.d.ts +20 -0
- package/dist/dev-diagnostics.d.ts.map +1 -0
- package/dist/dev-diagnostics.js +34 -0
- package/dist/dev-diagnostics.js.map +1 -0
- package/dist/dev-error.d.ts +10 -13
- package/dist/dev-error.d.ts.map +1 -1
- package/dist/dev-error.js +51 -37
- package/dist/dev-error.js.map +1 -1
- package/dist/dev-port.d.ts +3 -3
- package/dist/dev-port.d.ts.map +1 -1
- package/dist/dev-port.js +10 -4
- package/dist/dev-port.js.map +1 -1
- package/dist/dev.d.ts +4 -4
- package/dist/dev.d.ts.map +1 -1
- package/dist/dev.js +28 -12
- package/dist/dev.js.map +1 -1
- package/dist/diagnostic.d.ts +93 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +205 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/draft.d.ts +12 -12
- package/dist/draft.js +11 -11
- package/dist/fn-state.d.ts +56 -0
- package/dist/fn-state.d.ts.map +1 -0
- package/dist/fn-state.js +77 -0
- package/dist/fn-state.js.map +1 -0
- package/dist/fn.d.ts +111 -0
- package/dist/fn.d.ts.map +1 -0
- package/dist/fn.js +125 -0
- package/dist/fn.js.map +1 -0
- package/dist/fonts-google.d.ts +9 -9
- package/dist/fonts-google.js +10 -10
- package/dist/fonts.d.ts +7 -7
- package/dist/fonts.js +1 -1
- package/dist/forms.d.ts +8 -8
- package/dist/fs.d.ts +1 -1
- package/dist/fs.js +1 -1
- package/dist/index.d.ts +151 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +317 -139
- package/dist/index.js.map +1 -1
- package/dist/internal/head-attributes.d.ts +15 -0
- package/dist/internal/head-attributes.d.ts.map +1 -0
- package/dist/internal/head-attributes.js +99 -0
- package/dist/internal/head-attributes.js.map +1 -0
- package/dist/internal/script-types.d.ts +14 -0
- package/dist/internal/script-types.d.ts.map +1 -0
- package/dist/internal/script-types.js +17 -0
- package/dist/internal/script-types.js.map +1 -0
- package/dist/internal/server-boundary.d.ts +60 -0
- package/dist/internal/server-boundary.d.ts.map +1 -0
- package/dist/internal/server-boundary.js +174 -0
- package/dist/internal/server-boundary.js.map +1 -0
- package/dist/internal/timing-safe-equal.d.ts +1 -1
- package/dist/internal/timing-safe-equal.js +1 -1
- package/dist/internal/vite-import.d.ts +63 -0
- package/dist/internal/vite-import.d.ts.map +1 -0
- package/dist/internal/vite-import.js +94 -0
- package/dist/internal/vite-import.js.map +1 -0
- package/dist/islands.d.ts +5 -5
- package/dist/islands.js +5 -5
- package/dist/isr.d.ts +15 -15
- package/dist/isr.js +7 -7
- package/dist/manifest.d.ts +73 -35
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +10 -16
- package/dist/manifest.js.map +1 -1
- package/dist/module-graph.d.ts +5 -5
- package/dist/module-graph.js +4 -4
- package/dist/navigation.d.ts +120 -5
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +37 -5
- package/dist/navigation.js.map +1 -1
- package/dist/plugins/css-modules.d.ts +3 -3
- package/dist/plugins/css-modules.js +0 -0
- package/dist/plugins/kit.d.ts +8 -8
- package/dist/plugins/kit.js +9 -9
- package/dist/plugins/scss.js +3 -3
- package/dist/plugins/vite-leak-guard.d.ts +1 -1
- package/dist/plugins/vite-leak-guard.js +1 -1
- package/dist/plugins/vite-server-fn.d.ts +23 -0
- package/dist/plugins/vite-server-fn.d.ts.map +1 -0
- package/dist/plugins/vite-server-fn.js +51 -0
- package/dist/plugins/vite-server-fn.js.map +1 -0
- package/dist/plugins/vite-server-only.d.ts +49 -0
- package/dist/plugins/vite-server-only.d.ts.map +1 -0
- package/dist/plugins/vite-server-only.js +57 -0
- package/dist/plugins/vite-server-only.js.map +1 -0
- package/dist/prerender.d.ts +5 -5
- package/dist/prerender.js +7 -7
- package/dist/query.d.ts +10 -10
- package/dist/query.js +15 -15
- package/dist/route-manifest.d.ts +1 -1
- package/dist/route-manifest.js +2 -2
- package/dist/router.d.ts +30 -21
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +62 -32
- package/dist/router.js.map +1 -1
- package/dist/search.d.ts +94 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +232 -0
- package/dist/search.js.map +1 -0
- package/dist/server-only.d.ts +6 -6
- package/dist/server-only.js +7 -7
- package/dist/service-worker.d.ts +56 -0
- package/dist/service-worker.d.ts.map +1 -0
- package/dist/service-worker.js +127 -0
- package/dist/service-worker.js.map +1 -0
- package/dist/vite.d.ts +16 -14
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +51 -24
- package/dist/vite.js.map +1 -1
- package/package.json +38 -4
- package/server-manifest.d.ts +31 -0
- package/src/build-vite.ts +24 -77
- package/src/build.ts +137 -105
- package/src/bun-dev-entry.ts +1 -1
- package/src/chunk-names.ts +1 -1
- package/src/client.ts +215 -32
- package/src/conformance.ts +3 -3
- package/src/deferred.ts +17 -17
- package/src/dev-diagnostics.ts +47 -0
- package/src/dev-error.ts +64 -33
- package/src/dev-port.ts +17 -5
- package/src/dev.ts +36 -20
- package/src/diagnostic.ts +284 -0
- package/src/draft.ts +15 -15
- package/src/fn-state.ts +107 -0
- package/src/fn.ts +199 -0
- package/src/fonts-google.ts +13 -13
- package/src/fonts.ts +7 -7
- package/src/forms.ts +8 -8
- package/src/fs.ts +2 -2
- package/src/index.ts +460 -181
- package/src/internal/head-attributes.ts +109 -0
- package/src/internal/script-types.ts +18 -0
- package/src/internal/server-boundary.ts +187 -0
- package/src/internal/timing-safe-equal.ts +1 -1
- package/src/internal/vite-import.ts +92 -0
- package/src/islands.ts +7 -7
- package/src/isr.ts +17 -17
- package/src/manifest.ts +83 -42
- package/src/module-graph.ts +6 -6
- package/src/navigation.ts +151 -5
- package/src/plugins/css-modules.ts +0 -0
- package/src/plugins/kit.ts +11 -11
- package/src/plugins/scss.ts +3 -3
- package/src/plugins/vite-leak-guard.ts +2 -2
- package/src/plugins/vite-server-fn.ts +67 -0
- package/src/plugins/vite-server-only.ts +75 -0
- package/src/prerender.ts +10 -10
- package/src/query.ts +22 -22
- package/src/route-manifest.ts +3 -3
- package/src/router.ts +98 -45
- package/src/search.ts +297 -0
- package/src/server-only.ts +7 -7
- package/src/service-worker.ts +165 -0
- package/src/vite.ts +61 -32
package/dist/search.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/** Conservative defaults: a 4 KB query, 64 keys, 6 levels of nesting. */
|
|
2
|
+
export const DEFAULT_SEARCH_LIMITS = { maxLength: 4096, maxKeys: 64, maxDepth: 6 };
|
|
3
|
+
// Keys that must never be written from untrusted input: a bracket-assignment to `__proto__` (or the
|
|
4
|
+
// others) can pollute Object.prototype. Dropped at every level of a decoded value.
|
|
5
|
+
const FORBIDDEN_KEYS = new Set(["__proto__", "prototype", "constructor"]);
|
|
6
|
+
function isPlainObject(value) {
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
// True when `value` nests deeper than `remaining` levels (a scalar never does). Used to reject an
|
|
10
|
+
// over-deep decoded JSON value back to its raw string rather than store the graph.
|
|
11
|
+
function exceedsDepth(value, remaining) {
|
|
12
|
+
if (Array.isArray(value)) {
|
|
13
|
+
if (remaining <= 0)
|
|
14
|
+
return true;
|
|
15
|
+
return value.some((item) => exceedsDepth(item, remaining - 1));
|
|
16
|
+
}
|
|
17
|
+
if (isPlainObject(value)) {
|
|
18
|
+
if (remaining <= 0)
|
|
19
|
+
return true;
|
|
20
|
+
return Object.values(value).some((item) => exceedsDepth(item, remaining - 1));
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
// Recursively strip forbidden keys from a decoded value. `JSON.parse('{"__proto__":1}')` yields an OWN
|
|
25
|
+
// enumerable `__proto__` property (it does not set the prototype), but a later spread/assign of it would,
|
|
26
|
+
// so it is removed here, at the source.
|
|
27
|
+
function sanitize(value) {
|
|
28
|
+
if (Array.isArray(value))
|
|
29
|
+
return value.map(sanitize);
|
|
30
|
+
if (isPlainObject(value)) {
|
|
31
|
+
const out = {};
|
|
32
|
+
for (const [key, item] of Object.entries(value)) {
|
|
33
|
+
if (FORBIDDEN_KEYS.has(key))
|
|
34
|
+
continue;
|
|
35
|
+
out[key] = sanitize(item);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
// One query value: JSON-decode it (so `2` is a number, `true` a boolean, `{...}` an object), falling back
|
|
42
|
+
// to the raw string when it is not JSON or nests past the depth cap.
|
|
43
|
+
function decodeValue(raw, limits) {
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
parsed = JSON.parse(raw);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return raw;
|
|
50
|
+
}
|
|
51
|
+
if ((isPlainObject(parsed) || Array.isArray(parsed)) && exceedsDepth(parsed, limits.maxDepth)) {
|
|
52
|
+
return raw;
|
|
53
|
+
}
|
|
54
|
+
return sanitize(parsed);
|
|
55
|
+
}
|
|
56
|
+
function encodeValue(value) {
|
|
57
|
+
if (typeof value !== "string")
|
|
58
|
+
return JSON.stringify(value);
|
|
59
|
+
// The codec is JSON-first on decode, so a raw string such as `"2"`, `"true"`, or `"null"`
|
|
60
|
+
// would otherwise change type on a serialize → parse round-trip. Quote only ambiguous strings;
|
|
61
|
+
// ordinary text stays readable (`?q=hello`, not `?q=%22hello%22`).
|
|
62
|
+
try {
|
|
63
|
+
JSON.parse(value);
|
|
64
|
+
return JSON.stringify(value);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** The default JSON-first codec. Repeated keys (`?t=a&t=b`) decode to an array; single keys to a value. */
|
|
71
|
+
const jsonCodec = {
|
|
72
|
+
parse(raw, limits) {
|
|
73
|
+
const usp = new URLSearchParams(raw.startsWith("?") ? raw.slice(1) : raw);
|
|
74
|
+
const out = {};
|
|
75
|
+
let kept = 0;
|
|
76
|
+
for (const key of new Set(usp.keys())) {
|
|
77
|
+
if (FORBIDDEN_KEYS.has(key))
|
|
78
|
+
continue;
|
|
79
|
+
if (++kept > limits.maxKeys)
|
|
80
|
+
break;
|
|
81
|
+
const decoded = usp.getAll(key).map((value) => decodeValue(value, limits));
|
|
82
|
+
out[key] = decoded.length > 1 ? decoded : decoded[0];
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
},
|
|
86
|
+
serialize(value) {
|
|
87
|
+
const usp = new URLSearchParams();
|
|
88
|
+
for (const [key, item] of Object.entries(value)) {
|
|
89
|
+
if (item === undefined)
|
|
90
|
+
continue;
|
|
91
|
+
if (Array.isArray(item) && item.length > 1) {
|
|
92
|
+
for (const element of item)
|
|
93
|
+
usp.append(key, encodeValue(element));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Repeated query keys naturally preserve arrays of length >= 2. Empty and singleton arrays
|
|
97
|
+
// need one JSON value or they collapse to a missing key / scalar during decoding.
|
|
98
|
+
usp.set(key, encodeValue(item));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const query = usp.toString();
|
|
102
|
+
return query === "" ? "" : `?${query}`;
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Parse a raw URL query into a structured object. Fails closed to `{}` when the raw string exceeds
|
|
107
|
+
* `limits.maxLength` (before any parsing work is done).
|
|
108
|
+
*/
|
|
109
|
+
export function parseSearch(raw, codec = jsonCodec, limits = DEFAULT_SEARCH_LIMITS) {
|
|
110
|
+
if (raw.length > limits.maxLength)
|
|
111
|
+
return {};
|
|
112
|
+
return codec.parse(raw, limits);
|
|
113
|
+
}
|
|
114
|
+
/** Serialize a structured search object back to a query string (leading `?`, or `""` when empty). */
|
|
115
|
+
export function serializeSearch(value, codec = jsonCodec) {
|
|
116
|
+
return codec.serialize(value);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The search a route sees for a raw URL query: parsed, then validated against a single `searchSchema`
|
|
120
|
+
* when the route declares one (failing closed to its defaults), or the raw parsed query otherwise. A
|
|
121
|
+
* one-link {@link searchOfChain}; use that directly for a layout+page chain. Both the server (`renderPage`,
|
|
122
|
+
* loader ctx) and the client (the adapter mount) derive search this way, from the same URL + schema, so
|
|
123
|
+
* they produce the identical value - SSR-correct by construction, no serialization.
|
|
124
|
+
*/
|
|
125
|
+
export function searchOf(searchSchema, rawSearch) {
|
|
126
|
+
return searchOfChain([searchSchema], rawSearch);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The search for a route whose effective schema is a CHAIN - a `_layout` may declare `searchSchema` for
|
|
130
|
+
* shared keys (`?org`, `?theme`) and each page declares its own. The raw query is validated against every
|
|
131
|
+
* schema in the chain (outermost layout first, page last) and their outputs are merged, page-wins on a key
|
|
132
|
+
* conflict (nearest-wins, like `mergeHeads`): validate-each-then-combine, since Standard Schema has no
|
|
133
|
+
* `.merge()`. `undefined` links (a layout with no `searchSchema`) contribute nothing; when the whole chain
|
|
134
|
+
* is empty, the raw parsed query is returned. Fails closed per schema, same as {@link searchOf} (which is
|
|
135
|
+
* this with a one-link chain). The server and the client build the identical chain, so the value matches.
|
|
136
|
+
*/
|
|
137
|
+
export function searchOfChain(schemas, rawSearch) {
|
|
138
|
+
const parsed = parseSearch(rawSearch);
|
|
139
|
+
const defined = schemas.filter((s) => s !== undefined);
|
|
140
|
+
if (defined.length === 0)
|
|
141
|
+
return parsed;
|
|
142
|
+
let out = {};
|
|
143
|
+
for (const schema of defined) {
|
|
144
|
+
const validated = validateSearch(schema, parsed);
|
|
145
|
+
if (!isPlainObject(validated)) {
|
|
146
|
+
throw new TypeError("[nifra/web] a search schema must produce an object");
|
|
147
|
+
}
|
|
148
|
+
out = { ...out, ...validated };
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate a parsed search object against a route's Standard Schema, returning the typed output. Fails
|
|
154
|
+
* CLOSED: on validation issues it retries against an empty object so the schema's per-field defaults apply,
|
|
155
|
+
* and degrades to `{}` only if even that fails - it never throws on hostile input. An async validator is a
|
|
156
|
+
* configuration error (search must validate synchronously, in the render/nav path) and throws loudly.
|
|
157
|
+
*/
|
|
158
|
+
export function validateSearch(schema, parsed) {
|
|
159
|
+
const result = schema["~standard"].validate(parsed);
|
|
160
|
+
if (result instanceof Promise) {
|
|
161
|
+
throw new TypeError("[nifra/web] a search schema must validate synchronously");
|
|
162
|
+
}
|
|
163
|
+
if (result.issues === undefined)
|
|
164
|
+
return result.value;
|
|
165
|
+
const fallback = schema["~standard"].validate({});
|
|
166
|
+
if (fallback instanceof Promise) {
|
|
167
|
+
throw new TypeError("[nifra/web] a search schema must validate synchronously");
|
|
168
|
+
}
|
|
169
|
+
return (fallback.issues === undefined ? fallback.value : {});
|
|
170
|
+
}
|
|
171
|
+
function deepEqual(a, b) {
|
|
172
|
+
if (Object.is(a, b))
|
|
173
|
+
return true;
|
|
174
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
175
|
+
return a.length === b.length && a.every((item, index) => deepEqual(item, b[index]));
|
|
176
|
+
}
|
|
177
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
178
|
+
const aKeys = Object.keys(a);
|
|
179
|
+
return (aKeys.length === Object.keys(b).length &&
|
|
180
|
+
aKeys.every((key) => key in b && deepEqual(a[key], b[key])));
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Structural sharing (shallow-first): return `next`, but reuse `prev`'s reference for every top-level key
|
|
186
|
+
* whose value is deep-equal. When nothing changed, `prev` itself is returned (stable identity), so a
|
|
187
|
+
* selector like `useSearch(s => s.filters)` does not see a change - and a filters-only component does not
|
|
188
|
+
* re-render when an unrelated key (`page`) changes.
|
|
189
|
+
*/
|
|
190
|
+
export function shareSearch(prev, next) {
|
|
191
|
+
if (Object.is(prev, next))
|
|
192
|
+
return prev;
|
|
193
|
+
if (!isPlainObject(prev) || !isPlainObject(next))
|
|
194
|
+
return next;
|
|
195
|
+
const out = {};
|
|
196
|
+
let identical = Object.keys(prev).length === Object.keys(next).length;
|
|
197
|
+
for (const [key, after] of Object.entries(next)) {
|
|
198
|
+
if (key in prev && deepEqual(prev[key], after)) {
|
|
199
|
+
out[key] = prev[key];
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
out[key] = after;
|
|
203
|
+
identical = false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return identical ? prev : out;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* True when two raw queries differ ONLY in keys a route declared client-only (`searchClientKeys`) - the
|
|
210
|
+
* signal a client navigation can update search WITHOUT re-running the loader (re-render, not revalidate:
|
|
211
|
+
* `?tab`, a client-side `?sort` over already-loaded rows, `?modal`). Returns false when a key OUTSIDE the
|
|
212
|
+
* allow-list changed (that key drives data, so the nav must revalidate) and when nothing changed at all (a
|
|
213
|
+
* same-URL nav still revalidates). Fail-safe by construction: an empty allow-list can never return true,
|
|
214
|
+
* so a route that declares no client keys always revalidates - the correct, never-stale default.
|
|
215
|
+
*/
|
|
216
|
+
export function isClientOnlySearchChange(prevRaw, nextRaw, clientKeys) {
|
|
217
|
+
if (clientKeys.length === 0)
|
|
218
|
+
return false;
|
|
219
|
+
const prev = parseSearch(prevRaw);
|
|
220
|
+
const next = parseSearch(nextRaw);
|
|
221
|
+
const allow = new Set(clientKeys);
|
|
222
|
+
let changed = false;
|
|
223
|
+
for (const key of new Set([...Object.keys(prev), ...Object.keys(next)])) {
|
|
224
|
+
if (deepEqual(prev[key], next[key]))
|
|
225
|
+
continue;
|
|
226
|
+
if (!allow.has(key))
|
|
227
|
+
return false; // a loader-affecting key changed - must revalidate
|
|
228
|
+
changed = true;
|
|
229
|
+
}
|
|
230
|
+
return changed; // only a real change to a client-only key skips the fetch (else revalidate)
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/server-only.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@nifrajs/web/server-only`
|
|
3
|
-
* "server-only"`). A module of PURE server logic that carries no `node:` import
|
|
4
|
-
* constant, a server-only API call
|
|
2
|
+
* `@nifrajs/web/server-only` - the **explicit, opt-in poison-import marker** (Next's `import
|
|
3
|
+
* "server-only"`). A module of PURE server logic that carries no `node:` import - a secret-bearing
|
|
4
|
+
* constant, a server-only API call - can't be caught by nifra's other two client-leak guards: the
|
|
5
5
|
* `.server` convention (which empties `*.server` modules in the client build) needs the file to be
|
|
6
6
|
* NAMED `*.server`, and the node-builtin guard only fires when a `node:` import actually reaches a
|
|
7
|
-
* client chunk. This marker closes that gap: drop a side-effect import at the top of the module
|
|
7
|
+
* client chunk. This marker closes that gap: drop a side-effect import at the top of the module -
|
|
8
8
|
*
|
|
9
9
|
* import "@nifrajs/web/server-only"
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* - and the CLIENT build ({@link buildClient}) FAILS LOUD, naming the import chain, if that module
|
|
12
12
|
* ever lands in a browser chunk. On the SERVER build/runtime it's a harmless no-op (this empty
|
|
13
13
|
* module), so the same file runs untouched server-side.
|
|
14
14
|
*
|
|
15
15
|
* Pair it with the type-level {@link ServerOnly} brand (from `@nifrajs/web`) on the module's exports
|
|
16
16
|
* to signal intent to readers + the compiler; this runtime import is what actually fails the build.
|
|
17
17
|
*
|
|
18
|
-
* @see ServerOnly
|
|
18
|
+
* @see ServerOnly - the type-level intent marker that complements this runtime import.
|
|
19
19
|
*/
|
|
20
20
|
export {};
|
|
21
21
|
//# sourceMappingURL=server-only.d.ts.map
|
package/dist/server-only.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@nifrajs/web/server-only`
|
|
3
|
-
* "server-only"`). A module of PURE server logic that carries no `node:` import
|
|
4
|
-
* constant, a server-only API call
|
|
2
|
+
* `@nifrajs/web/server-only` - the **explicit, opt-in poison-import marker** (Next's `import
|
|
3
|
+
* "server-only"`). A module of PURE server logic that carries no `node:` import - a secret-bearing
|
|
4
|
+
* constant, a server-only API call - can't be caught by nifra's other two client-leak guards: the
|
|
5
5
|
* `.server` convention (which empties `*.server` modules in the client build) needs the file to be
|
|
6
6
|
* NAMED `*.server`, and the node-builtin guard only fires when a `node:` import actually reaches a
|
|
7
|
-
* client chunk. This marker closes that gap: drop a side-effect import at the top of the module
|
|
7
|
+
* client chunk. This marker closes that gap: drop a side-effect import at the top of the module -
|
|
8
8
|
*
|
|
9
9
|
* import "@nifrajs/web/server-only"
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* - and the CLIENT build ({@link buildClient}) FAILS LOUD, naming the import chain, if that module
|
|
12
12
|
* ever lands in a browser chunk. On the SERVER build/runtime it's a harmless no-op (this empty
|
|
13
13
|
* module), so the same file runs untouched server-side.
|
|
14
14
|
*
|
|
15
15
|
* Pair it with the type-level {@link ServerOnly} brand (from `@nifrajs/web`) on the module's exports
|
|
16
16
|
* to signal intent to readers + the compiler; this runtime import is what actually fails the build.
|
|
17
17
|
*
|
|
18
|
-
* @see ServerOnly
|
|
18
|
+
* @see ServerOnly - the type-level intent marker that complements this runtime import.
|
|
19
19
|
*/
|
|
20
20
|
// Intentionally empty. The marker is the IMPORT itself: `buildClient` detects any module that imports
|
|
21
21
|
// this specifier and lands in a client chunk (via the same Bun metafile graph the node-builtin guard
|
|
22
|
-
// walks) and fails the build. There is no value to export and nothing to run
|
|
22
|
+
// walks) and fails the build. There is no value to export and nothing to run - on the server it's a
|
|
23
23
|
// no-op so the marked module behaves normally; on the client the build never completes.
|
|
24
24
|
export {};
|
|
25
25
|
//# sourceMappingURL=server-only.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web/service-worker` - generate a service worker from a build manifest.
|
|
3
|
+
*
|
|
4
|
+
* A service worker is the one piece of an app that outlives a deploy, keeps serving after you have
|
|
5
|
+
* stopped, and can hand one user a response produced for another. So the generated worker is
|
|
6
|
+
* deliberately narrow, and every rule below exists because the permissive version of it is a bug:
|
|
7
|
+
*
|
|
8
|
+
* - **Only content-hashed assets are precached.** A hashed URL names its bytes, so serving it from
|
|
9
|
+
* cache forever is correct by construction. Anything unhashed is left to the network.
|
|
10
|
+
* - **Documents are never cached.** Only navigations that FAIL are answered, and only with the
|
|
11
|
+
* offline page you nominate. A cached HTML document is how a service worker serves one signed-in
|
|
12
|
+
* user the page rendered for another; there is no per-user story here worth that risk.
|
|
13
|
+
* - **GET, same-origin, `ok`, and not `no-store`.** Anything else goes straight to the network.
|
|
14
|
+
* - **The cache name carries the build id.** A deploy that changed the assets gets a new cache, and
|
|
15
|
+
* activation deletes every older one, so a stale worker cannot pin an old build indefinitely.
|
|
16
|
+
*
|
|
17
|
+
* It is opt-in and generated at build time; an app that does not call this ships nothing.
|
|
18
|
+
*/
|
|
19
|
+
/** The parts of a `BuildManifest` a worker needs. Structural, so a caller can pass extra fields. */
|
|
20
|
+
export interface ServiceWorkerManifest {
|
|
21
|
+
readonly entry: string;
|
|
22
|
+
readonly assets: readonly string[];
|
|
23
|
+
readonly css?: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
export interface ServiceWorkerOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Distinguishes this build's cache from the last one. Use something that changes exactly when the
|
|
28
|
+
* assets do - a content hash, a commit sha, a release version.
|
|
29
|
+
*/
|
|
30
|
+
readonly buildId: string;
|
|
31
|
+
/**
|
|
32
|
+
* URL of a page to serve when a navigation fails and the network is unreachable. It must be a
|
|
33
|
+
* static, user-independent document (a prerendered `/offline`), because every visitor gets the same
|
|
34
|
+
* bytes. Omit it and failed navigations simply fail, which is the honest default.
|
|
35
|
+
*/
|
|
36
|
+
readonly offlineUrl?: string;
|
|
37
|
+
/** Cache name prefix. Default `nifra`. */
|
|
38
|
+
readonly cacheName?: string;
|
|
39
|
+
/** Extra same-origin URLs to precache. Only pass immutable ones. */
|
|
40
|
+
readonly additionalPrecache?: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate the service worker source for a build.
|
|
44
|
+
*
|
|
45
|
+
* Write the result to a file served from the ORIGIN ROOT (`/sw.js`): a worker's default scope is its
|
|
46
|
+
* own directory, so one served from `/assets/` could never control the pages it exists for.
|
|
47
|
+
*/
|
|
48
|
+
export declare function generateServiceWorker(manifest: ServiceWorkerManifest, options: ServiceWorkerOptions): string;
|
|
49
|
+
/**
|
|
50
|
+
* The registration snippet, for a `<script>` in your document shell.
|
|
51
|
+
*
|
|
52
|
+
* Registration is deliberately deferred to `load`: a worker installing during first paint competes
|
|
53
|
+
* with the page it is meant to speed up.
|
|
54
|
+
*/
|
|
55
|
+
export declare function serviceWorkerRegistration(scriptUrl?: string): string;
|
|
56
|
+
//# sourceMappingURL=service-worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-worker.d.ts","sourceRoot":"","sources":["../src/service-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,oGAAoG;AACpG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChD;AAqBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAiFR;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,SAAW,GAAG,MAAM,CAGtE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nifrajs/web/service-worker` - generate a service worker from a build manifest.
|
|
3
|
+
*
|
|
4
|
+
* A service worker is the one piece of an app that outlives a deploy, keeps serving after you have
|
|
5
|
+
* stopped, and can hand one user a response produced for another. So the generated worker is
|
|
6
|
+
* deliberately narrow, and every rule below exists because the permissive version of it is a bug:
|
|
7
|
+
*
|
|
8
|
+
* - **Only content-hashed assets are precached.** A hashed URL names its bytes, so serving it from
|
|
9
|
+
* cache forever is correct by construction. Anything unhashed is left to the network.
|
|
10
|
+
* - **Documents are never cached.** Only navigations that FAIL are answered, and only with the
|
|
11
|
+
* offline page you nominate. A cached HTML document is how a service worker serves one signed-in
|
|
12
|
+
* user the page rendered for another; there is no per-user story here worth that risk.
|
|
13
|
+
* - **GET, same-origin, `ok`, and not `no-store`.** Anything else goes straight to the network.
|
|
14
|
+
* - **The cache name carries the build id.** A deploy that changed the assets gets a new cache, and
|
|
15
|
+
* activation deletes every older one, so a stale worker cannot pin an old build indefinitely.
|
|
16
|
+
*
|
|
17
|
+
* It is opt-in and generated at build time; an app that does not call this ships nothing.
|
|
18
|
+
*/
|
|
19
|
+
const SW_URL = /^\/[\w\-./@%]*$/;
|
|
20
|
+
/** A precache URL has to be same-origin, rooted, and free of anything that could break out of a list. */
|
|
21
|
+
function assertPrecachable(url, label) {
|
|
22
|
+
if (typeof url !== "string" || url === "") {
|
|
23
|
+
throw new Error(`[nifra/service-worker] ${label} must be a non-empty string`);
|
|
24
|
+
}
|
|
25
|
+
if (!url.startsWith("/") || url.startsWith("//")) {
|
|
26
|
+
throw new Error(`[nifra/service-worker] ${label} must be a root-relative same-origin path, got ${JSON.stringify(url)}`);
|
|
27
|
+
}
|
|
28
|
+
if (!SW_URL.test(url)) {
|
|
29
|
+
throw new Error(`[nifra/service-worker] ${label} contains characters that are not valid in an asset path: ${JSON.stringify(url)}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Generate the service worker source for a build.
|
|
34
|
+
*
|
|
35
|
+
* Write the result to a file served from the ORIGIN ROOT (`/sw.js`): a worker's default scope is its
|
|
36
|
+
* own directory, so one served from `/assets/` could never control the pages it exists for.
|
|
37
|
+
*/
|
|
38
|
+
export function generateServiceWorker(manifest, options) {
|
|
39
|
+
if (typeof options.buildId !== "string" || options.buildId.trim() === "") {
|
|
40
|
+
throw new Error("[nifra/service-worker] buildId is required and must be non-empty");
|
|
41
|
+
}
|
|
42
|
+
if (/[^\w.-]/.test(options.buildId)) {
|
|
43
|
+
throw new Error(`[nifra/service-worker] buildId must be word characters, dots or hyphens, got ${JSON.stringify(options.buildId)}`);
|
|
44
|
+
}
|
|
45
|
+
const prefix = options.cacheName ?? "nifra";
|
|
46
|
+
if (/[^\w.-]/.test(prefix)) {
|
|
47
|
+
throw new Error(`[nifra/service-worker] cacheName must be word characters, dots or hyphens`);
|
|
48
|
+
}
|
|
49
|
+
const precache = [
|
|
50
|
+
manifest.entry,
|
|
51
|
+
...manifest.assets,
|
|
52
|
+
...(manifest.css ?? []),
|
|
53
|
+
...(options.additionalPrecache ?? []),
|
|
54
|
+
];
|
|
55
|
+
for (const url of precache)
|
|
56
|
+
assertPrecachable(url, "precache url");
|
|
57
|
+
const offline = options.offlineUrl;
|
|
58
|
+
if (offline !== undefined)
|
|
59
|
+
assertPrecachable(offline, "offlineUrl");
|
|
60
|
+
// De-duped and sorted so an unchanged build produces an unchanged worker - a byte-identical file
|
|
61
|
+
// means the browser does not treat it as an update.
|
|
62
|
+
const urls = [...new Set(offline === undefined ? precache : [...precache, offline])].sort();
|
|
63
|
+
return `// Generated by @nifrajs/web/service-worker. Do not edit.
|
|
64
|
+
const CACHE = ${JSON.stringify(`${prefix}-${options.buildId}`)}
|
|
65
|
+
const PRECACHE = ${JSON.stringify(urls)}
|
|
66
|
+
const OFFLINE = ${offline === undefined ? "null" : JSON.stringify(offline)}
|
|
67
|
+
|
|
68
|
+
self.addEventListener("install", (event) => {
|
|
69
|
+
// Take over as soon as the new assets are stored; the activate handler drops the old cache, so
|
|
70
|
+
// waiting would only serve stale bytes for longer.
|
|
71
|
+
event.waitUntil(caches.open(CACHE).then((c) => c.addAll(PRECACHE)).then(() => self.skipWaiting()))
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
self.addEventListener("activate", (event) => {
|
|
75
|
+
event.waitUntil(
|
|
76
|
+
caches
|
|
77
|
+
.keys()
|
|
78
|
+
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
|
79
|
+
.then(() => self.clients.claim()),
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
self.addEventListener("fetch", (event) => {
|
|
84
|
+
const request = event.request
|
|
85
|
+
if (request.method !== "GET") return
|
|
86
|
+
const url = new URL(request.url)
|
|
87
|
+
if (url.origin !== self.location.origin) return
|
|
88
|
+
|
|
89
|
+
// Navigations: network only, with the offline document as a last resort. A cached HTML response is
|
|
90
|
+
// how one user gets served the page rendered for another, so nothing is stored here.
|
|
91
|
+
if (request.mode === "navigate") {
|
|
92
|
+
if (OFFLINE === null) return
|
|
93
|
+
event.respondWith(fetch(request).catch(() => caches.match(OFFLINE).then((r) => r ?? Response.error())))
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Assets: cache first, because every precached URL is content-hashed and therefore immutable.
|
|
98
|
+
event.respondWith(
|
|
99
|
+
caches.match(request).then((hit) => {
|
|
100
|
+
if (hit !== undefined) return hit
|
|
101
|
+
return fetch(request).then((response) => {
|
|
102
|
+
const cacheable =
|
|
103
|
+
response.ok &&
|
|
104
|
+
response.type === "basic" &&
|
|
105
|
+
!(response.headers.get("cache-control") ?? "").includes("no-store")
|
|
106
|
+
if (cacheable && PRECACHE.includes(url.pathname)) {
|
|
107
|
+
const copy = response.clone()
|
|
108
|
+
void caches.open(CACHE).then((c) => c.put(request, copy))
|
|
109
|
+
}
|
|
110
|
+
return response
|
|
111
|
+
})
|
|
112
|
+
}),
|
|
113
|
+
)
|
|
114
|
+
})
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The registration snippet, for a `<script>` in your document shell.
|
|
119
|
+
*
|
|
120
|
+
* Registration is deliberately deferred to `load`: a worker installing during first paint competes
|
|
121
|
+
* with the page it is meant to speed up.
|
|
122
|
+
*/
|
|
123
|
+
export function serviceWorkerRegistration(scriptUrl = "/sw.js") {
|
|
124
|
+
assertPrecachable(scriptUrl, "scriptUrl");
|
|
125
|
+
return `if("serviceWorker"in navigator){addEventListener("load",function(){navigator.serviceWorker.register(${JSON.stringify(scriptUrl)}).catch(function(){})})}`;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=service-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-worker.js","sourceRoot":"","sources":["../src/service-worker.ts"],"names":[],"mappings":"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"}
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Minimal app surface
|
|
1
|
+
/** Minimal app surface - `createWebApp(...)` satisfies it. */
|
|
2
2
|
interface FetchApp {
|
|
3
3
|
fetch(request: Request): Response | Promise<Response>;
|
|
4
4
|
}
|
|
@@ -17,10 +17,10 @@ export interface ViteDevServerOptions {
|
|
|
17
17
|
* crash. Vite re-evaluates on change, so no `importQuery` cache-buster is needed alongside it.
|
|
18
18
|
*/
|
|
19
19
|
readonly createApp: (clientEntry: string, load: (absolutePath: string) => Promise<unknown>) => FetchApp | Promise<FetchApp>;
|
|
20
|
-
/** Vite plugins
|
|
20
|
+
/** Vite plugins - inject your framework's official plugin, e.g. `[react()]`. */
|
|
21
21
|
readonly plugins?: readonly unknown[];
|
|
22
22
|
/**
|
|
23
|
-
* Extra `resolve.conditions` prepended ahead of nifra's defaults
|
|
23
|
+
* Extra `resolve.conditions` prepended ahead of nifra's defaults - some frameworks need their own
|
|
24
24
|
* (e.g. Solid's `"solid"` condition routes `solid-js` to its source/JSX-dev build).
|
|
25
25
|
*/
|
|
26
26
|
readonly conditions?: readonly string[];
|
|
@@ -35,18 +35,21 @@ export interface ViteDevServerOptions {
|
|
|
35
35
|
readonly port?: number;
|
|
36
36
|
/**
|
|
37
37
|
* Use polling for the file watcher. Native fs events (fsevents/inotify) are unreliable inside
|
|
38
|
-
* containers, networked filesystems, and some sandboxes
|
|
38
|
+
* containers, networked filesystems, and some sandboxes - there, HMR silently never fires. Set
|
|
39
39
|
* `true` (or the env var `CHOKIDAR_USEPOLLING=1`) to poll instead. Default: off (native events).
|
|
40
40
|
*/
|
|
41
41
|
readonly poll?: boolean;
|
|
42
42
|
/** Vite public directory. Defaults to `<root>/public`; `false` disables it. */
|
|
43
43
|
readonly publicDir?: string | false;
|
|
44
|
+
/** Client-visible environment prefix (default `"PUBLIC_"`; empty disables exposure). */
|
|
45
|
+
readonly publicEnvPrefix?: string;
|
|
44
46
|
}
|
|
45
47
|
export interface ViteDevServer {
|
|
46
48
|
readonly port: number;
|
|
47
49
|
stop(): Promise<void>;
|
|
48
50
|
}
|
|
49
|
-
|
|
51
|
+
export { LAST_ERROR_PATH } from "./diagnostic.js";
|
|
52
|
+
/** The bits of a Node ServerResponse `pipeWebBodyToNode` touches - structural, to avoid a node:http dep here. */
|
|
50
53
|
interface NodeResLike {
|
|
51
54
|
flushHeaders?(): void;
|
|
52
55
|
on(event: "close", cb: () => void): void;
|
|
@@ -59,30 +62,30 @@ interface NodeHeaderSink {
|
|
|
59
62
|
}
|
|
60
63
|
/**
|
|
61
64
|
* Copy a Web `Response`'s headers onto a Node response, emitting EACH `Set-Cookie` as its own header. The
|
|
62
|
-
* `Headers` iterator (and `.get`) join multiple set-cookie values with ", ", which corrupts cookies
|
|
65
|
+
* `Headers` iterator (and `.get`) join multiple set-cookie values with ", ", which corrupts cookies - e.g.
|
|
63
66
|
* better-auth's `session_token` + `session_data` collapse into one unparseable cookie and the session is
|
|
64
67
|
* silently lost. `getSetCookie()` returns them split; Node's `setHeader` emits one header per array element.
|
|
65
68
|
*/
|
|
66
69
|
export declare function applyResponseHeaders(headers: Headers, res: NodeHeaderSink): void;
|
|
67
70
|
/**
|
|
68
71
|
* Stream a Web `Response` body to a Node response chunk-by-chunk. Buffering the whole body (e.g.
|
|
69
|
-
* `arrayBuffer()`) waits for the stream to END
|
|
72
|
+
* `arrayBuffer()`) waits for the stream to END - which an open-ended SSE (`text/event-stream`) body never
|
|
70
73
|
* does, so it hung `nifra dev` (the Bun production server streamed it fine). This flushes each chunk as it
|
|
71
74
|
* arrives and cancels the reader if the client disconnects; a finite body just streams its chunk(s) + ends.
|
|
72
75
|
*/
|
|
73
76
|
export declare function pipeWebBodyToNode(body: ReadableStream<Uint8Array> | null, res: NodeResLike): Promise<void>;
|
|
74
77
|
/**
|
|
75
78
|
* Strip `optimizeDeps.rollupOptions.jsx` from a plugin's `config` hook output when running under
|
|
76
|
-
* rolldown-vite
|
|
79
|
+
* rolldown-vite - the source of the scary, harmless `Warning: Invalid input options … "jsx" Invalid
|
|
77
80
|
* key: Expected never but received "jsx"` on `nifra dev`.
|
|
78
81
|
*
|
|
79
82
|
* Why it happens: `@vitejs/plugin-react@4.x` (and peers) target an *older* rolldown-vite optimizeDeps
|
|
80
|
-
* API
|
|
83
|
+
* API - they inject `optimizeDeps.rollupOptions.jsx` to tell the dep pre-bundler to transform JSX. Vite
|
|
81
84
|
* 8's rolldown dep-optimizer renamed that surface to `optimizeDeps.rolldownOptions` (and moved jsx under
|
|
82
85
|
* `transform.jsx`), so the stale `rollupOptions.jsx` is an unrecognized input option → the warning. It's
|
|
83
86
|
* a version-skew artifact, not a real misconfig: the route source JSX transform runs through the
|
|
84
87
|
* plugin's own `transform` hook (untouched here), and node_modules deps that get pre-bundled almost
|
|
85
|
-
* never contain raw JSX
|
|
88
|
+
* never contain raw JSX - so dropping the dead key changes no behavior and keeps HMR/Fast Refresh
|
|
86
89
|
* intact. We *strip* (rather than translate to `rolldownOptions`) so the fix is version-agnostic: a
|
|
87
90
|
* plugin already emitting the correct `rolldownOptions` is left untouched, and a future plugin bump that
|
|
88
91
|
* stops emitting `rollupOptions.jsx` makes this a no-op.
|
|
@@ -90,12 +93,12 @@ export declare function pipeWebBodyToNode(body: ReadableStream<Uint8Array> | nul
|
|
|
90
93
|
* Scoped narrowly: only the `optimizeDeps.rollupOptions.jsx` key is removed, only under rolldown-vite,
|
|
91
94
|
* and only from the value a plugin's `config` hook returns. Non-rolldown Vite is passed through verbatim.
|
|
92
95
|
*
|
|
93
|
-
* FLATTEN FIRST: a Vite plugin factory may return an ARRAY of plugins
|
|
96
|
+
* FLATTEN FIRST: a Vite plugin factory may return an ARRAY of plugins - `@vitejs/plugin-react`'s `react()`
|
|
94
97
|
* returns `[vite:react-babel, vite:react-refresh]`, and it's `react:react-babel`'s `config` hook that emits
|
|
95
98
|
* the offending `optimizeDeps.rollupOptions.jsx`. `nifra.config.ts` writes `vitePlugins = [react()]`, so the
|
|
96
99
|
* plugin list arrives NESTED (`[[babel, refresh]]`). Without flattening, `.map` sees the inner array (which
|
|
97
|
-
* has no `config`), leaves it untouched, and Vite
|
|
98
|
-
*
|
|
100
|
+
* has no `config`), leaves it untouched, and Vite - which flattens plugin arrays itself before running them
|
|
101
|
+
* - then executes the un-stripped babel hook, so the warning survives. Flattening here (Vite accepts a flat
|
|
99
102
|
* list identically) is what lets the strip reach every real plugin.
|
|
100
103
|
*/
|
|
101
104
|
export declare function normalizeRolldownPlugins(plugins: readonly unknown[], isRolldown: boolean): readonly unknown[];
|
|
@@ -104,5 +107,4 @@ export declare function normalizeRolldownPlugins(plugins: readonly unknown[], is
|
|
|
104
107
|
* injects its HMR client + the framework refresh preamble via `transformIndexHtml`.
|
|
105
108
|
*/
|
|
106
109
|
export declare function createViteDevServer(options: ViteDevServerOptions): Promise<ViteDevServer>;
|
|
107
|
-
export {};
|
|
108
110
|
//# sourceMappingURL=vite.d.ts.map
|
package/dist/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AA4BA,8DAA8D;AAC9D,UAAU,QAAQ;IAChB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtD;AAuBD,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,SAAS,EAAE,CAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,KAC7C,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACjC,gFAAgF;IAChF,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;IACrC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACnC,wFAAwF;IACxF,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AA6CjD,iHAAiH;AACjH,UAAU,WAAW;IACnB,YAAY,CAAC,IAAI,IAAI,CAAA;IACrB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;IACxC,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAA;IACjC,GAAG,IAAI,IAAI,CAAA;CACZ;AAED,8DAA8D;AAC9D,UAAU,cAAc;IACtB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;CACjE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAOhF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,EACvC,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,UAAU,EAAE,OAAO,GAClB,SAAS,OAAO,EAAE,CAkCpB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CA6J/F"}
|