poveste 0.18.0 → 0.18.2
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 +4 -2
- package/dist/node/collect/error.js +2 -1
- package/dist/node/collect/index.js +2 -1
- package/dist/node/dom/env.d.ts +3 -1
- package/dist/node/dom/env.js +29 -9
- package/dist/node/dom/iterator.d.ts +2 -0
- package/dist/node/dom/iterator.js +213 -0
- package/dist/node/server.js +39 -15
- package/dist/node/util/escape-regexp.d.ts +8 -0
- package/dist/node/util/escape-regexp.js +10 -0
- package/dist/node/util/is-error.d.ts +7 -0
- package/dist/node/util/is-error.js +10 -0
- package/dist/node/vendors.d.ts +42 -2
- package/dist/node/vendors.js +92 -17
- package/dist/node/virtual/resolved-stories.d.ts +6 -0
- package/dist/node/virtual/resolved-stories.js +8 -0
- package/dist/node/vite.js +7 -4
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ pnpm i -D poveste @poveste/plugin-nuxt # Nuxt 4
|
|
|
20
20
|
pnpm i -D poveste @poveste/plugin-quasar # Quasar
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **Installed an older version than you expected?** For about a day after a release, pnpm installs the previous one
|
|
23
|
+
> **Installed an older version than you expected?** For about a day after a release, pnpm installs the previous one with no error and no hint, and for a plugin that's new in that release, its empty `0.0.1` placeholder. That's pnpm's release-age cooldown, not a broken publish. `package.json` keeps the old `^x.y.z`, so waiting doesn't fix it: install again with `npm`, with `--config.minimum-release-age=0` (kebab-case: pnpm 12.4 ignores the camelCase spelling), or with exact versions.
|
|
24
24
|
|
|
25
25
|
Then create a `poveste.config.ts` in your project root:
|
|
26
26
|
|
|
@@ -47,10 +47,12 @@ Run `npx poveste --help` for the full list of options.
|
|
|
47
47
|
|
|
48
48
|
## Requirements
|
|
49
49
|
|
|
50
|
-
Node `>=
|
|
50
|
+
Node `>=22.22.2` and Vite `^8.0.0`. See
|
|
51
51
|
[supported versions](https://poveste.dev/guide/getting-started#supported-versions) for
|
|
52
52
|
what proves each range.
|
|
53
53
|
|
|
54
|
+
On Node 24, use 24.15 or later: Poveste's DOM dependency (jsdom) accepts `^22.22.2 || ^24.15.0 || >=26`.
|
|
55
|
+
|
|
54
56
|
## Links
|
|
55
57
|
|
|
56
58
|
- [Documentation](https://poveste.dev)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isError } from '../util/is-error.js';
|
|
1
2
|
/*
|
|
2
3
|
* Structured clone keeps an `Error`'s `name`, `message` and `stack` and drops every
|
|
3
4
|
* own property beyond them, so the code frame a Vite transform error puts on `frame`
|
|
@@ -19,7 +20,7 @@ function isSerialized(value) {
|
|
|
19
20
|
* story may legitimately throw, and it should arrive as the data it is.
|
|
20
21
|
*/
|
|
21
22
|
function errorLike(value) {
|
|
22
|
-
if (
|
|
23
|
+
if (isError(value)) {
|
|
23
24
|
return true;
|
|
24
25
|
}
|
|
25
26
|
if (typeof value !== 'object' || value === null) {
|
|
@@ -3,6 +3,7 @@ import path, { relative } from 'pathe';
|
|
|
3
3
|
import pc from 'picocolors';
|
|
4
4
|
import { TEMP_PATH } from '../alias.js';
|
|
5
5
|
import { createPath } from '../tree.js';
|
|
6
|
+
import { escapeRegExp } from '../util/escape-regexp.js';
|
|
6
7
|
import { slash } from '../util/fs.js';
|
|
7
8
|
import { globalsFromDefine } from './define-globals.js';
|
|
8
9
|
import { createModuleServer } from './module-server.js';
|
|
@@ -24,7 +25,7 @@ export function useCollectStories(options, ctx) {
|
|
|
24
25
|
// @TODO temporary fix for https://github.com/histoire-dev/histoire/issues/409
|
|
25
26
|
/vite\w*\/dist\/client\/(client|env).mjs/,
|
|
26
27
|
...ctx.config.viteNodeInlineDeps ?? [],
|
|
27
|
-
new RegExp(
|
|
28
|
+
new RegExp(escapeRegExp(path.resolve(TEMP_PATH, 'plugins'))),
|
|
28
29
|
],
|
|
29
30
|
transformMode: ctx.config.viteNodeTransformMode,
|
|
30
31
|
});
|
package/dist/node/dom/env.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import './iterator.js';
|
|
1
2
|
export declare function createDomEnv(): {
|
|
2
3
|
window: Window & typeof globalThis;
|
|
3
4
|
destroy: () => void;
|
|
4
5
|
pristineKeys: Set<string>;
|
|
6
|
+
storages: Storage[];
|
|
5
7
|
};
|
|
6
8
|
/** Returns a reused environment to the state a fresh one would have been in. */
|
|
7
|
-
export declare function resetDomEnv(env: Pick<ReturnType<typeof createDomEnv>, 'window' | 'pristineKeys'>): void;
|
|
9
|
+
export declare function resetDomEnv(env: Pick<ReturnType<typeof createDomEnv>, 'window' | 'pristineKeys' | 'storages'>): void;
|
package/dist/node/dom/env.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/* eslint-disable perfectionist/sort-imports -- order is load order here */
|
|
2
|
+
// First, and kept first: it defines `Iterator` where the runtime lacks it, and
|
|
3
|
+
// jsdom extends `Iterator` while it loads (#1238).
|
|
4
|
+
import './iterator.js';
|
|
1
5
|
import { JSDOM, VirtualConsole, } from 'jsdom';
|
|
6
|
+
import { isError } from '../util/is-error.js';
|
|
2
7
|
import { populateGlobal } from './util.js';
|
|
8
|
+
/* eslint-enable perfectionist/sort-imports */
|
|
3
9
|
// jsdom error types — not exported by jsdom.
|
|
4
10
|
const JSDOM_ERROR_CSS_PARSING = 'css-parsing';
|
|
5
11
|
const JSDOM_ERROR_UNHANDLED_EXCEPTION = 'unhandled-exception';
|
|
@@ -26,7 +32,7 @@ function createVirtualConsole() {
|
|
|
26
32
|
// `Error.isError` and not `instanceof`: the cause was constructed inside
|
|
27
33
|
// jsdom's realm, where `instanceof Error` is false and the stack — the
|
|
28
34
|
// only part that says which line threw — is discarded (#1093).
|
|
29
|
-
globalThis.console.error((
|
|
35
|
+
globalThis.console.error((isError(err.cause) ? err.cause.stack : undefined) ?? err.message);
|
|
30
36
|
}
|
|
31
37
|
else {
|
|
32
38
|
globalThis.console.error(err.message);
|
|
@@ -43,12 +49,31 @@ export function createDomEnv() {
|
|
|
43
49
|
includeNodeLocations: false,
|
|
44
50
|
contentType: 'text/html',
|
|
45
51
|
});
|
|
52
|
+
const storageNames = ['localStorage', 'sessionStorage'];
|
|
53
|
+
// Before `populateGlobal`, which installs jsdom's own on older Node.
|
|
54
|
+
const storageDescriptors = storageNames.map(name => Object.getOwnPropertyDescriptor(globalThis, name));
|
|
46
55
|
const { keys, originals } = populateGlobal(globalThis, dom.window, { bindFunctions: true });
|
|
56
|
+
// From Node 25 the global names are Node's experimental Web Storage, so
|
|
57
|
+
// `populateGlobal` leaves them, and every read warns without
|
|
58
|
+
// `--localstorage-file`: from a story during collection, and from the reset
|
|
59
|
+
// below (#1175). jsdom's take their place, as they already did on older Node.
|
|
60
|
+
// Descriptors rather than values, because reading Node's is what warns.
|
|
61
|
+
const storages = storageNames.map(name => dom.window[name]);
|
|
62
|
+
storageNames.forEach((name, index) => {
|
|
63
|
+
Object.defineProperty(globalThis, name, { configurable: true, enumerable: true, writable: true, value: storages[index] });
|
|
64
|
+
});
|
|
47
65
|
function destroy() {
|
|
48
66
|
keys.forEach(key => Reflect.deleteProperty(globalThis, key));
|
|
49
67
|
originals.forEach((v, k) => {
|
|
50
68
|
Reflect.set(globalThis, k, v);
|
|
51
69
|
});
|
|
70
|
+
storageNames.forEach((name, index) => {
|
|
71
|
+
const descriptor = storageDescriptors[index];
|
|
72
|
+
if (descriptor)
|
|
73
|
+
Object.defineProperty(globalThis, name, descriptor);
|
|
74
|
+
else
|
|
75
|
+
Reflect.deleteProperty(globalThis, name);
|
|
76
|
+
});
|
|
52
77
|
}
|
|
53
78
|
window.ResizeObserver = window.ResizeObserver || class ResizeObserver {
|
|
54
79
|
disconnect() { }
|
|
@@ -105,6 +130,7 @@ export function createDomEnv() {
|
|
|
105
130
|
// `populateGlobal` does `global.window = global`, so `window` here is
|
|
106
131
|
// `globalThis` — one surface, not two.
|
|
107
132
|
pristineKeys: new Set(Object.keys(globalThis)),
|
|
133
|
+
storages,
|
|
108
134
|
};
|
|
109
135
|
}
|
|
110
136
|
/** Returns a reused environment to the state a fresh one would have been in. */
|
|
@@ -119,14 +145,8 @@ export function resetDomEnv(env) {
|
|
|
119
145
|
}
|
|
120
146
|
doc.head?.replaceChildren();
|
|
121
147
|
doc.body?.replaceChildren();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// node version.
|
|
125
|
-
env.window.localStorage?.clear();
|
|
126
|
-
env.window.sessionStorage?.clear();
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
// Unavailable for some jsdom urls.
|
|
148
|
+
for (const storage of env.storages) {
|
|
149
|
+
storage.clear();
|
|
130
150
|
}
|
|
131
151
|
// Additions only: the modules that installed the rest are cached, not re-run.
|
|
132
152
|
for (const key of Object.keys(globalThis)) {
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// StackBlitz's WebContainer reports Node 22.22.3 but has no global `Iterator`, and
|
|
2
|
+
// jsdom 30.1 extends it when it loads, so every story failed to collect there
|
|
3
|
+
// (#1238). Real Node has had it since 22.0 and never runs this.
|
|
4
|
+
//
|
|
5
|
+
// Vendored rather than core-js: core-js and core-js-pure both carry a postinstall,
|
|
6
|
+
// and pnpm 11 and 12 fail an install outright on a dependency's unapproved build
|
|
7
|
+
// script. The full ES2025 helper set rather than only the `find` jsdom calls
|
|
8
|
+
// today, so the next helper jsdom reaches for is already here.
|
|
9
|
+
const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
|
|
10
|
+
function callable(fn, name) {
|
|
11
|
+
if (typeof fn !== 'function') {
|
|
12
|
+
throw new TypeError(`Iterator.prototype.${name} expects a function`);
|
|
13
|
+
}
|
|
14
|
+
return fn;
|
|
15
|
+
}
|
|
16
|
+
function count(value, name) {
|
|
17
|
+
const n = Number(value);
|
|
18
|
+
if (Number.isNaN(n)) {
|
|
19
|
+
throw new RangeError(`Iterator.prototype.${name} expects a number`);
|
|
20
|
+
}
|
|
21
|
+
const whole = Math.trunc(n);
|
|
22
|
+
if (whole < 0) {
|
|
23
|
+
throw new RangeError(`Iterator.prototype.${name} expects a non-negative number`);
|
|
24
|
+
}
|
|
25
|
+
return whole;
|
|
26
|
+
}
|
|
27
|
+
// Closing after a callback threw keeps the callback's error, as the spec does.
|
|
28
|
+
function closeQuietly(iterator) {
|
|
29
|
+
try {
|
|
30
|
+
iterator.return?.();
|
|
31
|
+
}
|
|
32
|
+
catch { }
|
|
33
|
+
}
|
|
34
|
+
function guarded(iterator, run) {
|
|
35
|
+
try {
|
|
36
|
+
return run();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
closeQuietly(iterator);
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A lazy helper. `step` turns each value into what to yield, and `stop` ends it
|
|
45
|
+
* before the next read. The underlying iterator is closed whenever this one ends
|
|
46
|
+
* before it does.
|
|
47
|
+
*/
|
|
48
|
+
function lazy(iterator, step, stop = () => false) {
|
|
49
|
+
const next = iterator.next;
|
|
50
|
+
return (function* () {
|
|
51
|
+
let exhausted = false;
|
|
52
|
+
try {
|
|
53
|
+
for (let index = 0; !stop(); index++) {
|
|
54
|
+
const result = next.call(iterator);
|
|
55
|
+
if (result.done) {
|
|
56
|
+
exhausted = true;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
yield* guarded(iterator, () => step(result.value, index));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (!exhausted) {
|
|
64
|
+
closeQuietly(iterator);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
}
|
|
69
|
+
/** An eager helper: `visit` returns true to stop, which closes the iterator. */
|
|
70
|
+
function each(iterator, visit) {
|
|
71
|
+
const next = iterator.next;
|
|
72
|
+
for (let index = 0;; index++) {
|
|
73
|
+
const result = next.call(iterator);
|
|
74
|
+
if (result.done) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (guarded(iterator, () => visit(result.value, index))) {
|
|
78
|
+
closeQuietly(iterator);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function flattenable(value, name) {
|
|
84
|
+
if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {
|
|
85
|
+
throw new TypeError(`Iterator.${name} expects an iterator or an iterable`);
|
|
86
|
+
}
|
|
87
|
+
const method = Reflect.get(value, Symbol.iterator);
|
|
88
|
+
const inner = method === undefined ? value : method.call(value);
|
|
89
|
+
return { [Symbol.iterator]: () => inner };
|
|
90
|
+
}
|
|
91
|
+
const helpers = {
|
|
92
|
+
map(fn) {
|
|
93
|
+
const mapper = callable(fn, 'map');
|
|
94
|
+
return lazy(this, (value, index) => [mapper(value, index)]);
|
|
95
|
+
},
|
|
96
|
+
filter(fn) {
|
|
97
|
+
const predicate = callable(fn, 'filter');
|
|
98
|
+
return lazy(this, (value, index) => (predicate(value, index) ? [value] : []));
|
|
99
|
+
},
|
|
100
|
+
take(limit) {
|
|
101
|
+
let remaining = count(limit, 'take');
|
|
102
|
+
return lazy(this, (value) => {
|
|
103
|
+
remaining--;
|
|
104
|
+
return [value];
|
|
105
|
+
}, () => remaining === 0);
|
|
106
|
+
},
|
|
107
|
+
drop(limit) {
|
|
108
|
+
let remaining = count(limit, 'drop');
|
|
109
|
+
return lazy(this, (value) => {
|
|
110
|
+
if (remaining > 0) {
|
|
111
|
+
remaining--;
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
return [value];
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
flatMap(fn) {
|
|
118
|
+
const mapper = callable(fn, 'flatMap');
|
|
119
|
+
return lazy(this, (value, index) => flattenable(mapper(value, index), 'prototype.flatMap'));
|
|
120
|
+
},
|
|
121
|
+
reduce(fn, ...initial) {
|
|
122
|
+
const reducer = callable(fn, 'reduce');
|
|
123
|
+
let accumulator = initial[0];
|
|
124
|
+
let started = initial.length > 0;
|
|
125
|
+
each(this, (value, index) => {
|
|
126
|
+
if (started) {
|
|
127
|
+
accumulator = reducer(accumulator, value, index);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
accumulator = value;
|
|
131
|
+
started = true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
});
|
|
135
|
+
if (!started) {
|
|
136
|
+
throw new TypeError('Iterator.prototype.reduce of an empty iterator with no initial value');
|
|
137
|
+
}
|
|
138
|
+
return accumulator;
|
|
139
|
+
},
|
|
140
|
+
toArray() {
|
|
141
|
+
const out = [];
|
|
142
|
+
each(this, (value) => {
|
|
143
|
+
out.push(value);
|
|
144
|
+
return false;
|
|
145
|
+
});
|
|
146
|
+
return out;
|
|
147
|
+
},
|
|
148
|
+
forEach(fn) {
|
|
149
|
+
const visit = callable(fn, 'forEach');
|
|
150
|
+
each(this, (value, index) => {
|
|
151
|
+
visit(value, index);
|
|
152
|
+
return false;
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
some(fn) {
|
|
156
|
+
const predicate = callable(fn, 'some');
|
|
157
|
+
let found = false;
|
|
158
|
+
each(this, (value, index) => {
|
|
159
|
+
found = Boolean(predicate(value, index));
|
|
160
|
+
return found;
|
|
161
|
+
});
|
|
162
|
+
return found;
|
|
163
|
+
},
|
|
164
|
+
every(fn) {
|
|
165
|
+
const predicate = callable(fn, 'every');
|
|
166
|
+
let all = true;
|
|
167
|
+
each(this, (value, index) => {
|
|
168
|
+
all = Boolean(predicate(value, index));
|
|
169
|
+
return !all;
|
|
170
|
+
});
|
|
171
|
+
return all;
|
|
172
|
+
},
|
|
173
|
+
find(fn) {
|
|
174
|
+
const predicate = callable(fn, 'find');
|
|
175
|
+
let found;
|
|
176
|
+
each(this, (value, index) => {
|
|
177
|
+
if (predicate(value, index)) {
|
|
178
|
+
found = value;
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
});
|
|
183
|
+
return found;
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
/** Defines `globalThis.Iterator` and its helpers where the runtime has neither. */
|
|
187
|
+
export function installIterator() {
|
|
188
|
+
if (typeof Reflect.get(globalThis, 'Iterator') !== 'undefined') {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
function Iterator() {
|
|
192
|
+
if (new.target === undefined || new.target === Iterator) {
|
|
193
|
+
throw new TypeError('Iterator is an abstract class and cannot be constructed directly');
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
Iterator.prototype = IteratorPrototype;
|
|
197
|
+
Object.defineProperty(IteratorPrototype, 'constructor', { value: Iterator, writable: true, configurable: true });
|
|
198
|
+
Object.defineProperty(Iterator, 'from', {
|
|
199
|
+
value(value) {
|
|
200
|
+
const iterator = (typeof value === 'string' ? value : flattenable(value, 'from'))[Symbol.iterator]();
|
|
201
|
+
return Object.prototype.isPrototypeOf.call(IteratorPrototype, iterator) ? iterator : lazy(iterator, item => [item]);
|
|
202
|
+
},
|
|
203
|
+
writable: true,
|
|
204
|
+
configurable: true,
|
|
205
|
+
});
|
|
206
|
+
for (const [name, fn] of Object.entries(helpers)) {
|
|
207
|
+
if (!(name in IteratorPrototype)) {
|
|
208
|
+
Object.defineProperty(IteratorPrototype, name, { value: fn, writable: true, configurable: true });
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
Object.defineProperty(globalThis, 'Iterator', { value: Iterator, writable: true, configurable: true });
|
|
212
|
+
}
|
|
213
|
+
installIterator();
|
package/dist/node/server.js
CHANGED
|
@@ -131,6 +131,17 @@ async function startServer(ctx, options, onOpen, close) {
|
|
|
131
131
|
});
|
|
132
132
|
let collecting = false;
|
|
133
133
|
let didAllStoriesYet = false;
|
|
134
|
+
const updateFor = (url, timestamp) => ({
|
|
135
|
+
type: 'update',
|
|
136
|
+
updates: [
|
|
137
|
+
{
|
|
138
|
+
type: 'js-update',
|
|
139
|
+
acceptedPath: url,
|
|
140
|
+
path: url,
|
|
141
|
+
timestamp,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
});
|
|
134
145
|
// Invalidate modules
|
|
135
146
|
const invalidateModule = (id) => {
|
|
136
147
|
const mod = server.moduleGraph.getModuleById(id);
|
|
@@ -141,18 +152,33 @@ async function startServer(ctx, options, onOpen, close) {
|
|
|
141
152
|
// Send HMR update
|
|
142
153
|
const timestamp = Date.now();
|
|
143
154
|
mod.lastHMRTimestamp = timestamp;
|
|
144
|
-
server.ws.send(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
});
|
|
155
|
+
server.ws.send(updateFor(mod.url, timestamp));
|
|
156
|
+
};
|
|
157
|
+
// Bumped before the list is invalidated, so the copy a client loads next
|
|
158
|
+
// carries the generation it reflects.
|
|
159
|
+
const invalidateStoryList = () => {
|
|
160
|
+
VirtualFiles.storiesGeneration.set(ctx, (VirtualFiles.storiesGeneration.get(ctx) ?? 0) + 1);
|
|
161
|
+
invalidateModule(VirtualFiles.RESOLVED_STORIES_ID);
|
|
162
|
+
invalidateModule(VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID);
|
|
155
163
|
};
|
|
164
|
+
// The update and `poveste:all-stories-loaded` reach only a page that has
|
|
165
|
+
// already evaluated the list and registered for them, and neither is
|
|
166
|
+
// replayed. A page that loaded the list mid-collection and was still loading
|
|
167
|
+
// when collection ended kept that partial list until a reload (#1218). By the
|
|
168
|
+
// time it mounts it is listening, so it is sent what it missed.
|
|
169
|
+
server.ws.on('poveste:mount', (data, client) => {
|
|
170
|
+
if (!didAllStoriesYet || data?.generation === (VirtualFiles.storiesGeneration.get(ctx) ?? 0)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const timestamp = Date.now();
|
|
174
|
+
for (const id of [VirtualFiles.RESOLVED_STORIES_ID, VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID]) {
|
|
175
|
+
const mod = server.moduleGraph.getModuleById(id);
|
|
176
|
+
if (mod) {
|
|
177
|
+
client.send(updateFor(mod.url, timestamp));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
client.send('poveste:all-stories-loaded', {});
|
|
181
|
+
});
|
|
156
182
|
onOpen('onStoryChange', onStoryChange(async (changedFile) => {
|
|
157
183
|
if (changedFile && !didAllStoriesYet) {
|
|
158
184
|
return;
|
|
@@ -227,16 +253,14 @@ async function startServer(ctx, options, onOpen, close) {
|
|
|
227
253
|
return;
|
|
228
254
|
}
|
|
229
255
|
console.log(`Collect stories end ${pc.bold(pc.blue(Math.round(performance.now() - time)))}ms`);
|
|
230
|
-
|
|
231
|
-
invalidateModule(VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID);
|
|
256
|
+
invalidateStoryList();
|
|
232
257
|
collecting = false;
|
|
233
258
|
if (queued) {
|
|
234
259
|
await collect();
|
|
235
260
|
}
|
|
236
261
|
}
|
|
237
262
|
onOpen('onStoryListChange', onStoryListChange(() => {
|
|
238
|
-
|
|
239
|
-
invalidateModule(VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID);
|
|
263
|
+
invalidateStoryList();
|
|
240
264
|
}));
|
|
241
265
|
onOpen('onMarkdownListChange', onMarkdownListChange(() => {
|
|
242
266
|
invalidateModule(VirtualFiles.RESOLVED_MARKDOWN_FILES);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes a string so a `RegExp` built from it matches that string literally.
|
|
3
|
+
*
|
|
4
|
+
* Not `RegExp.escape`: Node 22, inside the supported range since #1226, does not
|
|
5
|
+
* have it, and TypeScript's `ESNext` lib types it anyway, so the compiler says
|
|
6
|
+
* nothing when it is used.
|
|
7
|
+
*/
|
|
8
|
+
export declare function escapeRegExp(value: string): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Escapes a string so a `RegExp` built from it matches that string literally.
|
|
3
|
+
*
|
|
4
|
+
* Not `RegExp.escape`: Node 22, inside the supported range since #1226, does not
|
|
5
|
+
* have it, and TypeScript's `ESNext` lib types it anyway, so the compiler says
|
|
6
|
+
* nothing when it is used.
|
|
7
|
+
*/
|
|
8
|
+
export function escapeRegExp(value) {
|
|
9
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
10
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Error.isError` where the Node has it, which is from 24; Node 22, inside the
|
|
3
|
+
* supported range since #1226, does not. The fallback gives the same answer for
|
|
4
|
+
* what these call sites see: an error from another realm, jsdom's included, still
|
|
5
|
+
* reports `[object Error]`, and jsdom's `DOMException` fails both.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isError(value: unknown): value is Error;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const native = Error.isError;
|
|
2
|
+
/**
|
|
3
|
+
* `Error.isError` where the Node has it, which is from 24; Node 22, inside the
|
|
4
|
+
* supported range since #1226, does not. The fallback gives the same answer for
|
|
5
|
+
* what these call sites see: an error from another realm, jsdom's included, still
|
|
6
|
+
* reports `[object Error]`, and jsdom's `DOMException` fails both.
|
|
7
|
+
*/
|
|
8
|
+
export function isError(value) {
|
|
9
|
+
return native ? native(value) : Object.prototype.toString.call(value) === '[object Error]';
|
|
10
|
+
}
|
package/dist/node/vendors.d.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
import type { Plugin as VitePlugin } from 'vite';
|
|
1
2
|
/**
|
|
2
3
|
* Resolves `specifier` as Node would from `from`, to a real path, or `undefined`
|
|
3
4
|
* when nothing answers.
|
|
4
5
|
*/
|
|
5
6
|
export type Resolver = (specifier: string, from: string) => string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Finds the package by walking `node_modules` up from `from`, then lets Node resolve
|
|
9
|
+
* the subpath from inside it, through its `exports`. Not `require.resolve` from `from`:
|
|
10
|
+
* Node folds NODE_PATH into every lookup, even with `paths`, and pnpm's bin shims
|
|
11
|
+
* point it at the whole store, so a Svelte book run through `poveste` "had" a Vue of
|
|
12
|
+
* its own and the chrome was collapsed onto a Vue Vite could not find (#1201).
|
|
13
|
+
*/
|
|
6
14
|
export declare const nodeResolver: Resolver;
|
|
7
15
|
export interface VendoredAlias {
|
|
8
16
|
/** The bare package the alias points at, `vue`. */
|
|
@@ -54,8 +62,8 @@ export declare function satisfiesCaret(version: string | undefined, range: strin
|
|
|
54
62
|
* and making the chrome's pinned copies authoritative for a project's own story code
|
|
55
63
|
* is a larger change than this defect asks for.
|
|
56
64
|
*
|
|
57
|
-
* Empty when the project has no Vue of its own, when the
|
|
58
|
-
*
|
|
65
|
+
* Empty when the project has no Vue of its own, or when the project's Vue does not
|
|
66
|
+
* satisfy the range vendors pins — in each
|
|
59
67
|
* case the vendored copy is what the chrome should keep. Refusing on anything it
|
|
60
68
|
* cannot read with certainty is deliberate: the failure of this function is a chrome
|
|
61
69
|
* that keeps a Vue it can certainly run, and the failure of guessing is a chrome
|
|
@@ -71,4 +79,36 @@ export declare function satisfiesCaret(version: string | undefined, range: strin
|
|
|
71
79
|
export declare function collapseVendoredVue(options: {
|
|
72
80
|
root: string;
|
|
73
81
|
resolve?: Resolver;
|
|
82
|
+
/** Where `@poveste/vendors` is resolved from: Poveste's own install unless a test says otherwise. */
|
|
83
|
+
vendorsFrom?: string;
|
|
74
84
|
}): Record<string, string>;
|
|
85
|
+
/**
|
|
86
|
+
* Resolves `@poveste/vendors` from Poveste's own install, wherever it is imported.
|
|
87
|
+
*
|
|
88
|
+
* `@poveste/vendors` is excluded from pre-bundling, so the pre-bundled
|
|
89
|
+
* `@poveste/controls` keeps bare imports of it. Vite resolves an optimized entry's
|
|
90
|
+
* imports from the package's real location, but a shared chunk of one has no real
|
|
91
|
+
* location and resolves from `node_modules/.pvt-vite/deps` under the project. Since
|
|
92
|
+
* #593 split the controls into chunks, that only worked where npm or Yarn had
|
|
93
|
+
* hoisted `@poveste/vendors` to the project's `node_modules`. pnpm doesn't, and
|
|
94
|
+
* `poveste dev` rendered a blank page (#1201).
|
|
95
|
+
*/
|
|
96
|
+
export declare function vendorsFromPoveste(): VitePlugin;
|
|
97
|
+
/**
|
|
98
|
+
* The chrome's vendored packages, as nested pre-bundle specifiers, for a book with no
|
|
99
|
+
* Vue of its own (Svelte, Solid, React).
|
|
100
|
+
*
|
|
101
|
+
* There the collapse has no project Vue to point at, and under pnpm `poveste-vue`
|
|
102
|
+
* and the `vue` that `poveste-vue-router` imports are one file in the store. Vite
|
|
103
|
+
* pre-bundled the first and served the second raw: one file, two module instances,
|
|
104
|
+
* and a book that rendered no story. Pre-bundling every vendored package together,
|
|
105
|
+
* reached through Poveste's own install, puts their Vue in one shared chunk (#1201).
|
|
106
|
+
*
|
|
107
|
+
* Empty wherever the collapse applies, or when the chain cannot be resolved from
|
|
108
|
+
* the project, where Vite would only warn about an include it cannot find.
|
|
109
|
+
*/
|
|
110
|
+
export declare function chromePrebundles(options: {
|
|
111
|
+
root: string;
|
|
112
|
+
resolve?: Resolver;
|
|
113
|
+
vendorsFrom?: string;
|
|
114
|
+
}): string[];
|
package/dist/node/vendors.js
CHANGED
|
@@ -1,15 +1,37 @@
|
|
|
1
|
-
import { readFileSync, realpathSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'pathe';
|
|
5
|
+
// A file of this package's own, to resolve from.
|
|
6
|
+
const POVESTE_FILE = fileURLToPath(import.meta.url);
|
|
7
|
+
function packageName(specifier) {
|
|
8
|
+
const parts = specifier.split('/');
|
|
9
|
+
return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Finds the package by walking `node_modules` up from `from`, then lets Node resolve
|
|
13
|
+
* the subpath from inside it, through its `exports`. Not `require.resolve` from `from`:
|
|
14
|
+
* Node folds NODE_PATH into every lookup, even with `paths`, and pnpm's bin shims
|
|
15
|
+
* point it at the whole store, so a Svelte book run through `poveste` "had" a Vue of
|
|
16
|
+
* its own and the chrome was collapsed onto a Vue Vite could not find (#1201).
|
|
17
|
+
*/
|
|
4
18
|
export const nodeResolver = (specifier, from) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
const name = packageName(specifier);
|
|
20
|
+
for (let dir = from;; dir = dirname(dir)) {
|
|
21
|
+
const candidate = join(dir, 'node_modules', name);
|
|
22
|
+
if (existsSync(join(candidate, 'package.json'))) {
|
|
23
|
+
try {
|
|
24
|
+
// From a file inside the package, whose own `node_modules` parent is the
|
|
25
|
+
// first place Node looks, so the lookup ends here before NODE_PATH.
|
|
26
|
+
return realpathSync(createRequire(join(candidate, 'package.json')).resolve(specifier));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (dirname(dir) === dir) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
13
35
|
}
|
|
14
36
|
};
|
|
15
37
|
/**
|
|
@@ -92,8 +114,8 @@ export function satisfiesCaret(version, range) {
|
|
|
92
114
|
* and making the chrome's pinned copies authoritative for a project's own story code
|
|
93
115
|
* is a larger change than this defect asks for.
|
|
94
116
|
*
|
|
95
|
-
* Empty when the project has no Vue of its own, when the
|
|
96
|
-
*
|
|
117
|
+
* Empty when the project has no Vue of its own, or when the project's Vue does not
|
|
118
|
+
* satisfy the range vendors pins — in each
|
|
97
119
|
* case the vendored copy is what the chrome should keep. Refusing on anything it
|
|
98
120
|
* cannot read with certainty is deliberate: the failure of this function is a chrome
|
|
99
121
|
* that keeps a Vue it can certainly run, and the failure of guessing is a chrome
|
|
@@ -109,12 +131,13 @@ export function satisfiesCaret(version, range) {
|
|
|
109
131
|
export function collapseVendoredVue(options) {
|
|
110
132
|
const { root } = options;
|
|
111
133
|
const resolve = options.resolve ?? nodeResolver;
|
|
112
|
-
//
|
|
113
|
-
// happens
|
|
114
|
-
//
|
|
134
|
+
// Vendors from Poveste's own install, and `poveste-vue` from the vendors directory:
|
|
135
|
+
// that is where each import happens. An isolated `node_modules` layout, pnpm's,
|
|
136
|
+
// puts neither at the project root, so resolving vendors from there found nothing,
|
|
137
|
+
// nothing was collapsed, and a pnpm book had two Vues (#1201).
|
|
115
138
|
// Through an exported subpath: vendors' `exports` map does not list
|
|
116
139
|
// `./package.json`, so resolving that name directly fails.
|
|
117
|
-
const vendorsEntry = resolve('@poveste/vendors/vue',
|
|
140
|
+
const vendorsEntry = resolve('@poveste/vendors/vue', options.vendorsFrom ?? dirname(POVESTE_FILE));
|
|
118
141
|
const vendorsDir = vendorsEntry ? join(vendorsEntry, '..') : undefined;
|
|
119
142
|
if (!vendorsDir) {
|
|
120
143
|
return {};
|
|
@@ -127,7 +150,10 @@ export function collapseVendoredVue(options) {
|
|
|
127
150
|
const [installedAs, { range }] = vueAlias;
|
|
128
151
|
const vendored = resolve(installedAs, vendorsDir);
|
|
129
152
|
const project = resolve('vue', root);
|
|
130
|
-
|
|
153
|
+
// Even when they are one file, as pnpm makes them: Vite keys a pre-bundled dependency
|
|
154
|
+
// by the name it is imported under, so `poveste-vue` was served raw beside the
|
|
155
|
+
// pre-bundled `vue` — one file, two module instances, and no story (#1201).
|
|
156
|
+
if (!vendored || !project) {
|
|
131
157
|
return {};
|
|
132
158
|
}
|
|
133
159
|
if (!satisfiesCaret(versionOf('vue/package.json', resolve, root), range)) {
|
|
@@ -155,3 +181,52 @@ function readJson(file) {
|
|
|
155
181
|
return undefined;
|
|
156
182
|
}
|
|
157
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolves `@poveste/vendors` from Poveste's own install, wherever it is imported.
|
|
186
|
+
*
|
|
187
|
+
* `@poveste/vendors` is excluded from pre-bundling, so the pre-bundled
|
|
188
|
+
* `@poveste/controls` keeps bare imports of it. Vite resolves an optimized entry's
|
|
189
|
+
* imports from the package's real location, but a shared chunk of one has no real
|
|
190
|
+
* location and resolves from `node_modules/.pvt-vite/deps` under the project. Since
|
|
191
|
+
* #593 split the controls into chunks, that only worked where npm or Yarn had
|
|
192
|
+
* hoisted `@poveste/vendors` to the project's `node_modules`. pnpm doesn't, and
|
|
193
|
+
* `poveste dev` rendered a blank page (#1201).
|
|
194
|
+
*/
|
|
195
|
+
export function vendorsFromPoveste() {
|
|
196
|
+
return {
|
|
197
|
+
name: 'poveste:vendors-from-poveste',
|
|
198
|
+
enforce: 'pre',
|
|
199
|
+
resolveId(source, _importer, options) {
|
|
200
|
+
if (source !== '@poveste/vendors' && !source.startsWith('@poveste/vendors/')) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
return this.resolve(source, POVESTE_FILE, { ...options, skipSelf: true });
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The chrome's vendored packages, as nested pre-bundle specifiers, for a book with no
|
|
209
|
+
* Vue of its own (Svelte, Solid, React).
|
|
210
|
+
*
|
|
211
|
+
* There the collapse has no project Vue to point at, and under pnpm `poveste-vue`
|
|
212
|
+
* and the `vue` that `poveste-vue-router` imports are one file in the store. Vite
|
|
213
|
+
* pre-bundled the first and served the second raw: one file, two module instances,
|
|
214
|
+
* and a book that rendered no story. Pre-bundling every vendored package together,
|
|
215
|
+
* reached through Poveste's own install, puts their Vue in one shared chunk (#1201).
|
|
216
|
+
*
|
|
217
|
+
* Empty wherever the collapse applies, or when the chain cannot be resolved from
|
|
218
|
+
* the project, where Vite would only warn about an include it cannot find.
|
|
219
|
+
*/
|
|
220
|
+
export function chromePrebundles(options) {
|
|
221
|
+
const { root } = options;
|
|
222
|
+
const resolve = options.resolve ?? nodeResolver;
|
|
223
|
+
if (resolve('vue', root) || !resolve('poveste/package.json', root)) {
|
|
224
|
+
return [];
|
|
225
|
+
}
|
|
226
|
+
const vendorsEntry = resolve('@poveste/vendors/vue', options.vendorsFrom ?? dirname(POVESTE_FILE));
|
|
227
|
+
if (!vendorsEntry) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
230
|
+
const aliases = vendoredAliases(readJson(join(vendorsEntry, '..', 'package.json'))?.dependencies);
|
|
231
|
+
return Object.keys(aliases).map(installedAs => `poveste > @poveste/vendors > ${installedAs}`);
|
|
232
|
+
}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import type { Context } from '../context.js';
|
|
2
|
+
/**
|
|
3
|
+
* How many times the story list has changed since the server started, per book.
|
|
4
|
+
* A client that loaded the list before a change, and missed the update that
|
|
5
|
+
* announced it, is told so when it mounts (#1218).
|
|
6
|
+
*/
|
|
7
|
+
export declare const storiesGeneration: WeakMap<Context, number>;
|
|
2
8
|
export declare function resolvedStories(ctx: Context): string;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { makeTree } from '../tree.js';
|
|
2
2
|
import { jsString } from './codegen.js';
|
|
3
|
+
/**
|
|
4
|
+
* How many times the story list has changed since the server started, per book.
|
|
5
|
+
* A client that loaded the list before a change, and missed the update that
|
|
6
|
+
* announced it, is told so when it mounts (#1218).
|
|
7
|
+
*/
|
|
8
|
+
export const storiesGeneration = new WeakMap();
|
|
3
9
|
export function resolvedStories(ctx) {
|
|
4
10
|
const resolvedStories = ctx.storyFiles.filter(s => !!s.story);
|
|
5
11
|
const files = resolvedStories.map((file, index) => {
|
|
@@ -26,6 +32,7 @@ ${resolvedStories.map((file, index) => {
|
|
|
26
32
|
}).filter(Boolean).join('\n')}
|
|
27
33
|
export let files = [${files.map(file => `{${JSON.stringify(file).slice(1, -1)}, component: Comp${file.index}, source: () => import(${jsString(`virtual:story-source:${file.story.id}`)})}`).join(',\n')}]
|
|
28
34
|
export let tree = ${JSON.stringify(makeTree(ctx.config, resolvedStories))}
|
|
35
|
+
export let generation = ${storiesGeneration.get(ctx) ?? 0}
|
|
29
36
|
const handlers = []
|
|
30
37
|
export function onUpdate (cb) {
|
|
31
38
|
handlers.push(cb)
|
|
@@ -34,6 +41,7 @@ if (import.meta.hot) {
|
|
|
34
41
|
import.meta.hot.accept(newModule => {
|
|
35
42
|
files = newModule.files
|
|
36
43
|
tree = newModule.tree
|
|
44
|
+
generation = newModule.generation
|
|
37
45
|
handlers.forEach(h => {
|
|
38
46
|
h(newModule.files, newModule.tree)
|
|
39
47
|
newModule.onUpdate(h)
|
package/dist/node/vite.js
CHANGED
|
@@ -8,9 +8,10 @@ import { createMarkdownPlugins } from './markdown.js';
|
|
|
8
8
|
import { optimizeEntries } from './optimize-entries.js';
|
|
9
9
|
import { notifyStoryChange } from './stories.js';
|
|
10
10
|
import { chromeCssScopePlugin, globalStylesPlugin, userCssScopePlugin, } from './style-isolation/index.js';
|
|
11
|
+
import { escapeRegExp } from './util/escape-regexp.js';
|
|
11
12
|
import { applyHeadTransform } from './util/head.js';
|
|
12
13
|
import { viteCommand, viteMode } from './util/vite-mode.js';
|
|
13
|
-
import { collapseVendoredVue } from './vendors.js';
|
|
14
|
+
import { chromePrebundles, collapseVendoredVue, vendorsFromPoveste } from './vendors.js';
|
|
14
15
|
import { createVirtualFilesPlugin } from './virtual/vite-plugin.js';
|
|
15
16
|
const require = createRequire(import.meta.url);
|
|
16
17
|
/**
|
|
@@ -192,6 +193,7 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
192
193
|
// bare `vue` was served raw beside the pre-bundled copy of the same
|
|
193
194
|
// file: two module instances, and `RouterView` rendered nothing (#1134).
|
|
194
195
|
...(Object.keys(collapsedVue).length > 0 ? ['vue'] : []),
|
|
196
|
+
...isServer || process.env['POVESTE_DEV'] ? [] : chromePrebundles({ root: ctx.root }),
|
|
195
197
|
],
|
|
196
198
|
exclude: [
|
|
197
199
|
'poveste',
|
|
@@ -332,6 +334,7 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
332
334
|
};
|
|
333
335
|
},
|
|
334
336
|
});
|
|
337
|
+
plugins.push(vendorsFromPoveste());
|
|
335
338
|
plugins.push(createVirtualFilesPlugin(ctx, isServer));
|
|
336
339
|
plugins.push(globalStylesPlugin({
|
|
337
340
|
files: ctx.config.globalStyles ?? [],
|
|
@@ -359,7 +362,7 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
359
362
|
if (/\.(?:vue|js)(?:$|\?)/.test(id)) {
|
|
360
363
|
const original = code;
|
|
361
364
|
for (const [flag, value] of Object.entries(flags)) {
|
|
362
|
-
code = code.replace(new RegExp(
|
|
365
|
+
code = code.replace(new RegExp(escapeRegExp(flag), 'g'), value);
|
|
363
366
|
}
|
|
364
367
|
if (original !== code)
|
|
365
368
|
return code;
|
|
@@ -419,11 +422,11 @@ export async function getViteConfigWithPlugins(isServer, ctx) {
|
|
|
419
422
|
['vue', 'vue'],
|
|
420
423
|
].reduce((acc, [name, entry]) => {
|
|
421
424
|
acc.push({
|
|
422
|
-
find: new RegExp(`^${
|
|
425
|
+
find: new RegExp(`^${escapeRegExp(name)}$`),
|
|
423
426
|
replacement: `@poveste/vendors/${entry}`,
|
|
424
427
|
});
|
|
425
428
|
acc.push({
|
|
426
|
-
find: new RegExp(`^${
|
|
429
|
+
find: new RegExp(`^${escapeRegExp(name)}/`),
|
|
427
430
|
replacement: `@poveste/vendors/${entry}/`,
|
|
428
431
|
});
|
|
429
432
|
return acc;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poveste",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.18.
|
|
4
|
+
"version": "0.18.2",
|
|
5
5
|
"description": "Interactive component playgrounds for Vue, Nuxt, Svelte, SvelteKit and Quasar, plus Solid (renderer only) — a drop-in fork of histoire, with Quasar support histoire does not ship.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Sorin Gitlan",
|
|
@@ -70,17 +70,17 @@
|
|
|
70
70
|
"plugin.js"
|
|
71
71
|
],
|
|
72
72
|
"engines": {
|
|
73
|
-
"node": ">=
|
|
73
|
+
"node": ">=22.22.2"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"vite": "^8.0.0"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@11ty/gray-matter": "^3.0.0",
|
|
80
|
-
"@poveste/app": "^0.18.
|
|
81
|
-
"@poveste/controls": "^0.18.
|
|
82
|
-
"@poveste/shared": "^0.18.
|
|
83
|
-
"@poveste/vendors": "^0.18.
|
|
80
|
+
"@poveste/app": "^0.18.2",
|
|
81
|
+
"@poveste/controls": "^0.18.2",
|
|
82
|
+
"@poveste/shared": "^0.18.2",
|
|
83
|
+
"@poveste/vendors": "^0.18.2",
|
|
84
84
|
"change-case": "^5.4.4",
|
|
85
85
|
"chokidar": "^5.0.0",
|
|
86
86
|
"defu": "^6.1.4",
|