@moostjs/vite 0.6.42 → 0.6.44
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 +22 -20
- package/dist/index.cjs +145 -16
- package/dist/index.d.ts +17 -7
- package/dist/index.mjs +145 -16
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -222,6 +222,8 @@ The guard works in one direction only, and the runtime is not the only package t
|
|
|
222
222
|
|
|
223
223
|
After the SSR build the plugin checks for exactly that: it compares the packages inlined into `dist/server` with the bare imports left in it and warns when any externalized package (or one of its transitive dependencies) depends on a bundled watched package — `moost` / `@moostjs/*` / `@wooksjs/*` / `wooks` / `@atscript/*` by default — naming the package and the fix. `ssrExternalCheck: { packages: ['some-registry-lib', '@acme/', /^my-lib-/] }` watches more (exact name, scope prefix, `RegExp`); `ssrExternalCheck: false` silences it. The symptoms of a split are `TypeError: Cannot read properties of undefined (reading 'headers')` (or any header name) from inside a composable, and an empty table where a managed view was declared — production only. Source-level tests share one module graph and cannot see it: verify on the installed build. Full explanation and a manual verification recipe: [SSR Bundle Size](https://moost.org/webapp/vite#ssr-bundle-size).
|
|
224
224
|
|
|
225
|
+
**Dev server.** In `vite serve`, installed `moost` / `@moostjs/*` / `@wooksjs/*` are loaded natively by Node, so the app and any library importing them on its own (e.g. `@atscript/moost-db` resolving `MoostHttp` through DI) share one copy. Don't put the runtime in `ssr.noExternal` for dev, and list a linked workspace copy of it in `ssr.external`; the plugin warns at startup when a natively loaded package depends on a watched package Vite's SSR module runner inlines (same `ssrExternalCheck` option). Up to 0.6.42 such libraries failed with `Class is not Injectable` in dev unless listed in `ssr.noExternal` — drop that workaround after upgrading. Details: [Dev server: one runtime copy](https://moost.org/webapp/vite#dev-server-one-runtime-copy).
|
|
226
|
+
|
|
225
227
|
## SSR Local Fetch
|
|
226
228
|
|
|
227
229
|
When `ssrFetch` is enabled (default: `true`), the plugin patches `globalThis.fetch` so that local paths are routed in-process through Moost instead of making a real HTTP request. This is useful for SSR where server-side code fetches from its own API:
|
|
@@ -249,26 +251,26 @@ The plugin injects a `__VITE_ID` decorator on `@Injectable` and `@Controller` cl
|
|
|
249
251
|
|
|
250
252
|
## Options
|
|
251
253
|
|
|
252
|
-
| Option | Type | Default | Description
|
|
253
|
-
| ------------------ | ------------------------------------------------ | ---------------------- |
|
|
254
|
-
| `entry` | `string` | — | Application entry file (required)
|
|
255
|
-
| `port` | `number` | `3000` | Dev server port (backend mode only)
|
|
256
|
-
| `host` | `string` | `'localhost'` | Dev server host (backend mode only)
|
|
257
|
-
| `outDir` | `string` | `'dist'` | Build output directory (backend mode only)
|
|
258
|
-
| `format` | `'cjs' \| 'esm'` | `'esm'` | Output module format (backend mode only)
|
|
259
|
-
| `sourcemap` | `boolean` | `true` | Generate source maps (both modes; in middleware mode applies to the `dist/server` SSR build)
|
|
260
|
-
| `externals` | `boolean \| object` | `true` | Configure external dependencies (backend mode only)
|
|
261
|
-
| `onEject` | `function` | — | Hook to control DI instance ejection during HMR
|
|
262
|
-
| `ssrFetch` | `boolean` | `true` | Enable local fetch interception for SSR
|
|
263
|
-
| `middleware` | `boolean` | `false` | Run Moost as Connect middleware (Vite serves frontend)
|
|
264
|
-
| `prefix` | `string` | `'/api'` (prod server) | URL prefix filter for middleware mode (e.g. `'/api'`); the production server defaults to `'/api'` when omitted
|
|
265
|
-
| `ssrEntry` | `string` | — | Vue/React SSR entry module (e.g. `'/src/entry-server.ts'`)
|
|
266
|
-
| `ssrOutlet` | `string` | `'<!--ssr-outlet-->'` | HTML placeholder for SSR-rendered content
|
|
267
|
-
| `ssrState` | `string` | `'<!--ssr-state-->'` | HTML placeholder for SSR state transfer script
|
|
268
|
-
| `ssrHead` | `string` | `'<!--ssr-head-->'` | HTML placeholder for SSR-rendered `<head>` tags (place inside `<head>`)
|
|
269
|
-
| `serverEntry` | `string` | — | Custom production server entry file (e.g. `'./server.ts'`)
|
|
270
|
-
| `ssrExternal` | `string[]` | — | Packages to keep external in the SSR build (middleware mode, `vite build` only). Concatenated with `cfg.ssr.external`. See [SSR Bundle Size](#ssr-bundle-size).
|
|
271
|
-
| `ssrExternalCheck` | `boolean \| { packages?: (string \| RegExp)[] }` | `true` | Warn after the middleware-mode SSR build when an externalized package depends on a bundled shared-state package (`moost`, `@moostjs/*`, `wooks`, `@wooksjs/*`, `@atscript/*`); `packages` watches more. See [SSR Bundle Size](#ssr-bundle-size). |
|
|
254
|
+
| Option | Type | Default | Description |
|
|
255
|
+
| ------------------ | ------------------------------------------------ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
256
|
+
| `entry` | `string` | — | Application entry file (required) |
|
|
257
|
+
| `port` | `number` | `3000` | Dev server port (backend mode only) |
|
|
258
|
+
| `host` | `string` | `'localhost'` | Dev server host (backend mode only) |
|
|
259
|
+
| `outDir` | `string` | `'dist'` | Build output directory (backend mode only) |
|
|
260
|
+
| `format` | `'cjs' \| 'esm'` | `'esm'` | Output module format (backend mode only) |
|
|
261
|
+
| `sourcemap` | `boolean` | `true` | Generate source maps (both modes; in middleware mode applies to the `dist/server` SSR build) |
|
|
262
|
+
| `externals` | `boolean \| object` | `true` | Configure external dependencies (backend mode only) |
|
|
263
|
+
| `onEject` | `function` | — | Hook to control DI instance ejection during HMR |
|
|
264
|
+
| `ssrFetch` | `boolean` | `true` | Enable local fetch interception for SSR |
|
|
265
|
+
| `middleware` | `boolean` | `false` | Run Moost as Connect middleware (Vite serves frontend) |
|
|
266
|
+
| `prefix` | `string` | `'/api'` (prod server) | URL prefix filter for middleware mode (e.g. `'/api'`); the production server defaults to `'/api'` when omitted |
|
|
267
|
+
| `ssrEntry` | `string` | — | Vue/React SSR entry module (e.g. `'/src/entry-server.ts'`) |
|
|
268
|
+
| `ssrOutlet` | `string` | `'<!--ssr-outlet-->'` | HTML placeholder for SSR-rendered content |
|
|
269
|
+
| `ssrState` | `string` | `'<!--ssr-state-->'` | HTML placeholder for SSR state transfer script |
|
|
270
|
+
| `ssrHead` | `string` | `'<!--ssr-head-->'` | HTML placeholder for SSR-rendered `<head>` tags (place inside `<head>`) |
|
|
271
|
+
| `serverEntry` | `string` | — | Custom production server entry file (e.g. `'./server.ts'`) |
|
|
272
|
+
| `ssrExternal` | `string[]` | — | Packages to keep external in the SSR build (middleware mode, `vite build` only). Concatenated with `cfg.ssr.external`. See [SSR Bundle Size](#ssr-bundle-size). |
|
|
273
|
+
| `ssrExternalCheck` | `boolean \| { packages?: (string \| RegExp)[] }` | `true` | Warn after the middleware-mode SSR build when an externalized package depends on a bundled shared-state package (`moost`, `@moostjs/*`, `wooks`, `@wooksjs/*`, `@prostojs/infact`/`mate`, `@atscript/*`), and at dev-server startup when one depends on a package the SSR runner inlines; `packages` watches more. See [SSR Bundle Size](#ssr-bundle-size). |
|
|
272
274
|
|
|
273
275
|
Options marked "backend mode only" are ignored when `middleware: true` — the user's `vite.config.ts` controls build/server configuration in middleware mode.
|
|
274
276
|
|
package/dist/index.cjs
CHANGED
|
@@ -142,6 +142,12 @@ function getExternals({ node, workspace }) {
|
|
|
142
142
|
|
|
143
143
|
//#endregion
|
|
144
144
|
//#region packages/vite/src/adapter-detector.ts
|
|
145
|
+
/** Id prefix of the virtual modules re-exporting an adapter package (`virtual:moost-adapter/http`). */ const ADAPTER_VIRTUAL_PREFIX = "virtual:moost-adapter/";
|
|
146
|
+
/** Source of a resolved (`\0`-prefixed) adapter virtual module, or `undefined` for any other id. */ function loadAdapterVirtualModule(id) {
|
|
147
|
+
if (!id.startsWith(`\0${ADAPTER_VIRTUAL_PREFIX}`)) return;
|
|
148
|
+
const adapter = id.slice(23);
|
|
149
|
+
return `export * from ${JSON.stringify(`@moostjs/event-${adapter}`)}\n`;
|
|
150
|
+
}
|
|
145
151
|
/**
|
|
146
152
|
* Creates an adapter detector for a specific adapter type.
|
|
147
153
|
* @param adapter
|
|
@@ -156,7 +162,7 @@ function getExternals({ node, workspace }) {
|
|
|
156
162
|
async init() {
|
|
157
163
|
this.detected = true;
|
|
158
164
|
const moduleId = `@moostjs/event-${adapter}`;
|
|
159
|
-
const module = this.ssrLoadModule ? await this.ssrLoadModule(
|
|
165
|
+
const module = this.ssrLoadModule ? await this.ssrLoadModule(`${ADAPTER_VIRTUAL_PREFIX}${adapter}`) : await import(moduleId);
|
|
160
166
|
const constructorName = `Moost${adapter.charAt(0).toUpperCase() + adapter.slice(1)}`;
|
|
161
167
|
getLogger().log(`🔍 [2mExtracting Adapter "${constructorName}"`);
|
|
162
168
|
this.constructor = module[constructorName];
|
|
@@ -460,15 +466,24 @@ function constructorName(i) {
|
|
|
460
466
|
/^wooks($|\/)/
|
|
461
467
|
];
|
|
462
468
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
|
|
466
|
-
|
|
469
|
+
* The `ssr.noExternal` entry the plugin always adds, so the `define:`
|
|
470
|
+
* substitutions in `prod-server.mjs` land.
|
|
471
|
+
*/ const PLUGIN_NO_EXTERNAL = /^@moostjs\/vite($|\/)/;
|
|
472
|
+
/**
|
|
473
|
+
* Packages the split checks watch by default: the moost/wooks runtime, the DI
|
|
474
|
+
* and metadata containers under it (`@prostojs/infact`, `@prostojs/mate`) and
|
|
475
|
+
* the `@atscript/*` family. All of them keep module-level state — Symbol slot
|
|
476
|
+
* keys, DI/model registries, class identity used by `instanceof` — so a second
|
|
477
|
+
* copy loaded by Node breaks lookups that the other copy filled in.
|
|
467
478
|
*
|
|
468
479
|
* This is deliberately wider than {@link RUNTIME_PACKAGE_PATTERNS}: the guard
|
|
469
|
-
* that force-bundles packages covers the runtime only, while the
|
|
470
|
-
*
|
|
471
|
-
*/ const SHARED_STATE_PACKAGE_PATTERNS = [
|
|
480
|
+
* that force-bundles packages covers the runtime only, while the checks merely
|
|
481
|
+
* report what the build output / dev config shows.
|
|
482
|
+
*/ const SHARED_STATE_PACKAGE_PATTERNS = [
|
|
483
|
+
...RUNTIME_PACKAGE_PATTERNS,
|
|
484
|
+
/^@prostojs\/(infact|mate)($|\/)/,
|
|
485
|
+
/^@atscript\//
|
|
486
|
+
];
|
|
472
487
|
function escapeRegExp(input) {
|
|
473
488
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
474
489
|
}
|
|
@@ -596,22 +611,123 @@ function readPkgJson(dir) {
|
|
|
596
611
|
}
|
|
597
612
|
return found;
|
|
598
613
|
}
|
|
599
|
-
/**
|
|
600
|
-
|
|
614
|
+
/** One warning line per split: the consumer, its external chain and its split deps (tagged `label`). */ function formatSplitLines(splits, label) {
|
|
615
|
+
return splits.map((s) => {
|
|
601
616
|
const chain = s.via.length > 0 ? ` (loaded via external ${s.via.join(" → ")})` : "";
|
|
602
|
-
const deps = s.splitDeps.map((d) => `${d} (
|
|
617
|
+
const deps = s.splitDeps.map((d) => `${d} (${label})`).join(", ");
|
|
603
618
|
return ` - ${s.name}${chain} depends on ${deps}`;
|
|
604
619
|
});
|
|
620
|
+
}
|
|
621
|
+
/** Human-readable build warning for {@link findSplitPackages} results. */ function formatSplitPackagesWarning(splits) {
|
|
605
622
|
const direct = [...new Set(splits.map((s) => s.via.length > 0 ? s.via[0] : s.name))];
|
|
606
623
|
return [
|
|
607
624
|
"These externalized packages depend on packages that are bundled into dist/server, so Node will load a second copy of them from node_modules:",
|
|
608
|
-
...
|
|
625
|
+
...formatSplitLines(splits, "bundled"),
|
|
609
626
|
"Two copies of a package split its module state — event-context slots, DI registries and class identity (instanceof) stop matching across the boundary, in production only. Symptoms: \"Cannot read properties of undefined (reading 'headers')\" inside a wooks composable, or a database adapter creating an empty table where a managed view was declared.",
|
|
610
627
|
`Fix: keep each shared package and everything that depends on it on the same side — add ${direct.map((d) => `'${d}'`).join(", ")} to ssr.noExternal (or drop them from ssr.external / ssrExternal), or externalize the whole family (for example every @atscript/* package, or the whole moost/wooks runtime) via ssr.external.`,
|
|
611
628
|
"Set ssrExternalCheck: false in moostVite() to silence this check, or ssrExternalCheck: { packages: [...] } to watch more packages."
|
|
612
629
|
].join("\n");
|
|
613
630
|
}
|
|
614
631
|
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region packages/vite/src/ssr-externals-dev-check.ts
|
|
634
|
+
const toArray = (v) => Array.isArray(v) ? v : [v];
|
|
635
|
+
/** A `noExternal` string entry is a glob over package names (`@acme/*`), as in Vite's filter. */ function globToRegExp(glob) {
|
|
636
|
+
const source = glob.split("**").map((part) => part.split("*").map((chunk) => escapeRegExp(chunk)).join("[^/]*")).join(".*");
|
|
637
|
+
return new RegExp(`^${source}$`);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Whether Vite's dev SSR module runner evaluates its own copy of a package —
|
|
641
|
+
* mirroring Vite's externalization rules for bare imports: listed in `external`
|
|
642
|
+
* → external; matched by `noExternal` → inlined; otherwise external when it
|
|
643
|
+
* resolves into `node_modules`, inlined when it is linked (a workspace package
|
|
644
|
+
* outside `node_modules`). Packages that do not resolve from `root` count as
|
|
645
|
+
* external — the runner never loads them.
|
|
646
|
+
*/ function createDevInlineCheck(root, config) {
|
|
647
|
+
const { external = [], noExternal = [] } = config;
|
|
648
|
+
const noExternalPatterns = typeof noExternal === "boolean" ? [] : toArray(noExternal).map((p) => p instanceof RegExp ? p : globToRegExp(p));
|
|
649
|
+
const cache = /* @__PURE__ */ new Map();
|
|
650
|
+
const decide = (name) => {
|
|
651
|
+
if (external !== true && external.includes(name)) return false;
|
|
652
|
+
if (typeof noExternal === "boolean") return noExternal;
|
|
653
|
+
if (noExternalPatterns.some((re) => re.test(name))) return true;
|
|
654
|
+
if (external === true) return false;
|
|
655
|
+
const dir = findPackageDir(name, root);
|
|
656
|
+
return dir !== void 0 && !dir.replaceAll("\\", "/").includes("/node_modules/");
|
|
657
|
+
};
|
|
658
|
+
return (name) => {
|
|
659
|
+
let inlined = cache.get(name);
|
|
660
|
+
if (inlined === void 0) {
|
|
661
|
+
inlined = decide(name);
|
|
662
|
+
cache.set(name, inlined);
|
|
663
|
+
}
|
|
664
|
+
return inlined;
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Package names `root` depends on at runtime — `devDependencies` are left out, like
|
|
669
|
+
* the build check does: they are build tooling (Vite plugins such as
|
|
670
|
+
* `unplugin-atscript`) that Node loads for Vite itself, never next to app code.
|
|
671
|
+
*/ function rootDependencies(root) {
|
|
672
|
+
const pkg = readPkgJson(root);
|
|
673
|
+
if (!pkg) return [];
|
|
674
|
+
const names = /* @__PURE__ */ new Set();
|
|
675
|
+
for (const group of [
|
|
676
|
+
pkg.dependencies,
|
|
677
|
+
pkg.peerDependencies,
|
|
678
|
+
pkg.optionalDependencies
|
|
679
|
+
]) for (const dep of Object.keys(group ?? {})) names.add(dep);
|
|
680
|
+
return [...names];
|
|
681
|
+
}
|
|
682
|
+
/** Is `entry` (a `noExternal` entry) the plugin's own (`PLUGIN_NO_EXTERNAL`)? */ const isPluginOwnEntry = (entry) => entry instanceof RegExp && entry.source === PLUGIN_NO_EXTERNAL.source;
|
|
683
|
+
/**
|
|
684
|
+
* The dev-server counterpart of {@link findSplitPackages}. In `vite serve` the
|
|
685
|
+
* SSR module runner evaluates app code and every *inlined* dependency, while
|
|
686
|
+
* Node loads every *externalized* one natively. When an external package
|
|
687
|
+
* depends on a watched package the runner inlines (forced by `ssr.noExternal`,
|
|
688
|
+
* or a linked workspace package), the two sides run separate copies of it —
|
|
689
|
+
* the same split as in production, only in dev.
|
|
690
|
+
*
|
|
691
|
+
* The externals walked are the root package's direct dependencies the runner
|
|
692
|
+
* does not inline (and their dependency trees). The plugin itself is always
|
|
693
|
+
* loaded by Node and works on Node's `moost` (DI cleanup on reload, init
|
|
694
|
+
* capture), so an inlined `moost` is reported against `@moostjs/vite` too.
|
|
695
|
+
*
|
|
696
|
+
* Skips the walk when nothing watched can be inlined: no `noExternal` entry
|
|
697
|
+
* beyond the plugin's own, and no watched direct dependency that is linked.
|
|
698
|
+
*/ function findDevSplitPackages(opts) {
|
|
699
|
+
const patterns = opts.patterns ?? SHARED_STATE_PACKAGE_PATTERNS;
|
|
700
|
+
const isInlined = createDevInlineCheck(opts.root, opts.config);
|
|
701
|
+
const isInlinedWatched = (name) => !PLUGIN_NO_EXTERNAL.test(name) && patterns.some((re) => re.test(name)) && isInlined(name);
|
|
702
|
+
const deps = rootDependencies(opts.root);
|
|
703
|
+
const { noExternal = [] } = opts.config;
|
|
704
|
+
if (!(noExternal === true || typeof noExternal !== "boolean" && toArray(noExternal).some((e) => !isPluginOwnEntry(e))) && !deps.some((dep) => isInlinedWatched(dep))) return [];
|
|
705
|
+
const found = findSplitPackages({
|
|
706
|
+
root: opts.root,
|
|
707
|
+
externalIds: deps.filter((dep) => !isInlined(dep)),
|
|
708
|
+
bundledPackages: { has: isInlinedWatched },
|
|
709
|
+
patterns
|
|
710
|
+
});
|
|
711
|
+
if (isInlined("moost") && findPackageDir("moost", opts.root)) found.unshift({
|
|
712
|
+
name: "@moostjs/vite",
|
|
713
|
+
via: [],
|
|
714
|
+
splitDeps: ["moost"]
|
|
715
|
+
});
|
|
716
|
+
return found;
|
|
717
|
+
}
|
|
718
|
+
/** Human-readable dev-server warning for {@link findDevSplitPackages} results. */ function formatDevSplitPackagesWarning(splits) {
|
|
719
|
+
const inlined = [...new Set(splits.flatMap((s) => s.splitDeps))];
|
|
720
|
+
const consumers = [...new Set(splits.map((s) => s.via.length > 0 ? s.via[0] : s.name).filter((n) => n !== "@moostjs/vite"))];
|
|
721
|
+
const addConsumers = consumers.length > 0 ? `, or add ${consumers.map((d) => `'${d}'`).join(", ")} to ssr.noExternal so the runner evaluates those as well` : "";
|
|
722
|
+
return [
|
|
723
|
+
"These packages are loaded natively by Node in dev, but depend on packages Vite's SSR module runner evaluates its own copy of (ssr.noExternal, or a linked workspace package):",
|
|
724
|
+
...formatSplitLines(splits, "inlined"),
|
|
725
|
+
"Two copies of a package split its module state — class identity (\"Class is not Injectable\" when a library resolves an adapter through DI), DI registries and event-context slots stop matching across the boundary.",
|
|
726
|
+
`Fix: let Vite externalize ${inlined.map((d) => `'${d}'`).join(", ")} in dev (remove it from ssr.noExternal; list a linked workspace package in ssr.external)${addConsumers}.`,
|
|
727
|
+
"Set ssrExternalCheck: false in moostVite() to silence this check."
|
|
728
|
+
].join("\n");
|
|
729
|
+
}
|
|
730
|
+
|
|
615
731
|
//#endregion
|
|
616
732
|
//#region packages/vite/src/moost-vite.ts
|
|
617
733
|
/**
|
|
@@ -682,6 +798,7 @@ function moostVite(options) {
|
|
|
682
798
|
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
683
799
|
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
684
800
|
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
801
|
+
const splitCheckPatterns = compilePackagePatterns(typeof options.ssrExternalCheck === "object" ? options.ssrExternalCheck.packages : void 0);
|
|
685
802
|
/**
|
|
686
803
|
* Boot-identity stamps (dev-only "mongrel state" diagnostic — a stale pipeline
|
|
687
804
|
* presents as security middleware silently switched off). `bootGeneration` is
|
|
@@ -846,9 +963,8 @@ function moostVite(options) {
|
|
|
846
963
|
}
|
|
847
964
|
const outDir = cfg.build?.outDir || "dist";
|
|
848
965
|
const isBuild = env.command === "build";
|
|
849
|
-
const ourPlugin = /^@moostjs\/vite($|\/)/;
|
|
850
966
|
const userNoExternal = cfg.ssr?.noExternal;
|
|
851
|
-
let ssrNoExternal = userNoExternal === true ? true : userNoExternal !== void 0 ? [...Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal],
|
|
967
|
+
let ssrNoExternal = userNoExternal === true ? true : userNoExternal !== void 0 ? [...Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal], PLUGIN_NO_EXTERNAL] : isBuild ? true : [PLUGIN_NO_EXTERNAL];
|
|
852
968
|
const userExternal = cfg.ssr?.external;
|
|
853
969
|
const ssrExternal = isBuild ? [...Array.isArray(userExternal) ? userExternal : [], ...options.ssrExternal ?? []] : void 0;
|
|
854
970
|
runtimeExternalized = (ssrExternal ?? []).some((e) => typeof e === "string" && RUNTIME_PACKAGE_PATTERNS.some((re) => re.test(e)));
|
|
@@ -939,7 +1055,7 @@ function moostVite(options) {
|
|
|
939
1055
|
root: cfg.root,
|
|
940
1056
|
externalIds,
|
|
941
1057
|
bundledPackages,
|
|
942
|
-
patterns:
|
|
1058
|
+
patterns: splitCheckPatterns
|
|
943
1059
|
});
|
|
944
1060
|
if (splits.length > 0) cfg.logger.warn(`\n[${PLUGIN_NAME}] ${formatSplitPackagesWarning(splits)}\n`);
|
|
945
1061
|
},
|
|
@@ -958,9 +1074,14 @@ function moostVite(options) {
|
|
|
958
1074
|
return null;
|
|
959
1075
|
},
|
|
960
1076
|
resolveId(id) {
|
|
961
|
-
if (id === "virtual:vite-id") return
|
|
1077
|
+
if (id === "virtual:vite-id" || id.startsWith(ADAPTER_VIRTUAL_PREFIX)) return `\0${id}`;
|
|
962
1078
|
},
|
|
963
1079
|
load(id) {
|
|
1080
|
+
const adapterModule = loadAdapterVirtualModule(id);
|
|
1081
|
+
if (adapterModule !== void 0) return {
|
|
1082
|
+
code: adapterModule,
|
|
1083
|
+
map: null
|
|
1084
|
+
};
|
|
964
1085
|
if (id === "\0virtual:vite-id") return {
|
|
965
1086
|
code: `
|
|
966
1087
|
import { getMoostMate } from "moost";
|
|
@@ -1010,6 +1131,14 @@ function moostVite(options) {
|
|
|
1010
1131
|
await reloadPromise;
|
|
1011
1132
|
}
|
|
1012
1133
|
};
|
|
1134
|
+
if (options.ssrExternalCheck !== false) {
|
|
1135
|
+
const splits = findDevSplitPackages({
|
|
1136
|
+
root: server.config.root,
|
|
1137
|
+
config: server.environments.ssr.config.resolve,
|
|
1138
|
+
patterns: splitCheckPatterns
|
|
1139
|
+
});
|
|
1140
|
+
if (splits.length > 0) server.config.logger.warn(`\n[${PLUGIN_NAME}] ${formatDevSplitPackagesWarning(splits)}\n`);
|
|
1141
|
+
}
|
|
1013
1142
|
for (const adapter of adapters) adapter.ssrLoadModule = ssrImport;
|
|
1014
1143
|
await prepareBoot(EJECT_ALL);
|
|
1015
1144
|
await ssrImport(options.entry);
|
package/dist/index.d.ts
CHANGED
|
@@ -170,11 +170,15 @@ interface TMoostViteDevOptions {
|
|
|
170
170
|
* (`vite serve`) is unaffected: Vite's default externalizer continues
|
|
171
171
|
* to handle node_modules, which is required so CJS-only packages like
|
|
172
172
|
* `@vue/server-renderer` can be loaded by Node's ESM/CJS interop
|
|
173
|
-
* instead of evaluated by Vite's ESM-only SSR module runner.
|
|
173
|
+
* instead of evaluated by Vite's ESM-only SSR module runner. It also keeps
|
|
174
|
+
* the moost/wooks runtime a single (Node-loaded) copy shared by app code and
|
|
175
|
+
* natively loaded dependencies — don't put the runtime in `ssr.noExternal`
|
|
176
|
+
* for dev.
|
|
174
177
|
*/
|
|
175
178
|
ssrExternal?: string[];
|
|
176
179
|
/**
|
|
177
|
-
* Verify the
|
|
180
|
+
* Verify the SSR module graph for split shared-state packages — in the
|
|
181
|
+
* production build and on the dev server.
|
|
178
182
|
*
|
|
179
183
|
* After the middleware-mode `vite build`, the plugin compares what ended up
|
|
180
184
|
* inside `dist/server` (the bundled packages) with the bare imports left in
|
|
@@ -184,12 +188,18 @@ interface TMoostViteDevOptions {
|
|
|
184
188
|
* and `instanceof` checks stop matching in production only — so the build
|
|
185
189
|
* prints a warning naming the package and the fix.
|
|
186
190
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
+
* On `vite serve` (both modes) the same walk runs against the dev SSR config:
|
|
192
|
+
* an externalized dependency (loaded natively by Node) that depends on a
|
|
193
|
+
* watched package the SSR module runner inlines — forced by `ssr.noExternal`,
|
|
194
|
+
* or a linked workspace package — gets a second copy in dev, and the server
|
|
195
|
+
* prints a warning at startup.
|
|
191
196
|
*
|
|
192
|
-
*
|
|
197
|
+
* Watched by default: `moost`, `@moostjs/*`, `wooks`, `@wooksjs/*`,
|
|
198
|
+
* `@prostojs/infact`, `@prostojs/mate` and `@atscript/*`. Pass
|
|
199
|
+
* `{ packages: [...] }` to watch more: an exact package name (`'lodash'`), a
|
|
200
|
+
* scope/prefix ending with `/` (`'@acme/'`), or a `RegExp`.
|
|
201
|
+
*
|
|
202
|
+
* Default: `true`. Set `false` to silence both checks.
|
|
193
203
|
*/
|
|
194
204
|
ssrExternalCheck?: boolean | TSSRExternalCheckOptions;
|
|
195
205
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -113,6 +113,12 @@ function getExternals({ node, workspace }) {
|
|
|
113
113
|
|
|
114
114
|
//#endregion
|
|
115
115
|
//#region packages/vite/src/adapter-detector.ts
|
|
116
|
+
/** Id prefix of the virtual modules re-exporting an adapter package (`virtual:moost-adapter/http`). */ const ADAPTER_VIRTUAL_PREFIX = "virtual:moost-adapter/";
|
|
117
|
+
/** Source of a resolved (`\0`-prefixed) adapter virtual module, or `undefined` for any other id. */ function loadAdapterVirtualModule(id) {
|
|
118
|
+
if (!id.startsWith(`\0${ADAPTER_VIRTUAL_PREFIX}`)) return;
|
|
119
|
+
const adapter = id.slice(23);
|
|
120
|
+
return `export * from ${JSON.stringify(`@moostjs/event-${adapter}`)}\n`;
|
|
121
|
+
}
|
|
116
122
|
/**
|
|
117
123
|
* Creates an adapter detector for a specific adapter type.
|
|
118
124
|
* @param adapter
|
|
@@ -127,7 +133,7 @@ function getExternals({ node, workspace }) {
|
|
|
127
133
|
async init() {
|
|
128
134
|
this.detected = true;
|
|
129
135
|
const moduleId = `@moostjs/event-${adapter}`;
|
|
130
|
-
const module = this.ssrLoadModule ? await this.ssrLoadModule(
|
|
136
|
+
const module = this.ssrLoadModule ? await this.ssrLoadModule(`${ADAPTER_VIRTUAL_PREFIX}${adapter}`) : await import(moduleId);
|
|
131
137
|
const constructorName = `Moost${adapter.charAt(0).toUpperCase() + adapter.slice(1)}`;
|
|
132
138
|
getLogger().log(`🔍 [2mExtracting Adapter "${constructorName}"`);
|
|
133
139
|
this.constructor = module[constructorName];
|
|
@@ -431,15 +437,24 @@ function constructorName(i) {
|
|
|
431
437
|
/^wooks($|\/)/
|
|
432
438
|
];
|
|
433
439
|
/**
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
|
|
437
|
-
|
|
440
|
+
* The `ssr.noExternal` entry the plugin always adds, so the `define:`
|
|
441
|
+
* substitutions in `prod-server.mjs` land.
|
|
442
|
+
*/ const PLUGIN_NO_EXTERNAL = /^@moostjs\/vite($|\/)/;
|
|
443
|
+
/**
|
|
444
|
+
* Packages the split checks watch by default: the moost/wooks runtime, the DI
|
|
445
|
+
* and metadata containers under it (`@prostojs/infact`, `@prostojs/mate`) and
|
|
446
|
+
* the `@atscript/*` family. All of them keep module-level state — Symbol slot
|
|
447
|
+
* keys, DI/model registries, class identity used by `instanceof` — so a second
|
|
448
|
+
* copy loaded by Node breaks lookups that the other copy filled in.
|
|
438
449
|
*
|
|
439
450
|
* This is deliberately wider than {@link RUNTIME_PACKAGE_PATTERNS}: the guard
|
|
440
|
-
* that force-bundles packages covers the runtime only, while the
|
|
441
|
-
*
|
|
442
|
-
*/ const SHARED_STATE_PACKAGE_PATTERNS = [
|
|
451
|
+
* that force-bundles packages covers the runtime only, while the checks merely
|
|
452
|
+
* report what the build output / dev config shows.
|
|
453
|
+
*/ const SHARED_STATE_PACKAGE_PATTERNS = [
|
|
454
|
+
...RUNTIME_PACKAGE_PATTERNS,
|
|
455
|
+
/^@prostojs\/(infact|mate)($|\/)/,
|
|
456
|
+
/^@atscript\//
|
|
457
|
+
];
|
|
443
458
|
function escapeRegExp(input) {
|
|
444
459
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
445
460
|
}
|
|
@@ -567,22 +582,123 @@ function readPkgJson(dir) {
|
|
|
567
582
|
}
|
|
568
583
|
return found;
|
|
569
584
|
}
|
|
570
|
-
/**
|
|
571
|
-
|
|
585
|
+
/** One warning line per split: the consumer, its external chain and its split deps (tagged `label`). */ function formatSplitLines(splits, label) {
|
|
586
|
+
return splits.map((s) => {
|
|
572
587
|
const chain = s.via.length > 0 ? ` (loaded via external ${s.via.join(" → ")})` : "";
|
|
573
|
-
const deps = s.splitDeps.map((d) => `${d} (
|
|
588
|
+
const deps = s.splitDeps.map((d) => `${d} (${label})`).join(", ");
|
|
574
589
|
return ` - ${s.name}${chain} depends on ${deps}`;
|
|
575
590
|
});
|
|
591
|
+
}
|
|
592
|
+
/** Human-readable build warning for {@link findSplitPackages} results. */ function formatSplitPackagesWarning(splits) {
|
|
576
593
|
const direct = [...new Set(splits.map((s) => s.via.length > 0 ? s.via[0] : s.name))];
|
|
577
594
|
return [
|
|
578
595
|
"These externalized packages depend on packages that are bundled into dist/server, so Node will load a second copy of them from node_modules:",
|
|
579
|
-
...
|
|
596
|
+
...formatSplitLines(splits, "bundled"),
|
|
580
597
|
"Two copies of a package split its module state — event-context slots, DI registries and class identity (instanceof) stop matching across the boundary, in production only. Symptoms: \"Cannot read properties of undefined (reading 'headers')\" inside a wooks composable, or a database adapter creating an empty table where a managed view was declared.",
|
|
581
598
|
`Fix: keep each shared package and everything that depends on it on the same side — add ${direct.map((d) => `'${d}'`).join(", ")} to ssr.noExternal (or drop them from ssr.external / ssrExternal), or externalize the whole family (for example every @atscript/* package, or the whole moost/wooks runtime) via ssr.external.`,
|
|
582
599
|
"Set ssrExternalCheck: false in moostVite() to silence this check, or ssrExternalCheck: { packages: [...] } to watch more packages."
|
|
583
600
|
].join("\n");
|
|
584
601
|
}
|
|
585
602
|
|
|
603
|
+
//#endregion
|
|
604
|
+
//#region packages/vite/src/ssr-externals-dev-check.ts
|
|
605
|
+
const toArray = (v) => Array.isArray(v) ? v : [v];
|
|
606
|
+
/** A `noExternal` string entry is a glob over package names (`@acme/*`), as in Vite's filter. */ function globToRegExp(glob) {
|
|
607
|
+
const source = glob.split("**").map((part) => part.split("*").map((chunk) => escapeRegExp(chunk)).join("[^/]*")).join(".*");
|
|
608
|
+
return new RegExp(`^${source}$`);
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Whether Vite's dev SSR module runner evaluates its own copy of a package —
|
|
612
|
+
* mirroring Vite's externalization rules for bare imports: listed in `external`
|
|
613
|
+
* → external; matched by `noExternal` → inlined; otherwise external when it
|
|
614
|
+
* resolves into `node_modules`, inlined when it is linked (a workspace package
|
|
615
|
+
* outside `node_modules`). Packages that do not resolve from `root` count as
|
|
616
|
+
* external — the runner never loads them.
|
|
617
|
+
*/ function createDevInlineCheck(root, config) {
|
|
618
|
+
const { external = [], noExternal = [] } = config;
|
|
619
|
+
const noExternalPatterns = typeof noExternal === "boolean" ? [] : toArray(noExternal).map((p) => p instanceof RegExp ? p : globToRegExp(p));
|
|
620
|
+
const cache = /* @__PURE__ */ new Map();
|
|
621
|
+
const decide = (name) => {
|
|
622
|
+
if (external !== true && external.includes(name)) return false;
|
|
623
|
+
if (typeof noExternal === "boolean") return noExternal;
|
|
624
|
+
if (noExternalPatterns.some((re) => re.test(name))) return true;
|
|
625
|
+
if (external === true) return false;
|
|
626
|
+
const dir = findPackageDir(name, root);
|
|
627
|
+
return dir !== void 0 && !dir.replaceAll("\\", "/").includes("/node_modules/");
|
|
628
|
+
};
|
|
629
|
+
return (name) => {
|
|
630
|
+
let inlined = cache.get(name);
|
|
631
|
+
if (inlined === void 0) {
|
|
632
|
+
inlined = decide(name);
|
|
633
|
+
cache.set(name, inlined);
|
|
634
|
+
}
|
|
635
|
+
return inlined;
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Package names `root` depends on at runtime — `devDependencies` are left out, like
|
|
640
|
+
* the build check does: they are build tooling (Vite plugins such as
|
|
641
|
+
* `unplugin-atscript`) that Node loads for Vite itself, never next to app code.
|
|
642
|
+
*/ function rootDependencies(root) {
|
|
643
|
+
const pkg = readPkgJson(root);
|
|
644
|
+
if (!pkg) return [];
|
|
645
|
+
const names = /* @__PURE__ */ new Set();
|
|
646
|
+
for (const group of [
|
|
647
|
+
pkg.dependencies,
|
|
648
|
+
pkg.peerDependencies,
|
|
649
|
+
pkg.optionalDependencies
|
|
650
|
+
]) for (const dep of Object.keys(group ?? {})) names.add(dep);
|
|
651
|
+
return [...names];
|
|
652
|
+
}
|
|
653
|
+
/** Is `entry` (a `noExternal` entry) the plugin's own (`PLUGIN_NO_EXTERNAL`)? */ const isPluginOwnEntry = (entry) => entry instanceof RegExp && entry.source === PLUGIN_NO_EXTERNAL.source;
|
|
654
|
+
/**
|
|
655
|
+
* The dev-server counterpart of {@link findSplitPackages}. In `vite serve` the
|
|
656
|
+
* SSR module runner evaluates app code and every *inlined* dependency, while
|
|
657
|
+
* Node loads every *externalized* one natively. When an external package
|
|
658
|
+
* depends on a watched package the runner inlines (forced by `ssr.noExternal`,
|
|
659
|
+
* or a linked workspace package), the two sides run separate copies of it —
|
|
660
|
+
* the same split as in production, only in dev.
|
|
661
|
+
*
|
|
662
|
+
* The externals walked are the root package's direct dependencies the runner
|
|
663
|
+
* does not inline (and their dependency trees). The plugin itself is always
|
|
664
|
+
* loaded by Node and works on Node's `moost` (DI cleanup on reload, init
|
|
665
|
+
* capture), so an inlined `moost` is reported against `@moostjs/vite` too.
|
|
666
|
+
*
|
|
667
|
+
* Skips the walk when nothing watched can be inlined: no `noExternal` entry
|
|
668
|
+
* beyond the plugin's own, and no watched direct dependency that is linked.
|
|
669
|
+
*/ function findDevSplitPackages(opts) {
|
|
670
|
+
const patterns = opts.patterns ?? SHARED_STATE_PACKAGE_PATTERNS;
|
|
671
|
+
const isInlined = createDevInlineCheck(opts.root, opts.config);
|
|
672
|
+
const isInlinedWatched = (name) => !PLUGIN_NO_EXTERNAL.test(name) && patterns.some((re) => re.test(name)) && isInlined(name);
|
|
673
|
+
const deps = rootDependencies(opts.root);
|
|
674
|
+
const { noExternal = [] } = opts.config;
|
|
675
|
+
if (!(noExternal === true || typeof noExternal !== "boolean" && toArray(noExternal).some((e) => !isPluginOwnEntry(e))) && !deps.some((dep) => isInlinedWatched(dep))) return [];
|
|
676
|
+
const found = findSplitPackages({
|
|
677
|
+
root: opts.root,
|
|
678
|
+
externalIds: deps.filter((dep) => !isInlined(dep)),
|
|
679
|
+
bundledPackages: { has: isInlinedWatched },
|
|
680
|
+
patterns
|
|
681
|
+
});
|
|
682
|
+
if (isInlined("moost") && findPackageDir("moost", opts.root)) found.unshift({
|
|
683
|
+
name: "@moostjs/vite",
|
|
684
|
+
via: [],
|
|
685
|
+
splitDeps: ["moost"]
|
|
686
|
+
});
|
|
687
|
+
return found;
|
|
688
|
+
}
|
|
689
|
+
/** Human-readable dev-server warning for {@link findDevSplitPackages} results. */ function formatDevSplitPackagesWarning(splits) {
|
|
690
|
+
const inlined = [...new Set(splits.flatMap((s) => s.splitDeps))];
|
|
691
|
+
const consumers = [...new Set(splits.map((s) => s.via.length > 0 ? s.via[0] : s.name).filter((n) => n !== "@moostjs/vite"))];
|
|
692
|
+
const addConsumers = consumers.length > 0 ? `, or add ${consumers.map((d) => `'${d}'`).join(", ")} to ssr.noExternal so the runner evaluates those as well` : "";
|
|
693
|
+
return [
|
|
694
|
+
"These packages are loaded natively by Node in dev, but depend on packages Vite's SSR module runner evaluates its own copy of (ssr.noExternal, or a linked workspace package):",
|
|
695
|
+
...formatSplitLines(splits, "inlined"),
|
|
696
|
+
"Two copies of a package split its module state — class identity (\"Class is not Injectable\" when a library resolves an adapter through DI), DI registries and event-context slots stop matching across the boundary.",
|
|
697
|
+
`Fix: let Vite externalize ${inlined.map((d) => `'${d}'`).join(", ")} in dev (remove it from ssr.noExternal; list a linked workspace package in ssr.external)${addConsumers}.`,
|
|
698
|
+
"Set ssrExternalCheck: false in moostVite() to silence this check."
|
|
699
|
+
].join("\n");
|
|
700
|
+
}
|
|
701
|
+
|
|
586
702
|
//#endregion
|
|
587
703
|
//#region packages/vite/src/moost-vite.ts
|
|
588
704
|
/**
|
|
@@ -651,6 +767,7 @@ function moostVite(options) {
|
|
|
651
767
|
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
652
768
|
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
653
769
|
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
770
|
+
const splitCheckPatterns = compilePackagePatterns(typeof options.ssrExternalCheck === "object" ? options.ssrExternalCheck.packages : void 0);
|
|
654
771
|
/**
|
|
655
772
|
* Boot-identity stamps (dev-only "mongrel state" diagnostic — a stale pipeline
|
|
656
773
|
* presents as security middleware silently switched off). `bootGeneration` is
|
|
@@ -815,9 +932,8 @@ function moostVite(options) {
|
|
|
815
932
|
}
|
|
816
933
|
const outDir = cfg.build?.outDir || "dist";
|
|
817
934
|
const isBuild = env.command === "build";
|
|
818
|
-
const ourPlugin = /^@moostjs\/vite($|\/)/;
|
|
819
935
|
const userNoExternal = cfg.ssr?.noExternal;
|
|
820
|
-
let ssrNoExternal = userNoExternal === true ? true : userNoExternal !== void 0 ? [...Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal],
|
|
936
|
+
let ssrNoExternal = userNoExternal === true ? true : userNoExternal !== void 0 ? [...Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal], PLUGIN_NO_EXTERNAL] : isBuild ? true : [PLUGIN_NO_EXTERNAL];
|
|
821
937
|
const userExternal = cfg.ssr?.external;
|
|
822
938
|
const ssrExternal = isBuild ? [...Array.isArray(userExternal) ? userExternal : [], ...options.ssrExternal ?? []] : void 0;
|
|
823
939
|
runtimeExternalized = (ssrExternal ?? []).some((e) => typeof e === "string" && RUNTIME_PACKAGE_PATTERNS.some((re) => re.test(e)));
|
|
@@ -908,7 +1024,7 @@ function moostVite(options) {
|
|
|
908
1024
|
root: cfg.root,
|
|
909
1025
|
externalIds,
|
|
910
1026
|
bundledPackages,
|
|
911
|
-
patterns:
|
|
1027
|
+
patterns: splitCheckPatterns
|
|
912
1028
|
});
|
|
913
1029
|
if (splits.length > 0) cfg.logger.warn(`\n[${PLUGIN_NAME}] ${formatSplitPackagesWarning(splits)}\n`);
|
|
914
1030
|
},
|
|
@@ -927,9 +1043,14 @@ function moostVite(options) {
|
|
|
927
1043
|
return null;
|
|
928
1044
|
},
|
|
929
1045
|
resolveId(id) {
|
|
930
|
-
if (id === "virtual:vite-id") return
|
|
1046
|
+
if (id === "virtual:vite-id" || id.startsWith(ADAPTER_VIRTUAL_PREFIX)) return `\0${id}`;
|
|
931
1047
|
},
|
|
932
1048
|
load(id) {
|
|
1049
|
+
const adapterModule = loadAdapterVirtualModule(id);
|
|
1050
|
+
if (adapterModule !== void 0) return {
|
|
1051
|
+
code: adapterModule,
|
|
1052
|
+
map: null
|
|
1053
|
+
};
|
|
933
1054
|
if (id === "\0virtual:vite-id") return {
|
|
934
1055
|
code: `
|
|
935
1056
|
import { getMoostMate } from "moost";
|
|
@@ -979,6 +1100,14 @@ function moostVite(options) {
|
|
|
979
1100
|
await reloadPromise;
|
|
980
1101
|
}
|
|
981
1102
|
};
|
|
1103
|
+
if (options.ssrExternalCheck !== false) {
|
|
1104
|
+
const splits = findDevSplitPackages({
|
|
1105
|
+
root: server.config.root,
|
|
1106
|
+
config: server.environments.ssr.config.resolve,
|
|
1107
|
+
patterns: splitCheckPatterns
|
|
1108
|
+
});
|
|
1109
|
+
if (splits.length > 0) server.config.logger.warn(`\n[${PLUGIN_NAME}] ${formatDevSplitPackagesWarning(splits)}\n`);
|
|
1110
|
+
}
|
|
982
1111
|
for (const adapter of adapters) adapter.ssrLoadModule = ssrImport;
|
|
983
1112
|
await prepareBoot(EJECT_ALL);
|
|
984
1113
|
await ssrImport(options.entry);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moostjs/vite",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.44",
|
|
4
4
|
"description": "Vite Dev plugin for moostjs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"composables",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"sirv": "^3.0.0",
|
|
60
60
|
"vite": "^8.0.0",
|
|
61
|
-
"@moostjs/event-http": "^0.6.
|
|
62
|
-
"moost": "^0.6.
|
|
61
|
+
"@moostjs/event-http": "^0.6.44",
|
|
62
|
+
"moost": "^0.6.44"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"sirv": {
|