arcway 0.4.10 → 0.4.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcway",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "description": "A convention-based framework for building modular monoliths with strict domain boundaries.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -11,14 +11,65 @@ const DEFAULTS = {
11
11
  },
12
12
  };
13
13
 
14
+ const HMR_KEYS = new Set(['protocol', 'host', 'clientPort']);
15
+
16
+ function resolveHmr(rawHmr) {
17
+ if (rawHmr == null) return undefined;
18
+ if (typeof rawHmr !== 'object' || Array.isArray(rawHmr)) {
19
+ throw new TypeError('Invalid config: pages.vite.hmr must be an object');
20
+ }
21
+
22
+ for (const key of Object.keys(rawHmr)) {
23
+ if (!HMR_KEYS.has(key)) {
24
+ throw new TypeError(`Invalid config: pages.vite.hmr.${key} is not supported`);
25
+ }
26
+ }
27
+
28
+ const hmr = {};
29
+ if (rawHmr.protocol != null) {
30
+ if (!['ws', 'wss'].includes(rawHmr.protocol)) {
31
+ throw new TypeError('Invalid config: pages.vite.hmr.protocol must be "ws" or "wss"');
32
+ }
33
+ hmr.protocol = rawHmr.protocol;
34
+ }
35
+ if (rawHmr.host != null) {
36
+ if (
37
+ typeof rawHmr.host !== 'string' ||
38
+ rawHmr.host.length === 0 ||
39
+ rawHmr.host.trim() !== rawHmr.host ||
40
+ /[/?#\s]/.test(rawHmr.host)
41
+ ) {
42
+ throw new TypeError('Invalid config: pages.vite.hmr.host must be a hostname');
43
+ }
44
+ hmr.host = rawHmr.host;
45
+ }
46
+ if (rawHmr.clientPort != null) {
47
+ if (
48
+ !Number.isInteger(rawHmr.clientPort) ||
49
+ rawHmr.clientPort < 1 ||
50
+ rawHmr.clientPort > 65535
51
+ ) {
52
+ throw new TypeError(
53
+ 'Invalid config: pages.vite.hmr.clientPort must be an integer from 1 to 65535',
54
+ );
55
+ }
56
+ hmr.clientPort = rawHmr.clientPort;
57
+ }
58
+
59
+ return Object.keys(hmr).length > 0 ? hmr : undefined;
60
+ }
61
+
14
62
  function resolve(config, { rootDir } = {}) {
15
63
  const rawPages = config.pages ?? {};
64
+ const { hmr: rawHmr, ...rawVite } = rawPages.vite ?? {};
65
+ const hmr = resolveHmr(rawHmr);
16
66
  const pages = {
17
67
  ...DEFAULTS,
18
68
  ...rawPages,
19
69
  vite: {
20
70
  ...DEFAULTS.vite,
21
- ...(rawPages.vite ?? {}),
71
+ ...rawVite,
72
+ ...(hmr ? { hmr } : {}),
22
73
  },
23
74
  };
24
75
  if (pages.dir && !path.isAbsolute(pages.dir)) {
@@ -33,4 +84,5 @@ function resolve(config, { rootDir } = {}) {
33
84
  return { ...config, pages };
34
85
  }
35
86
 
87
+ export { resolveHmr };
36
88
  export default resolve;
@@ -5,6 +5,7 @@ import reactPlugin from '@vitejs/plugin-react';
5
5
  import tailwindcss from '@tailwindcss/vite';
6
6
  import { createServer as createViteServer } from 'vite';
7
7
  import { patternToFileName } from './build-server.js';
8
+ import { closeServer, createHttpServer, listen } from '../server.js';
8
9
 
9
10
  function toPosixPath(value) {
10
11
  return value.replace(/\\/g, '/');
@@ -203,38 +204,60 @@ function resolveAppAliases(rootDir) {
203
204
  return aliases;
204
205
  }
205
206
 
206
- async function createViteDevRouter({ rootDir, log }) {
207
+ function getViteServerOptions(config, hmrServer) {
208
+ const hmr = config?.pages?.vite?.hmr;
209
+ return {
210
+ middlewareMode: true,
211
+ ...(hmr ? { hmr: { ...hmr, ...(hmrServer ? { server: hmrServer } : {}) } } : {}),
212
+ };
213
+ }
214
+
215
+ async function createViteHmrServer(log, { host = '0.0.0.0', port = 24678 } = {}) {
216
+ const server = createHttpServer((_req, res) => {
217
+ res.writeHead(426, { 'Content-Type': 'text/plain' });
218
+ res.end('Upgrade Required');
219
+ }, log);
220
+ await listen(server, port, host);
221
+ return server;
222
+ }
223
+
224
+ async function createViteDevRouter({ rootDir, log, config }) {
207
225
  const appAliases = resolveAppAliases(rootDir);
208
- const vite = await createViteServer({
209
- root: rootDir,
210
- appType: 'custom',
211
- server: {
212
- middlewareMode: true,
213
- },
214
- resolve: {
215
- alias: appAliases,
216
- dedupe: ['react', 'react-dom', 'swr'],
217
- },
218
- css: {
219
- devSourcemap: true,
220
- },
221
- esbuild: {
222
- keepNames: true,
223
- },
224
- optimizeDeps: {
225
- include: [
226
- 'react',
227
- 'react-dom',
228
- 'react/jsx-runtime',
229
- 'react/jsx-dev-runtime',
230
- 'swr',
231
- 'use-sync-external-store/shim',
232
- '@radix-ui/react-use-is-hydrated',
233
- ],
234
- },
235
- plugins: [reactPlugin(), tailwindcss()],
236
- clearScreen: false,
237
- });
226
+ const hmrServer = config?.pages?.vite?.hmr ? await createViteHmrServer(log) : null;
227
+ let vite;
228
+ try {
229
+ vite = await createViteServer({
230
+ root: rootDir,
231
+ appType: 'custom',
232
+ server: getViteServerOptions(config, hmrServer),
233
+ resolve: {
234
+ alias: appAliases,
235
+ dedupe: ['react', 'react-dom', 'swr'],
236
+ },
237
+ css: {
238
+ devSourcemap: true,
239
+ },
240
+ esbuild: {
241
+ keepNames: true,
242
+ },
243
+ optimizeDeps: {
244
+ include: [
245
+ 'react',
246
+ 'react-dom',
247
+ 'react/jsx-runtime',
248
+ 'react/jsx-dev-runtime',
249
+ 'swr',
250
+ 'use-sync-external-store/shim',
251
+ '@radix-ui/react-use-is-hydrated',
252
+ ],
253
+ },
254
+ plugins: [reactPlugin(), tailwindcss()],
255
+ clearScreen: false,
256
+ });
257
+ } catch (error) {
258
+ if (hmrServer) await closeServer(hmrServer);
259
+ throw error;
260
+ }
238
261
 
239
262
  const internalPrefixes = ['/@vite/', '/@id/', '/@react-refresh', '/@fs/', '/node_modules/.vite/'];
240
263
  const sourceExt = /\.(?:[cm]?[jt]sx?|css|pcss|postcss|json|svg)$/i;
@@ -264,7 +287,11 @@ async function createViteDevRouter({ rootDir, log }) {
264
287
  vite,
265
288
  handle,
266
289
  async close() {
267
- await vite.close();
290
+ try {
291
+ await vite.close();
292
+ } finally {
293
+ if (hmrServer) await closeServer(hmrServer);
294
+ }
268
295
  log?.info?.('Vite dev server closed');
269
296
  },
270
297
  };
@@ -274,6 +301,8 @@ export {
274
301
  buildViteClientManifestJson,
275
302
  buildViteRoute,
276
303
  createViteDevRouter,
304
+ createViteHmrServer,
305
+ getViteServerOptions,
277
306
  getViteEntryPath,
278
307
  getViteFontsPath,
279
308
  syncViteHydrationEntries,