@remix-run/node-hmr 0.1.0 → 0.2.0

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 CHANGED
@@ -120,7 +120,6 @@ let isDevelopment = process.env.NODE_ENV === 'development'
120
120
 
121
121
  let assetServer = createAssetServer({
122
122
  basePath: '/assets',
123
- fileMap: { '/app/*path': 'app/*path' },
124
123
  allowFiles: ['app/routes.ts', 'app/**/public/**'],
125
124
  denyFiles: ['app/**/*.test.*'],
126
125
  hmr:
@@ -1,38 +1,26 @@
1
1
  export declare const defaultBrowserHmrPathname = "/hmr";
2
+ /** Value that can be serialized as JSON for delivery to browser HMR clients. */
3
+ export type BrowserHmrData = null | boolean | number | string | BrowserHmrData[] | {
4
+ [key: string]: BrowserHmrData;
5
+ };
2
6
  /**
3
7
  * Event payload sent to browser HMR clients.
4
8
  */
5
9
  export interface HmrEventPayload {
6
10
  /** Event type string consumed by browser HMR clients. */
7
11
  type: string;
8
- [key: string]: unknown;
12
+ [key: string]: BrowserHmrData;
9
13
  }
10
- /** JavaScript or CSS module update sent to a browser HMR client. */
11
- export type HmrBrowserUpdate = {
12
- /** Importing module whose dependency-accept handler accepts this update. */
13
- acceptedPath?: string;
14
- /** Public URL of the changed JavaScript module. */
15
- path: string;
16
- /** Identifies a JavaScript module update. */
17
- type: 'js';
18
- } | {
19
- /** Public URL of the changed stylesheet. */
20
- path: string;
21
- /** Identifies a stylesheet update. */
22
- type: 'css';
23
- };
24
14
  /**
25
15
  * Browser HMR event emitted to connected clients.
26
16
  */
27
17
  export type BrowserHmrEvent = {
18
+ /** Consumer-owned data keyed by a stable, versioned namespace. */
19
+ data: Record<string, BrowserHmrData>;
28
20
  /** Absolute source file paths that triggered this update. */
29
21
  files?: string[];
30
- /** Update timestamp used to bust module and stylesheet caches. */
31
- timestamp: number;
32
22
  /** Browser update event. */
33
23
  type: 'update';
34
- /** JavaScript and CSS updates for the browser to apply. */
35
- updates: HmrBrowserUpdate[];
36
24
  } | {
37
25
  /** Absolute source file paths that could not be handled in place. */
38
26
  files?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"browser-events.d.ts","sourceRoot":"","sources":["../../src/lib/browser-events.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,SAAS,CAAA;AAE/C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GACxB;IACE,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,6CAA6C;IAC7C,IAAI,EAAE,IAAI,CAAA;CACX,GACD;IACE,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,sCAAsC;IACtC,IAAI,EAAE,KAAK,CAAA;CACZ,CAAA;AAEL;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,IAAI,EAAE,QAAQ,CAAA;IACd,2DAA2D;IAC3D,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAC5B,GACD;IACE,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,4BAA4B;IAC5B,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAEL;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,2DAA2D;IAC3D,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAClC,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACvC,MAAM,EAAE,SAAS,mBAAmB,EAAE,KACnC,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAA;AAExC;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IACtB,qEAAqE;IACrE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oGAAoG;IACpG,KAAK,IAAI,IAAI,CAAA;IACb;;;;;;;;OAQG;IACH,YAAY,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,IAAI,CAAA;IAC7D;;;;;;;OAOG;IACH,kBAAkB,CAAC,KAAK,EAAE,0BAA0B,GAAG,IAAI,CAAA;CAC5D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAOlE"}
1
+ {"version":3,"file":"browser-events.d.ts","sourceRoot":"","sources":["../../src/lib/browser-events.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,SAAS,CAAA;AAE/C,gFAAgF;AAChF,MAAM,MAAM,cAAc,GACtB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,cAAc,EAAE,GAChB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAA;CAAE,CAAA;AAErC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACpC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,4BAA4B;IAC5B,IAAI,EAAE,QAAQ,CAAA;CACf,GACD;IACE,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,4BAA4B;IAC5B,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAEL;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,2DAA2D;IAC3D,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAClC,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACvC,MAAM,EAAE,SAAS,mBAAmB,EAAE,KACnC,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAAA;AAExC;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IACtB,qEAAqE;IACrE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,oGAAoG;IACpG,KAAK,IAAI,IAAI,CAAA;IACb;;;;;;;;OAQG;IACH,YAAY,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,IAAI,CAAA;IAC7D;;;;;;;OAOG;IACH,kBAAkB,CAAC,KAAK,EAAE,0BAA0B,GAAG,IAAI,CAAA;CAC5D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAOlE"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
@@ -637,9 +637,8 @@ export function createHmrSupervisor(options) {
637
637
  for (let event of events) {
638
638
  if (event.type === 'update') {
639
639
  browserHmrEventChannel?.send({
640
- timestamp: event.timestamp,
640
+ data: event.data,
641
641
  type: 'browser:update',
642
- updates: event.updates,
643
642
  });
644
643
  }
645
644
  }
@@ -986,30 +985,35 @@ function isBrowserHmrEvent(event) {
986
985
  if (typeof event !== 'object' || event === null || !('type' in event))
987
986
  return false;
988
987
  if (event.type === 'update') {
989
- return (isOptionalStringArrayProperty(event, 'files') &&
990
- 'timestamp' in event &&
991
- typeof event.timestamp === 'number' &&
992
- 'updates' in event &&
993
- Array.isArray(event.updates) &&
994
- event.updates.every(isHmrBrowserUpdate));
988
+ return ('data' in event && isJsonObject(event.data) && isOptionalStringArrayProperty(event, 'files'));
995
989
  }
996
990
  if (event.type === 'reload') {
997
991
  return isOptionalStringArrayProperty(event, 'files');
998
992
  }
999
993
  return false;
1000
994
  }
1001
- function isHmrBrowserUpdate(update) {
1002
- if (typeof update !== 'object' || update === null || !('type' in update))
1003
- return false;
1004
- if (update.type === 'js') {
1005
- return ('path' in update &&
1006
- typeof update.path === 'string' &&
1007
- (!('acceptedPath' in update) || typeof update.acceptedPath === 'string'));
1008
- }
1009
- if (update.type === 'css') {
1010
- return 'path' in update && typeof update.path === 'string';
995
+ function isJsonObject(value) {
996
+ return isJsonValue(value) && typeof value === 'object' && value !== null && !Array.isArray(value);
997
+ }
998
+ function isJsonValue(value, ancestors = new Set()) {
999
+ if (value === null ||
1000
+ typeof value === 'string' ||
1001
+ typeof value === 'boolean' ||
1002
+ (typeof value === 'number' && Number.isFinite(value))) {
1003
+ return true;
1011
1004
  }
1012
- return false;
1005
+ if (typeof value !== 'object')
1006
+ return false;
1007
+ let prototype = Object.getPrototypeOf(value);
1008
+ if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null)
1009
+ return false;
1010
+ if (ancestors.has(value))
1011
+ return false;
1012
+ ancestors.add(value);
1013
+ let values = Array.isArray(value) ? value : Object.values(value);
1014
+ let valid = values.every((item) => isJsonValue(item, ancestors));
1015
+ ancestors.delete(value);
1016
+ return valid;
1013
1017
  }
1014
1018
  function isOptionalStringArrayProperty(value, property) {
1015
1019
  if (!(property in value))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/node-hmr",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Run Node.js applications with Hot Module Reloading",
5
5
  "author": "Michael Jackson <mjijackson@gmail.com>",
6
6
  "license": "MIT",
@@ -4,45 +4,35 @@ import { hasNodeHmrParentProcess } from './process-state.ts'
4
4
 
5
5
  export const defaultBrowserHmrPathname = '/hmr'
6
6
 
7
+ /** Value that can be serialized as JSON for delivery to browser HMR clients. */
8
+ export type BrowserHmrData =
9
+ | null
10
+ | boolean
11
+ | number
12
+ | string
13
+ | BrowserHmrData[]
14
+ | { [key: string]: BrowserHmrData }
15
+
7
16
  /**
8
17
  * Event payload sent to browser HMR clients.
9
18
  */
10
19
  export interface HmrEventPayload {
11
20
  /** Event type string consumed by browser HMR clients. */
12
21
  type: string
13
- [key: string]: unknown
22
+ [key: string]: BrowserHmrData
14
23
  }
15
24
 
16
- /** JavaScript or CSS module update sent to a browser HMR client. */
17
- export type HmrBrowserUpdate =
18
- | {
19
- /** Importing module whose dependency-accept handler accepts this update. */
20
- acceptedPath?: string
21
- /** Public URL of the changed JavaScript module. */
22
- path: string
23
- /** Identifies a JavaScript module update. */
24
- type: 'js'
25
- }
26
- | {
27
- /** Public URL of the changed stylesheet. */
28
- path: string
29
- /** Identifies a stylesheet update. */
30
- type: 'css'
31
- }
32
-
33
25
  /**
34
26
  * Browser HMR event emitted to connected clients.
35
27
  */
36
28
  export type BrowserHmrEvent =
37
29
  | {
30
+ /** Consumer-owned data keyed by a stable, versioned namespace. */
31
+ data: Record<string, BrowserHmrData>
38
32
  /** Absolute source file paths that triggered this update. */
39
33
  files?: string[]
40
- /** Update timestamp used to bust module and stylesheet caches. */
41
- timestamp: number
42
34
  /** Browser update event. */
43
35
  type: 'update'
44
- /** JavaScript and CSS updates for the browser to apply. */
45
- updates: HmrBrowserUpdate[]
46
36
  }
47
37
  | {
48
38
  /** Absolute source file paths that could not be handled in place. */
package/src/lib/runner.ts CHANGED
@@ -895,9 +895,8 @@ export function createHmrSupervisor(options: {
895
895
  for (let event of events) {
896
896
  if (event.type === 'update') {
897
897
  browserHmrEventChannel?.send({
898
- timestamp: event.timestamp,
898
+ data: event.data,
899
899
  type: 'browser:update',
900
- updates: event.updates,
901
900
  })
902
901
  }
903
902
  }
@@ -1348,12 +1347,7 @@ function isBrowserHmrEvent(event: unknown): event is BrowserHmrEvent {
1348
1347
 
1349
1348
  if (event.type === 'update') {
1350
1349
  return (
1351
- isOptionalStringArrayProperty(event, 'files') &&
1352
- 'timestamp' in event &&
1353
- typeof event.timestamp === 'number' &&
1354
- 'updates' in event &&
1355
- Array.isArray(event.updates) &&
1356
- event.updates.every(isHmrBrowserUpdate)
1350
+ 'data' in event && isJsonObject(event.data) && isOptionalStringArrayProperty(event, 'files')
1357
1351
  )
1358
1352
  }
1359
1353
 
@@ -1364,22 +1358,30 @@ function isBrowserHmrEvent(event: unknown): event is BrowserHmrEvent {
1364
1358
  return false
1365
1359
  }
1366
1360
 
1367
- function isHmrBrowserUpdate(update: unknown): boolean {
1368
- if (typeof update !== 'object' || update === null || !('type' in update)) return false
1361
+ function isJsonObject(value: unknown): value is Record<string, unknown> {
1362
+ return isJsonValue(value) && typeof value === 'object' && value !== null && !Array.isArray(value)
1363
+ }
1369
1364
 
1370
- if (update.type === 'js') {
1371
- return (
1372
- 'path' in update &&
1373
- typeof update.path === 'string' &&
1374
- (!('acceptedPath' in update) || typeof update.acceptedPath === 'string')
1375
- )
1365
+ function isJsonValue(value: unknown, ancestors = new Set<object>()): boolean {
1366
+ if (
1367
+ value === null ||
1368
+ typeof value === 'string' ||
1369
+ typeof value === 'boolean' ||
1370
+ (typeof value === 'number' && Number.isFinite(value))
1371
+ ) {
1372
+ return true
1376
1373
  }
1374
+ if (typeof value !== 'object') return false
1377
1375
 
1378
- if (update.type === 'css') {
1379
- return 'path' in update && typeof update.path === 'string'
1380
- }
1376
+ let prototype = Object.getPrototypeOf(value)
1377
+ if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) return false
1378
+ if (ancestors.has(value)) return false
1381
1379
 
1382
- return false
1380
+ ancestors.add(value)
1381
+ let values = Array.isArray(value) ? value : Object.values(value)
1382
+ let valid = values.every((item) => isJsonValue(item, ancestors))
1383
+ ancestors.delete(value)
1384
+ return valid
1383
1385
  }
1384
1386
 
1385
1387
  function isOptionalStringArrayProperty(value: object, property: string): boolean {