@moostjs/vite 0.6.39 → 0.6.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +66 -33
- package/dist/index.mjs +66 -33
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -337,30 +337,41 @@ function _define_property(obj, key, value) {
|
|
|
337
337
|
|
|
338
338
|
//#endregion
|
|
339
339
|
//#region packages/vite/src/restart-cleanup.ts
|
|
340
|
+
/** Metadata key the transform's `@__VITE_ID(<module id>)` stamps on DI classes. */ const VITE_ID_KEY = "__vite_id";
|
|
341
|
+
/** The module id stamped on the class of `target` (a class or an instance), if any. */ function readViteId(target) {
|
|
342
|
+
return (0, moost.getMoostMate)().read(target)?.[VITE_ID_KEY];
|
|
343
|
+
}
|
|
344
|
+
/** Cleanup scope of a full reboot (server start/restart, full invalidation). */ const EJECT_ALL = "all";
|
|
345
|
+
/** Coalesces a queued cleanup with the next one: module ids add up, `EJECT_ALL` wins. */ function mergeCleanup(pending, next) {
|
|
346
|
+
if (pending === EJECT_ALL || next === EJECT_ALL) return EJECT_ALL;
|
|
347
|
+
return pending ? new Set([...pending, ...next]) : next;
|
|
348
|
+
}
|
|
340
349
|
/**
|
|
341
|
-
* Clean up Moost’s global containers and
|
|
350
|
+
* Clean up Moost’s global containers and eject instances from the registry:
|
|
351
|
+
* those of the given module ids (plus, transitively, their dependants), or —
|
|
352
|
+
* with `EJECT_ALL`, the default — every instance.
|
|
342
353
|
*
|
|
343
354
|
* Every instance actually removed from the registry is **disposed** before the
|
|
344
355
|
* caches are dropped: its `@MoostDispose` hooks (or `Symbol.asyncDispose` /
|
|
345
356
|
* `Symbol.dispose`) are awaited, so a singleton owning a connection, consumer,
|
|
346
357
|
* timer or file handle releases it instead of leaking one copy per reload. An
|
|
347
|
-
* instance kept by an `onEject` veto is never disposed
|
|
348
|
-
*
|
|
358
|
+
* instance kept by an `onEject` veto is never disposed (there is no veto on a
|
|
359
|
+
* full reboot: the registry is dropped either way). A failing hook is warned
|
|
360
|
+
* about and the reload continues.
|
|
349
361
|
*
|
|
350
|
-
* @param {Set<string>} [cleanupInstances] A set of module IDs to remove from the registry.
|
|
351
362
|
* @returns the instances that were ejected (and therefore disposed)
|
|
352
|
-
*/ async function moostRestartCleanup(onEject,
|
|
363
|
+
*/ async function moostRestartCleanup(onEject, cleanup = EJECT_ALL) {
|
|
353
364
|
const logger = getLogger();
|
|
354
365
|
const infact = (0, moost.getMoostInfact)();
|
|
355
366
|
const { registry } = infact;
|
|
356
367
|
infact._cleanup();
|
|
357
|
-
const mate = (0, moost.getMoostMate)();
|
|
358
368
|
/** Instances removed from the registry by this run — disposed below, before the caches drop. */ const ejected = [];
|
|
359
|
-
if (
|
|
369
|
+
if (cleanup === EJECT_ALL) for (const key of Object.getOwnPropertySymbols(registry)) ejected.push(registry[key]);
|
|
370
|
+
else {
|
|
360
371
|
for (const key of Object.getOwnPropertySymbols(registry)) {
|
|
361
372
|
const instance = registry[key];
|
|
362
|
-
const viteId =
|
|
363
|
-
if (viteId &&
|
|
373
|
+
const viteId = readViteId(instance);
|
|
374
|
+
if (viteId && cleanup.has(viteId)) {
|
|
364
375
|
logger.debug(`🔃 Replacing "${constructorName(instance)}"`);
|
|
365
376
|
delete registry[key];
|
|
366
377
|
ejected.push(instance);
|
|
@@ -603,8 +614,11 @@ function readPkgJson(dir) {
|
|
|
603
614
|
|
|
604
615
|
//#endregion
|
|
605
616
|
//#region packages/vite/src/moost-vite.ts
|
|
606
|
-
/**
|
|
607
|
-
|
|
617
|
+
/**
|
|
618
|
+
* Classes that land in the DI registry: every `@Injectable()`, `@Controller()`
|
|
619
|
+
* and `@Interceptor()` class (exported or not) gets `@__VITE_ID(<module id>)`,
|
|
620
|
+
* which drives the per-module eject on reload.
|
|
621
|
+
*/ const REG_DI_CLASS = /(^\s*@(Injectable|Controller|Interceptor)\()/gm;
|
|
608
622
|
/**
|
|
609
623
|
* The main Vite plugin for integrating Moost applications.
|
|
610
624
|
*
|
|
@@ -613,7 +627,7 @@ const REG_REPLACE_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/gm;
|
|
|
613
627
|
* - **Dev Mode Middleware**:
|
|
614
628
|
* - Patches `MoostHttp.prototype.listen` to register a custom middleware for serving the app via Vite's dev server instead of binding to a port.
|
|
615
629
|
* - Handles Moost state cleanup and hot module replacement (HMR) during development.
|
|
616
|
-
* - **Class Tracking**: Injects a `__VITE_ID()` decorator into
|
|
630
|
+
* - **Class Tracking**: Injects a `__VITE_ID()` decorator into DI classes to enable tracking and cleanup during hot reloads.
|
|
617
631
|
* - **Externals Support**:
|
|
618
632
|
* - Allows marking Node.js built-in modules and dependencies from `package.json` (optionally excluding workspace dependencies) as external during builds.
|
|
619
633
|
* - Configured via the `externals` option, which helps reduce bundle size and ensures compatibility with runtime environments.
|
|
@@ -665,6 +679,9 @@ function moostVite(options) {
|
|
|
665
679
|
* boot, cleared on eject.
|
|
666
680
|
*/ const moostHttpRef = { current: null };
|
|
667
681
|
const ssrForwarding = options.ssrFetchForwarding !== false;
|
|
682
|
+
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
683
|
+
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
684
|
+
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
668
685
|
/**
|
|
669
686
|
* Boot-identity stamps (dev-only "mongrel state" diagnostic — a stale pipeline
|
|
670
687
|
* presents as security middleware silently switched off). `bootGeneration` is
|
|
@@ -680,7 +697,7 @@ function moostVite(options) {
|
|
|
680
697
|
* several when one entry boots several apps, none for a boot that never calls
|
|
681
698
|
* `init()`. Reset by `beginBoot()`, consumed by `settleBootInit()`.
|
|
682
699
|
*/ let bootInitPromises = [];
|
|
683
|
-
/**
|
|
700
|
+
/** DI cleanup awaiting the next reload (module IDs, or EJECT_ALL) — consumed in runReload; see ejectApp. */ let pendingCleanup = null;
|
|
684
701
|
/** In middleware mode: maps req → next() for the onNoMatch callback */ const pendingNextMap = /* @__PURE__ */ new WeakMap();
|
|
685
702
|
const adapters = isTest ? [] : [
|
|
686
703
|
createAdapterDetector("http", (MoostHttp, moduleExports) => {
|
|
@@ -736,7 +753,7 @@ function moostVite(options) {
|
|
|
736
753
|
* into the OLD pipeline, producing a mongrel half-old/half-new app. Waves
|
|
737
754
|
* arriving before the lazy reload (editor bulk-save storms) coalesce into one
|
|
738
755
|
* pending set and one cleanup.
|
|
739
|
-
*/ const ejectApp = (
|
|
756
|
+
*/ const ejectApp = (cleanup) => {
|
|
740
757
|
bootGeneration++;
|
|
741
758
|
moostMiddleware = null;
|
|
742
759
|
moostHttpRef.current = null;
|
|
@@ -744,8 +761,7 @@ function moostVite(options) {
|
|
|
744
761
|
localFetchTeardown();
|
|
745
762
|
localFetchTeardown = null;
|
|
746
763
|
}
|
|
747
|
-
|
|
748
|
-
else pendingCleanup = cleanupInstances;
|
|
764
|
+
pendingCleanup = mergeCleanup(pendingCleanup, cleanup);
|
|
749
765
|
reloadRequired = true;
|
|
750
766
|
};
|
|
751
767
|
patchMoostHandlerLogging();
|
|
@@ -756,6 +772,22 @@ function moostVite(options) {
|
|
|
756
772
|
}
|
|
757
773
|
bootInitPromises.push(promise);
|
|
758
774
|
});
|
|
775
|
+
/**
|
|
776
|
+
* Readies the process for the next evaluation of the entry — the first boot,
|
|
777
|
+
* a `server.restart()` and every reload alike (they drifted apart once: a
|
|
778
|
+
* restart skipped the adapter step and its app bound the port for real):
|
|
779
|
+
* 1. DI cleanup, awaited: the ejected instances' `@MoostDispose` hooks must
|
|
780
|
+
* release what they own (connections, consumers, handles) BEFORE the entry
|
|
781
|
+
* re-imports, or the replacement opens a second copy of the resource.
|
|
782
|
+
* 2. Re-establish the adapter capture. The listen() patch lives on whatever
|
|
783
|
+
* `MoostHttp.prototype` was evaluated first; a new runner or a re-evaluated
|
|
784
|
+
* `@moostjs/event-http` hands the entry an unpatched prototype, and
|
|
785
|
+
* `app.listen()` would bind the port for real → EADDRINUSE. `init()`
|
|
786
|
+
* re-resolves the adapter through the runner the entry imports from.
|
|
787
|
+
*/ const prepareBoot = async (cleanup) => {
|
|
788
|
+
await moostRestartCleanup(options.onEject, cleanup);
|
|
789
|
+
for (const adapter of adapters) if (adapter.detected) await adapter.init();
|
|
790
|
+
};
|
|
759
791
|
/** Marks the boot about to run as authoritative for the current generation. */ const beginBoot = () => {
|
|
760
792
|
bootingGeneration = bootGeneration;
|
|
761
793
|
bootInitPromises = [];
|
|
@@ -797,7 +829,11 @@ function moostVite(options) {
|
|
|
797
829
|
"process.env.MOOST_DEFERRED_ENV": "\"production\"",
|
|
798
830
|
__MOOST_ENTRY__: JSON.stringify(`./${entryKey}.js`),
|
|
799
831
|
__MOOST_PREFIX__: JSON.stringify(prefixes ?? null),
|
|
800
|
-
__MOOST_SSR_FORWARDING__: JSON.stringify(ssrForwarding)
|
|
832
|
+
__MOOST_SSR_FORWARDING__: JSON.stringify(ssrForwarding),
|
|
833
|
+
__MOOST_SSR_ENTRY__: "undefined",
|
|
834
|
+
__MOOST_SSR_OUTLET__: JSON.stringify(ssrOutlet),
|
|
835
|
+
__MOOST_SSR_STATE__: JSON.stringify(ssrState),
|
|
836
|
+
__MOOST_SSR_HEAD__: JSON.stringify(ssrHead)
|
|
801
837
|
};
|
|
802
838
|
const ssrInput = {
|
|
803
839
|
server: options.serverEntry || generatedServerEntry(cfg.root),
|
|
@@ -807,9 +843,6 @@ function moostVite(options) {
|
|
|
807
843
|
const ssrBasename = entryBasename(options.ssrEntry);
|
|
808
844
|
ssrInput[`ssr/${ssrBasename.replace(/\.js$/, "")}`] = options.ssrEntry;
|
|
809
845
|
serverDefines.__MOOST_SSR_ENTRY__ = JSON.stringify(`./ssr/${ssrBasename}`);
|
|
810
|
-
serverDefines.__MOOST_SSR_OUTLET__ = JSON.stringify(options.ssrOutlet || DEFAULT_SSR_OUTLET);
|
|
811
|
-
serverDefines.__MOOST_SSR_STATE__ = JSON.stringify(options.ssrState || DEFAULT_SSR_STATE);
|
|
812
|
-
serverDefines.__MOOST_SSR_HEAD__ = JSON.stringify(options.ssrHead || DEFAULT_SSR_HEAD);
|
|
813
846
|
}
|
|
814
847
|
const outDir = cfg.build?.outDir || "dist";
|
|
815
848
|
const isBuild = env.command === "build";
|
|
@@ -913,9 +946,9 @@ function moostVite(options) {
|
|
|
913
946
|
async transform(code, id) {
|
|
914
947
|
if (!id.endsWith(".ts")) return null;
|
|
915
948
|
for (const adapter of adapters) if (!adapter.detected && adapter.regex.test(code)) await adapter.init();
|
|
916
|
-
if (
|
|
949
|
+
if (code.search(REG_DI_CLASS) !== -1) {
|
|
917
950
|
const s = new magic_string.default(code);
|
|
918
|
-
s.replace(
|
|
951
|
+
s.replace(REG_DI_CLASS, "\n@__VITE_ID(import.meta.filename)\n$1");
|
|
919
952
|
s.prepend(`import { __VITE_ID } from 'virtual:vite-id'\n\n`);
|
|
920
953
|
return {
|
|
921
954
|
code: s.toString(),
|
|
@@ -933,7 +966,7 @@ function moostVite(options) {
|
|
|
933
966
|
import { getMoostMate } from "moost";
|
|
934
967
|
const mate = getMoostMate();
|
|
935
968
|
export function __VITE_ID(id) {
|
|
936
|
-
return mate.decorate(
|
|
969
|
+
return mate.decorate(${JSON.stringify(VITE_ID_KEY)}, id)
|
|
937
970
|
}
|
|
938
971
|
`,
|
|
939
972
|
map: null
|
|
@@ -955,10 +988,9 @@ function moostVite(options) {
|
|
|
955
988
|
return (async () => {
|
|
956
989
|
try {
|
|
957
990
|
beginBoot();
|
|
958
|
-
const
|
|
991
|
+
const cleanup = pendingCleanup ?? EJECT_ALL;
|
|
959
992
|
pendingCleanup = null;
|
|
960
|
-
await
|
|
961
|
-
for (const adapter of adapters) if (adapter.detected) await adapter.init();
|
|
993
|
+
await prepareBoot(cleanup);
|
|
962
994
|
const entryModule = await getEntryModule(server.environments.ssr.moduleGraph);
|
|
963
995
|
if (entryModule?.transformResult) server.environments.ssr.moduleGraph.invalidateModule(entryModule);
|
|
964
996
|
await ssrImport(options.entry);
|
|
@@ -979,7 +1011,7 @@ function moostVite(options) {
|
|
|
979
1011
|
}
|
|
980
1012
|
};
|
|
981
1013
|
for (const adapter of adapters) adapter.ssrLoadModule = ssrImport;
|
|
982
|
-
await
|
|
1014
|
+
await prepareBoot(EJECT_ALL);
|
|
983
1015
|
await ssrImport(options.entry);
|
|
984
1016
|
await settleBootInit();
|
|
985
1017
|
server.middlewares.use(async (req, res, next) => {
|
|
@@ -1010,9 +1042,13 @@ function moostVite(options) {
|
|
|
1010
1042
|
const cleanupInstances = /* @__PURE__ */ new Set();
|
|
1011
1043
|
for (const importers of importerSets) for (const impModule of importers) if (impModule.id) cleanupInstances.add(impModule.id);
|
|
1012
1044
|
for (const mod of modules) moduleGraph.invalidateModule(mod);
|
|
1013
|
-
if (entryModule)
|
|
1014
|
-
|
|
1015
|
-
|
|
1045
|
+
if (entryModule) {
|
|
1046
|
+
moduleGraph.invalidateModule(entryModule);
|
|
1047
|
+
ejectApp(cleanupInstances);
|
|
1048
|
+
} else {
|
|
1049
|
+
moduleGraph.invalidateAll();
|
|
1050
|
+
ejectApp(EJECT_ALL);
|
|
1051
|
+
}
|
|
1016
1052
|
return [];
|
|
1017
1053
|
}
|
|
1018
1054
|
};
|
|
@@ -1026,9 +1062,6 @@ function moostVite(options) {
|
|
|
1026
1062
|
return [pluginConfig, !isProd && !isTest && options.middleware && options.ssrEntry ? {
|
|
1027
1063
|
name: `${PLUGIN_NAME}:ssr-fallback`,
|
|
1028
1064
|
async configureServer(server) {
|
|
1029
|
-
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
1030
|
-
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
1031
|
-
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
1032
1065
|
const fs = await import("node:fs/promises");
|
|
1033
1066
|
return () => {
|
|
1034
1067
|
server.middlewares.use(async (req, res, next) => {
|
package/dist/index.mjs
CHANGED
|
@@ -308,30 +308,41 @@ function _define_property(obj, key, value) {
|
|
|
308
308
|
|
|
309
309
|
//#endregion
|
|
310
310
|
//#region packages/vite/src/restart-cleanup.ts
|
|
311
|
+
/** Metadata key the transform's `@__VITE_ID(<module id>)` stamps on DI classes. */ const VITE_ID_KEY = "__vite_id";
|
|
312
|
+
/** The module id stamped on the class of `target` (a class or an instance), if any. */ function readViteId(target) {
|
|
313
|
+
return getMoostMate().read(target)?.[VITE_ID_KEY];
|
|
314
|
+
}
|
|
315
|
+
/** Cleanup scope of a full reboot (server start/restart, full invalidation). */ const EJECT_ALL = "all";
|
|
316
|
+
/** Coalesces a queued cleanup with the next one: module ids add up, `EJECT_ALL` wins. */ function mergeCleanup(pending, next) {
|
|
317
|
+
if (pending === EJECT_ALL || next === EJECT_ALL) return EJECT_ALL;
|
|
318
|
+
return pending ? new Set([...pending, ...next]) : next;
|
|
319
|
+
}
|
|
311
320
|
/**
|
|
312
|
-
* Clean up Moost’s global containers and
|
|
321
|
+
* Clean up Moost’s global containers and eject instances from the registry:
|
|
322
|
+
* those of the given module ids (plus, transitively, their dependants), or —
|
|
323
|
+
* with `EJECT_ALL`, the default — every instance.
|
|
313
324
|
*
|
|
314
325
|
* Every instance actually removed from the registry is **disposed** before the
|
|
315
326
|
* caches are dropped: its `@MoostDispose` hooks (or `Symbol.asyncDispose` /
|
|
316
327
|
* `Symbol.dispose`) are awaited, so a singleton owning a connection, consumer,
|
|
317
328
|
* timer or file handle releases it instead of leaking one copy per reload. An
|
|
318
|
-
* instance kept by an `onEject` veto is never disposed
|
|
319
|
-
*
|
|
329
|
+
* instance kept by an `onEject` veto is never disposed (there is no veto on a
|
|
330
|
+
* full reboot: the registry is dropped either way). A failing hook is warned
|
|
331
|
+
* about and the reload continues.
|
|
320
332
|
*
|
|
321
|
-
* @param {Set<string>} [cleanupInstances] A set of module IDs to remove from the registry.
|
|
322
333
|
* @returns the instances that were ejected (and therefore disposed)
|
|
323
|
-
*/ async function moostRestartCleanup(onEject,
|
|
334
|
+
*/ async function moostRestartCleanup(onEject, cleanup = EJECT_ALL) {
|
|
324
335
|
const logger = getLogger();
|
|
325
336
|
const infact = getMoostInfact();
|
|
326
337
|
const { registry } = infact;
|
|
327
338
|
infact._cleanup();
|
|
328
|
-
const mate = getMoostMate();
|
|
329
339
|
/** Instances removed from the registry by this run — disposed below, before the caches drop. */ const ejected = [];
|
|
330
|
-
if (
|
|
340
|
+
if (cleanup === EJECT_ALL) for (const key of Object.getOwnPropertySymbols(registry)) ejected.push(registry[key]);
|
|
341
|
+
else {
|
|
331
342
|
for (const key of Object.getOwnPropertySymbols(registry)) {
|
|
332
343
|
const instance = registry[key];
|
|
333
|
-
const viteId =
|
|
334
|
-
if (viteId &&
|
|
344
|
+
const viteId = readViteId(instance);
|
|
345
|
+
if (viteId && cleanup.has(viteId)) {
|
|
335
346
|
logger.debug(`🔃 Replacing "${constructorName(instance)}"`);
|
|
336
347
|
delete registry[key];
|
|
337
348
|
ejected.push(instance);
|
|
@@ -574,8 +585,11 @@ function readPkgJson(dir) {
|
|
|
574
585
|
|
|
575
586
|
//#endregion
|
|
576
587
|
//#region packages/vite/src/moost-vite.ts
|
|
577
|
-
/**
|
|
578
|
-
|
|
588
|
+
/**
|
|
589
|
+
* Classes that land in the DI registry: every `@Injectable()`, `@Controller()`
|
|
590
|
+
* and `@Interceptor()` class (exported or not) gets `@__VITE_ID(<module id>)`,
|
|
591
|
+
* which drives the per-module eject on reload.
|
|
592
|
+
*/ const REG_DI_CLASS = /(^\s*@(Injectable|Controller|Interceptor)\()/gm;
|
|
579
593
|
/**
|
|
580
594
|
* The main Vite plugin for integrating Moost applications.
|
|
581
595
|
*
|
|
@@ -584,7 +598,7 @@ const REG_REPLACE_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/gm;
|
|
|
584
598
|
* - **Dev Mode Middleware**:
|
|
585
599
|
* - Patches `MoostHttp.prototype.listen` to register a custom middleware for serving the app via Vite's dev server instead of binding to a port.
|
|
586
600
|
* - Handles Moost state cleanup and hot module replacement (HMR) during development.
|
|
587
|
-
* - **Class Tracking**: Injects a `__VITE_ID()` decorator into
|
|
601
|
+
* - **Class Tracking**: Injects a `__VITE_ID()` decorator into DI classes to enable tracking and cleanup during hot reloads.
|
|
588
602
|
* - **Externals Support**:
|
|
589
603
|
* - Allows marking Node.js built-in modules and dependencies from `package.json` (optionally excluding workspace dependencies) as external during builds.
|
|
590
604
|
* - Configured via the `externals` option, which helps reduce bundle size and ensures compatibility with runtime environments.
|
|
@@ -634,6 +648,9 @@ function moostVite(options) {
|
|
|
634
648
|
* boot, cleared on eject.
|
|
635
649
|
*/ const moostHttpRef = { current: null };
|
|
636
650
|
const ssrForwarding = options.ssrFetchForwarding !== false;
|
|
651
|
+
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
652
|
+
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
653
|
+
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
637
654
|
/**
|
|
638
655
|
* Boot-identity stamps (dev-only "mongrel state" diagnostic — a stale pipeline
|
|
639
656
|
* presents as security middleware silently switched off). `bootGeneration` is
|
|
@@ -649,7 +666,7 @@ function moostVite(options) {
|
|
|
649
666
|
* several when one entry boots several apps, none for a boot that never calls
|
|
650
667
|
* `init()`. Reset by `beginBoot()`, consumed by `settleBootInit()`.
|
|
651
668
|
*/ let bootInitPromises = [];
|
|
652
|
-
/**
|
|
669
|
+
/** DI cleanup awaiting the next reload (module IDs, or EJECT_ALL) — consumed in runReload; see ejectApp. */ let pendingCleanup = null;
|
|
653
670
|
/** In middleware mode: maps req → next() for the onNoMatch callback */ const pendingNextMap = /* @__PURE__ */ new WeakMap();
|
|
654
671
|
const adapters = [
|
|
655
672
|
createAdapterDetector("http", (MoostHttp, moduleExports) => {
|
|
@@ -705,7 +722,7 @@ function moostVite(options) {
|
|
|
705
722
|
* into the OLD pipeline, producing a mongrel half-old/half-new app. Waves
|
|
706
723
|
* arriving before the lazy reload (editor bulk-save storms) coalesce into one
|
|
707
724
|
* pending set and one cleanup.
|
|
708
|
-
*/ const ejectApp = (
|
|
725
|
+
*/ const ejectApp = (cleanup) => {
|
|
709
726
|
bootGeneration++;
|
|
710
727
|
moostMiddleware = null;
|
|
711
728
|
moostHttpRef.current = null;
|
|
@@ -713,8 +730,7 @@ function moostVite(options) {
|
|
|
713
730
|
localFetchTeardown();
|
|
714
731
|
localFetchTeardown = null;
|
|
715
732
|
}
|
|
716
|
-
|
|
717
|
-
else pendingCleanup = cleanupInstances;
|
|
733
|
+
pendingCleanup = mergeCleanup(pendingCleanup, cleanup);
|
|
718
734
|
reloadRequired = true;
|
|
719
735
|
};
|
|
720
736
|
patchMoostHandlerLogging();
|
|
@@ -725,6 +741,22 @@ function moostVite(options) {
|
|
|
725
741
|
}
|
|
726
742
|
bootInitPromises.push(promise);
|
|
727
743
|
});
|
|
744
|
+
/**
|
|
745
|
+
* Readies the process for the next evaluation of the entry — the first boot,
|
|
746
|
+
* a `server.restart()` and every reload alike (they drifted apart once: a
|
|
747
|
+
* restart skipped the adapter step and its app bound the port for real):
|
|
748
|
+
* 1. DI cleanup, awaited: the ejected instances' `@MoostDispose` hooks must
|
|
749
|
+
* release what they own (connections, consumers, handles) BEFORE the entry
|
|
750
|
+
* re-imports, or the replacement opens a second copy of the resource.
|
|
751
|
+
* 2. Re-establish the adapter capture. The listen() patch lives on whatever
|
|
752
|
+
* `MoostHttp.prototype` was evaluated first; a new runner or a re-evaluated
|
|
753
|
+
* `@moostjs/event-http` hands the entry an unpatched prototype, and
|
|
754
|
+
* `app.listen()` would bind the port for real → EADDRINUSE. `init()`
|
|
755
|
+
* re-resolves the adapter through the runner the entry imports from.
|
|
756
|
+
*/ const prepareBoot = async (cleanup) => {
|
|
757
|
+
await moostRestartCleanup(options.onEject, cleanup);
|
|
758
|
+
for (const adapter of adapters) if (adapter.detected) await adapter.init();
|
|
759
|
+
};
|
|
728
760
|
/** Marks the boot about to run as authoritative for the current generation. */ const beginBoot = () => {
|
|
729
761
|
bootingGeneration = bootGeneration;
|
|
730
762
|
bootInitPromises = [];
|
|
@@ -766,7 +798,11 @@ function moostVite(options) {
|
|
|
766
798
|
"process.env.MOOST_DEFERRED_ENV": "\"production\"",
|
|
767
799
|
__MOOST_ENTRY__: JSON.stringify(`./${entryKey}.js`),
|
|
768
800
|
__MOOST_PREFIX__: JSON.stringify(prefixes ?? null),
|
|
769
|
-
__MOOST_SSR_FORWARDING__: JSON.stringify(ssrForwarding)
|
|
801
|
+
__MOOST_SSR_FORWARDING__: JSON.stringify(ssrForwarding),
|
|
802
|
+
__MOOST_SSR_ENTRY__: "undefined",
|
|
803
|
+
__MOOST_SSR_OUTLET__: JSON.stringify(ssrOutlet),
|
|
804
|
+
__MOOST_SSR_STATE__: JSON.stringify(ssrState),
|
|
805
|
+
__MOOST_SSR_HEAD__: JSON.stringify(ssrHead)
|
|
770
806
|
};
|
|
771
807
|
const ssrInput = {
|
|
772
808
|
server: options.serverEntry || generatedServerEntry(cfg.root),
|
|
@@ -776,9 +812,6 @@ function moostVite(options) {
|
|
|
776
812
|
const ssrBasename = entryBasename(options.ssrEntry);
|
|
777
813
|
ssrInput[`ssr/${ssrBasename.replace(/\.js$/, "")}`] = options.ssrEntry;
|
|
778
814
|
serverDefines.__MOOST_SSR_ENTRY__ = JSON.stringify(`./ssr/${ssrBasename}`);
|
|
779
|
-
serverDefines.__MOOST_SSR_OUTLET__ = JSON.stringify(options.ssrOutlet || DEFAULT_SSR_OUTLET);
|
|
780
|
-
serverDefines.__MOOST_SSR_STATE__ = JSON.stringify(options.ssrState || DEFAULT_SSR_STATE);
|
|
781
|
-
serverDefines.__MOOST_SSR_HEAD__ = JSON.stringify(options.ssrHead || DEFAULT_SSR_HEAD);
|
|
782
815
|
}
|
|
783
816
|
const outDir = cfg.build?.outDir || "dist";
|
|
784
817
|
const isBuild = env.command === "build";
|
|
@@ -882,9 +915,9 @@ function moostVite(options) {
|
|
|
882
915
|
async transform(code, id) {
|
|
883
916
|
if (!id.endsWith(".ts")) return null;
|
|
884
917
|
for (const adapter of adapters) if (!adapter.detected && adapter.regex.test(code)) await adapter.init();
|
|
885
|
-
if (
|
|
918
|
+
if (code.search(REG_DI_CLASS) !== -1) {
|
|
886
919
|
const s = new MagicString(code);
|
|
887
|
-
s.replace(
|
|
920
|
+
s.replace(REG_DI_CLASS, "\n@__VITE_ID(import.meta.filename)\n$1");
|
|
888
921
|
s.prepend(`import { __VITE_ID } from 'virtual:vite-id'\n\n`);
|
|
889
922
|
return {
|
|
890
923
|
code: s.toString(),
|
|
@@ -902,7 +935,7 @@ function moostVite(options) {
|
|
|
902
935
|
import { getMoostMate } from "moost";
|
|
903
936
|
const mate = getMoostMate();
|
|
904
937
|
export function __VITE_ID(id) {
|
|
905
|
-
return mate.decorate(
|
|
938
|
+
return mate.decorate(${JSON.stringify(VITE_ID_KEY)}, id)
|
|
906
939
|
}
|
|
907
940
|
`,
|
|
908
941
|
map: null
|
|
@@ -924,10 +957,9 @@ function moostVite(options) {
|
|
|
924
957
|
return (async () => {
|
|
925
958
|
try {
|
|
926
959
|
beginBoot();
|
|
927
|
-
const
|
|
960
|
+
const cleanup = pendingCleanup ?? EJECT_ALL;
|
|
928
961
|
pendingCleanup = null;
|
|
929
|
-
await
|
|
930
|
-
for (const adapter of adapters) if (adapter.detected) await adapter.init();
|
|
962
|
+
await prepareBoot(cleanup);
|
|
931
963
|
const entryModule = await getEntryModule(server.environments.ssr.moduleGraph);
|
|
932
964
|
if (entryModule?.transformResult) server.environments.ssr.moduleGraph.invalidateModule(entryModule);
|
|
933
965
|
await ssrImport(options.entry);
|
|
@@ -948,7 +980,7 @@ function moostVite(options) {
|
|
|
948
980
|
}
|
|
949
981
|
};
|
|
950
982
|
for (const adapter of adapters) adapter.ssrLoadModule = ssrImport;
|
|
951
|
-
await
|
|
983
|
+
await prepareBoot(EJECT_ALL);
|
|
952
984
|
await ssrImport(options.entry);
|
|
953
985
|
await settleBootInit();
|
|
954
986
|
server.middlewares.use(async (req, res, next) => {
|
|
@@ -979,17 +1011,18 @@ function moostVite(options) {
|
|
|
979
1011
|
const cleanupInstances = /* @__PURE__ */ new Set();
|
|
980
1012
|
for (const importers of importerSets) for (const impModule of importers) if (impModule.id) cleanupInstances.add(impModule.id);
|
|
981
1013
|
for (const mod of modules) moduleGraph.invalidateModule(mod);
|
|
982
|
-
if (entryModule)
|
|
983
|
-
|
|
984
|
-
|
|
1014
|
+
if (entryModule) {
|
|
1015
|
+
moduleGraph.invalidateModule(entryModule);
|
|
1016
|
+
ejectApp(cleanupInstances);
|
|
1017
|
+
} else {
|
|
1018
|
+
moduleGraph.invalidateAll();
|
|
1019
|
+
ejectApp(EJECT_ALL);
|
|
1020
|
+
}
|
|
985
1021
|
return [];
|
|
986
1022
|
}
|
|
987
1023
|
}, options.middleware && options.ssrEntry ? {
|
|
988
1024
|
name: `${PLUGIN_NAME}:ssr-fallback`,
|
|
989
1025
|
async configureServer(server) {
|
|
990
|
-
const ssrOutlet = options.ssrOutlet || DEFAULT_SSR_OUTLET;
|
|
991
|
-
const ssrState = options.ssrState || DEFAULT_SSR_STATE;
|
|
992
|
-
const ssrHead = options.ssrHead || DEFAULT_SSR_HEAD;
|
|
993
1026
|
const fs = await import("node:fs/promises");
|
|
994
1027
|
return () => {
|
|
995
1028
|
server.middlewares.use(async (req, res, next) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moostjs/vite",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.41",
|
|
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.41",
|
|
62
|
+
"moost": "^0.6.41"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"sirv": {
|