@moostjs/vite 0.4.23

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 ADDED
@@ -0,0 +1 @@
1
+ # @moostjs/vite
package/dist/index.cjs ADDED
@@ -0,0 +1,252 @@
1
+ 'use strict';
2
+
3
+ var moost = require('moost');
4
+
5
+ function createAdapterDetector(adapter, onInit) {
6
+ return {
7
+ detected: false,
8
+ regex: new RegExp(`from\\s+["'](@moostjs\\/event-${adapter})["']`),
9
+ constructor: null,
10
+ async init() {
11
+ this.detected = true;
12
+ const module = await import(`@moostjs/event-${adapter}`);
13
+ this.constructor = module[`Moost${adapter.charAt(0).toUpperCase() + adapter.slice(1)}`];
14
+ if (onInit) {
15
+ onInit(this.constructor);
16
+ }
17
+ },
18
+ compare(c) {
19
+ if (this.detected && this.constructor) {
20
+ return (this.constructor === c ||
21
+ c instanceof this.constructor ||
22
+ c.prototype instanceof this.constructor);
23
+ }
24
+ return false;
25
+ },
26
+ };
27
+ }
28
+
29
+ const PLUGIN_NAME = 'moost-vite-dev';
30
+ function gatherAllImporters(moduleNode, visited = new Set()) {
31
+ if (!moduleNode) {
32
+ return visited;
33
+ }
34
+ if (visited.has(moduleNode)) {
35
+ return visited;
36
+ }
37
+ visited.add(moduleNode);
38
+ if (moduleNode.importers) {
39
+ for (const importer of moduleNode.importers) {
40
+ gatherAllImporters(importer, visited);
41
+ }
42
+ }
43
+ return visited;
44
+ }
45
+ const logger = new moost.EventLogger('', { level: 99 }).createTopic(PLUGIN_NAME);
46
+ function getLogger() {
47
+ return logger;
48
+ }
49
+
50
+ function moostRestartCleanup(adapters, cleanupInstances) {
51
+ const logger = getLogger();
52
+ const infact = moost.getMoostInfact();
53
+ const { registry } = infact;
54
+ infact._cleanup();
55
+ const mate = moost.getMoostMate();
56
+ if (cleanupInstances) {
57
+ for (const key of Object.getOwnPropertySymbols(registry)) {
58
+ const instance = registry[key];
59
+ const viteId = mate.read(instance)?.__vite_id;
60
+ if (viteId && cleanupInstances.has(viteId)) {
61
+ logger.debug(`🔃 Replacing "${constructorName(instance)}"`);
62
+ delete registry[key];
63
+ }
64
+ }
65
+ for (const key of Object.getOwnPropertySymbols(registry)) {
66
+ const instance = registry[key];
67
+ scanParams(instance, (type) => {
68
+ if (type === moost.Moost || type instanceof moost.Moost || type.prototype instanceof moost.Moost) {
69
+ delete registry[key];
70
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on re-instantiated "Moost")`);
71
+ return true;
72
+ }
73
+ for (const adapter of adapters) {
74
+ if (adapter.compare(type)) {
75
+ delete registry[key];
76
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on re-instantiated "${adapter.constructor.name}")`);
77
+ return true;
78
+ }
79
+ }
80
+ });
81
+ }
82
+ clearDependantRegistry(registry);
83
+ infact.registry = registry;
84
+ }
85
+ moost.getMoostMate()._cleanup();
86
+ moost.getGlobalWooks(undefined, undefined, 'cleanup');
87
+ }
88
+ function clearDependantRegistry(registry) {
89
+ const logger = getLogger();
90
+ const objSet = new Set();
91
+ let somethingIsDeleted = true;
92
+ while (somethingIsDeleted) {
93
+ somethingIsDeleted = false;
94
+ for (const key of Object.getOwnPropertySymbols(registry)) {
95
+ const instance = registry[key];
96
+ objSet.add(Object.getPrototypeOf(instance).constructor);
97
+ }
98
+ for (const key of Object.getOwnPropertySymbols(registry)) {
99
+ const instance = registry[key];
100
+ scanParams(instance, (type) => {
101
+ if (!objSet.has(type)) {
102
+ delete registry[key];
103
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on "${type.name}" which is not in registry)`);
104
+ somethingIsDeleted = true;
105
+ return true;
106
+ }
107
+ });
108
+ }
109
+ }
110
+ }
111
+ function scanParams(instance, cb) {
112
+ const mate = moost.getMoostMate();
113
+ const params = mate.read(instance)?.params;
114
+ if (params?.length) {
115
+ for (const param of params) {
116
+ if (param.type === undefined ||
117
+ [Array, String, Number, Boolean].includes(param.type)) {
118
+ continue;
119
+ }
120
+ if (cb(param.type)) {
121
+ break;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ function constructorName(i) {
127
+ return Object.getPrototypeOf(i).constructor.name;
128
+ }
129
+
130
+ const REG_HAS_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/m;
131
+ const REG_REPLACE_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/gm;
132
+ function moostViteDev(options) {
133
+ const entry = options.entry;
134
+ let moostMiddleware = null;
135
+ const adapters = [
136
+ createAdapterDetector('http', MoostHttp => {
137
+ MoostHttp.prototype.listen = function (...args) {
138
+ moostMiddleware = this.getServerCb();
139
+ setTimeout(() => {
140
+ args.filter(a => typeof a === 'function').forEach(a => a());
141
+ }, 1);
142
+ return Promise.resolve();
143
+ };
144
+ }),
145
+ createAdapterDetector('cli'),
146
+ createAdapterDetector('wf'),
147
+ ];
148
+ const logger = getLogger();
149
+ let reloadRequired = false;
150
+ return {
151
+ name: PLUGIN_NAME,
152
+ apply: 'serve',
153
+ enforce: 'pre',
154
+ config(cfg) {
155
+ return {
156
+ server: {
157
+ port: cfg.server?.port || options.port || 3000,
158
+ host: cfg.server?.host || options.host,
159
+ },
160
+ optimizeDeps: {
161
+ noDiscovery: cfg.optimizeDeps?.noDiscovery === undefined ? true : cfg.optimizeDeps.noDiscovery,
162
+ exclude: cfg.optimizeDeps?.exclude || ['@swc/core'],
163
+ },
164
+ build: {
165
+ target: cfg.build?.target || 'node20',
166
+ outDir: cfg.build?.outDir || options.outDir || 'dist',
167
+ ssr: cfg.build?.ssr || options.entry,
168
+ minify: cfg.build?.minify || false,
169
+ rollupOptions: {
170
+ input: cfg.build?.rollupOptions?.input || options.entry,
171
+ output: cfg.build?.rollupOptions?.output || {
172
+ format: options.format,
173
+ sourcemap: !!(options.sourcemap ?? true),
174
+ },
175
+ },
176
+ },
177
+ };
178
+ },
179
+ async transform(code, id) {
180
+ if (!id.endsWith('.ts')) {
181
+ return code;
182
+ }
183
+ for (const adapter of adapters) {
184
+ if (!adapter.detected && adapter.regex.test(code)) {
185
+ await adapter.init();
186
+ }
187
+ }
188
+ if (REG_HAS_EXPORT_CLASS.test(code)) {
189
+ code = code.replace(REG_REPLACE_EXPORT_CLASS, '\n@__VITE_ID(import.meta.filename)\n$1');
190
+ code = `import { __VITE_ID } from 'virtual:vite-id'\n\n${code}`;
191
+ }
192
+ return code;
193
+ },
194
+ resolveId(id) {
195
+ if (id === 'virtual:vite-id') {
196
+ return '\0virtual:vite-id';
197
+ }
198
+ },
199
+ load(id) {
200
+ if (id === '\0virtual:vite-id') {
201
+ return `
202
+ import { getMoostMate } from "moost";
203
+ const mate = getMoostMate();
204
+ export function __VITE_ID(id) {
205
+ return mate.decorate("__vite_id", id)
206
+ }
207
+ `;
208
+ }
209
+ },
210
+ async configureServer(server) {
211
+ moostRestartCleanup(adapters);
212
+ await server.ssrLoadModule(entry);
213
+ server.middlewares.use(async (req, res, next) => {
214
+ if (reloadRequired) {
215
+ console.clear();
216
+ reloadRequired = false;
217
+ logger.debug('🚀 Reloading Moost App...');
218
+ await server.ssrLoadModule(entry);
219
+ await new Promise(resolve => setTimeout(resolve, 1));
220
+ }
221
+ if (moostMiddleware) {
222
+ return moostMiddleware(req, res);
223
+ }
224
+ next();
225
+ });
226
+ },
227
+ hotUpdate({ file }) {
228
+ if (file.endsWith('.ts')) {
229
+ const modules = this.environment.moduleGraph.getModulesByFile(file);
230
+ if (modules) {
231
+ logger.debug(`🔃 Hot update: ${file}`);
232
+ const cleanupInstances = new Set();
233
+ for (const mod of modules) {
234
+ const allImporters = gatherAllImporters(mod);
235
+ for (const impModule of allImporters) {
236
+ if (impModule.id) {
237
+ cleanupInstances.add(impModule.id);
238
+ }
239
+ }
240
+ this.environment.moduleGraph.invalidateModule(mod);
241
+ }
242
+ moostMiddleware = null;
243
+ moostRestartCleanup(adapters, cleanupInstances);
244
+ reloadRequired = true;
245
+ }
246
+ return [];
247
+ }
248
+ },
249
+ };
250
+ }
251
+
252
+ exports.moostViteDev = moostViteDev;
@@ -0,0 +1,20 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ interface TMoostViteDevOptions {
4
+ entry: string;
5
+ port?: number;
6
+ host?: string;
7
+ outDir?: string;
8
+ format?: 'cjs' | 'esm';
9
+ sourcemap?: boolean;
10
+ }
11
+ /**
12
+ * The main Vite plugin that:
13
+ * - Detects when moost adapter usage (http, cli, wf).
14
+ * - Patches `MoostHttp.prototype.listen` in dev mode to register a custom middleware instead of listening on a port.
15
+ * - Injects a `__VITE_ID()` decorator into exported classes to track them for hot reload cleanup.
16
+ * - Cleans up internal Moost state upon hot updates, then reloads the SSR entry.
17
+ */
18
+ declare function moostViteDev(options: TMoostViteDevOptions): Plugin;
19
+
20
+ export { moostViteDev };
package/dist/index.mjs ADDED
@@ -0,0 +1,250 @@
1
+ import { EventLogger, getMoostInfact, getMoostMate, getGlobalWooks, Moost } from 'moost';
2
+
3
+ function createAdapterDetector(adapter, onInit) {
4
+ return {
5
+ detected: false,
6
+ regex: new RegExp(`from\\s+["'](@moostjs\\/event-${adapter})["']`),
7
+ constructor: null,
8
+ async init() {
9
+ this.detected = true;
10
+ const module = await import(`@moostjs/event-${adapter}`);
11
+ this.constructor = module[`Moost${adapter.charAt(0).toUpperCase() + adapter.slice(1)}`];
12
+ if (onInit) {
13
+ onInit(this.constructor);
14
+ }
15
+ },
16
+ compare(c) {
17
+ if (this.detected && this.constructor) {
18
+ return (this.constructor === c ||
19
+ c instanceof this.constructor ||
20
+ c.prototype instanceof this.constructor);
21
+ }
22
+ return false;
23
+ },
24
+ };
25
+ }
26
+
27
+ const PLUGIN_NAME = 'moost-vite-dev';
28
+ function gatherAllImporters(moduleNode, visited = new Set()) {
29
+ if (!moduleNode) {
30
+ return visited;
31
+ }
32
+ if (visited.has(moduleNode)) {
33
+ return visited;
34
+ }
35
+ visited.add(moduleNode);
36
+ if (moduleNode.importers) {
37
+ for (const importer of moduleNode.importers) {
38
+ gatherAllImporters(importer, visited);
39
+ }
40
+ }
41
+ return visited;
42
+ }
43
+ const logger = new EventLogger('', { level: 99 }).createTopic(PLUGIN_NAME);
44
+ function getLogger() {
45
+ return logger;
46
+ }
47
+
48
+ function moostRestartCleanup(adapters, cleanupInstances) {
49
+ const logger = getLogger();
50
+ const infact = getMoostInfact();
51
+ const { registry } = infact;
52
+ infact._cleanup();
53
+ const mate = getMoostMate();
54
+ if (cleanupInstances) {
55
+ for (const key of Object.getOwnPropertySymbols(registry)) {
56
+ const instance = registry[key];
57
+ const viteId = mate.read(instance)?.__vite_id;
58
+ if (viteId && cleanupInstances.has(viteId)) {
59
+ logger.debug(`🔃 Replacing "${constructorName(instance)}"`);
60
+ delete registry[key];
61
+ }
62
+ }
63
+ for (const key of Object.getOwnPropertySymbols(registry)) {
64
+ const instance = registry[key];
65
+ scanParams(instance, (type) => {
66
+ if (type === Moost || type instanceof Moost || type.prototype instanceof Moost) {
67
+ delete registry[key];
68
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on re-instantiated "Moost")`);
69
+ return true;
70
+ }
71
+ for (const adapter of adapters) {
72
+ if (adapter.compare(type)) {
73
+ delete registry[key];
74
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on re-instantiated "${adapter.constructor.name}")`);
75
+ return true;
76
+ }
77
+ }
78
+ });
79
+ }
80
+ clearDependantRegistry(registry);
81
+ infact.registry = registry;
82
+ }
83
+ getMoostMate()._cleanup();
84
+ getGlobalWooks(undefined, undefined, 'cleanup');
85
+ }
86
+ function clearDependantRegistry(registry) {
87
+ const logger = getLogger();
88
+ const objSet = new Set();
89
+ let somethingIsDeleted = true;
90
+ while (somethingIsDeleted) {
91
+ somethingIsDeleted = false;
92
+ for (const key of Object.getOwnPropertySymbols(registry)) {
93
+ const instance = registry[key];
94
+ objSet.add(Object.getPrototypeOf(instance).constructor);
95
+ }
96
+ for (const key of Object.getOwnPropertySymbols(registry)) {
97
+ const instance = registry[key];
98
+ scanParams(instance, (type) => {
99
+ if (!objSet.has(type)) {
100
+ delete registry[key];
101
+ logger.debug(`✖️ Ejecting "${constructorName(instance)}" (depends on "${type.name}" which is not in registry)`);
102
+ somethingIsDeleted = true;
103
+ return true;
104
+ }
105
+ });
106
+ }
107
+ }
108
+ }
109
+ function scanParams(instance, cb) {
110
+ const mate = getMoostMate();
111
+ const params = mate.read(instance)?.params;
112
+ if (params?.length) {
113
+ for (const param of params) {
114
+ if (param.type === undefined ||
115
+ [Array, String, Number, Boolean].includes(param.type)) {
116
+ continue;
117
+ }
118
+ if (cb(param.type)) {
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ function constructorName(i) {
125
+ return Object.getPrototypeOf(i).constructor.name;
126
+ }
127
+
128
+ const REG_HAS_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/m;
129
+ const REG_REPLACE_EXPORT_CLASS = /(^\s*@(Injectable|Controller)\()/gm;
130
+ function moostViteDev(options) {
131
+ const entry = options.entry;
132
+ let moostMiddleware = null;
133
+ const adapters = [
134
+ createAdapterDetector('http', MoostHttp => {
135
+ MoostHttp.prototype.listen = function (...args) {
136
+ moostMiddleware = this.getServerCb();
137
+ setTimeout(() => {
138
+ args.filter(a => typeof a === 'function').forEach(a => a());
139
+ }, 1);
140
+ return Promise.resolve();
141
+ };
142
+ }),
143
+ createAdapterDetector('cli'),
144
+ createAdapterDetector('wf'),
145
+ ];
146
+ const logger = getLogger();
147
+ let reloadRequired = false;
148
+ return {
149
+ name: PLUGIN_NAME,
150
+ apply: 'serve',
151
+ enforce: 'pre',
152
+ config(cfg) {
153
+ return {
154
+ server: {
155
+ port: cfg.server?.port || options.port || 3000,
156
+ host: cfg.server?.host || options.host,
157
+ },
158
+ optimizeDeps: {
159
+ noDiscovery: cfg.optimizeDeps?.noDiscovery === undefined ? true : cfg.optimizeDeps.noDiscovery,
160
+ exclude: cfg.optimizeDeps?.exclude || ['@swc/core'],
161
+ },
162
+ build: {
163
+ target: cfg.build?.target || 'node20',
164
+ outDir: cfg.build?.outDir || options.outDir || 'dist',
165
+ ssr: cfg.build?.ssr || options.entry,
166
+ minify: cfg.build?.minify || false,
167
+ rollupOptions: {
168
+ input: cfg.build?.rollupOptions?.input || options.entry,
169
+ output: cfg.build?.rollupOptions?.output || {
170
+ format: options.format,
171
+ sourcemap: !!(options.sourcemap ?? true),
172
+ },
173
+ },
174
+ },
175
+ };
176
+ },
177
+ async transform(code, id) {
178
+ if (!id.endsWith('.ts')) {
179
+ return code;
180
+ }
181
+ for (const adapter of adapters) {
182
+ if (!adapter.detected && adapter.regex.test(code)) {
183
+ await adapter.init();
184
+ }
185
+ }
186
+ if (REG_HAS_EXPORT_CLASS.test(code)) {
187
+ code = code.replace(REG_REPLACE_EXPORT_CLASS, '\n@__VITE_ID(import.meta.filename)\n$1');
188
+ code = `import { __VITE_ID } from 'virtual:vite-id'\n\n${code}`;
189
+ }
190
+ return code;
191
+ },
192
+ resolveId(id) {
193
+ if (id === 'virtual:vite-id') {
194
+ return '\0virtual:vite-id';
195
+ }
196
+ },
197
+ load(id) {
198
+ if (id === '\0virtual:vite-id') {
199
+ return `
200
+ import { getMoostMate } from "moost";
201
+ const mate = getMoostMate();
202
+ export function __VITE_ID(id) {
203
+ return mate.decorate("__vite_id", id)
204
+ }
205
+ `;
206
+ }
207
+ },
208
+ async configureServer(server) {
209
+ moostRestartCleanup(adapters);
210
+ await server.ssrLoadModule(entry);
211
+ server.middlewares.use(async (req, res, next) => {
212
+ if (reloadRequired) {
213
+ console.clear();
214
+ reloadRequired = false;
215
+ logger.debug('🚀 Reloading Moost App...');
216
+ await server.ssrLoadModule(entry);
217
+ await new Promise(resolve => setTimeout(resolve, 1));
218
+ }
219
+ if (moostMiddleware) {
220
+ return moostMiddleware(req, res);
221
+ }
222
+ next();
223
+ });
224
+ },
225
+ hotUpdate({ file }) {
226
+ if (file.endsWith('.ts')) {
227
+ const modules = this.environment.moduleGraph.getModulesByFile(file);
228
+ if (modules) {
229
+ logger.debug(`🔃 Hot update: ${file}`);
230
+ const cleanupInstances = new Set();
231
+ for (const mod of modules) {
232
+ const allImporters = gatherAllImporters(mod);
233
+ for (const impModule of allImporters) {
234
+ if (impModule.id) {
235
+ cleanupInstances.add(impModule.id);
236
+ }
237
+ }
238
+ this.environment.moduleGraph.invalidateModule(mod);
239
+ }
240
+ moostMiddleware = null;
241
+ moostRestartCleanup(adapters, cleanupInstances);
242
+ reloadRequired = true;
243
+ }
244
+ return [];
245
+ }
246
+ },
247
+ };
248
+ }
249
+
250
+ export { moostViteDev };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@moostjs/vite",
3
+ "version": "0.4.23",
4
+ "description": "Vite Dev plugin for moostjs",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ "./package.json": "./package.json",
11
+ ".": {
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/moostjs/moostjs.git",
23
+ "directory": "packages/vite"
24
+ },
25
+ "keywords": [
26
+ "moost",
27
+ "moostjs",
28
+ "composables",
29
+ "framework",
30
+ "wooksjs",
31
+ "prostojs",
32
+ "vite"
33
+ ],
34
+ "author": "Artem Maltsev",
35
+ "license": "MIT",
36
+ "bugs": {
37
+ "url": "https://github.com/moostjs/moostjs/issues"
38
+ },
39
+ "homepage": "https://github.com/moostjs/moostjs/tree/main/packages/vite#readme",
40
+ "peerDependencies": {
41
+ "moost": "0.4.23",
42
+ "@moostjs/event-http": "0.4.23",
43
+ "vite": "6.x"
44
+ }
45
+ }