@remix-run/assets 0.4.4 → 0.5.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.
Files changed (74) hide show
  1. package/README.md +322 -56
  2. package/dist/assets.d.ts +2 -1
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/assets.js +2 -2
  5. package/dist/lib/access.d.ts +6 -2
  6. package/dist/lib/access.d.ts.map +1 -1
  7. package/dist/lib/access.js +300 -5
  8. package/dist/lib/asset-server.d.ts +118 -5
  9. package/dist/lib/asset-server.d.ts.map +1 -1
  10. package/dist/lib/asset-server.js +260 -24
  11. package/dist/lib/compilation-error.d.ts +1 -1
  12. package/dist/lib/compilation-error.d.ts.map +1 -1
  13. package/dist/lib/file-matcher.js +1 -1
  14. package/dist/lib/files/compiler.d.ts.map +1 -1
  15. package/dist/lib/files/compiler.js +7 -6
  16. package/dist/lib/files/config.js +1 -1
  17. package/dist/lib/hmr.d.ts +37 -0
  18. package/dist/lib/hmr.d.ts.map +1 -0
  19. package/dist/lib/hmr.js +357 -0
  20. package/dist/lib/injected-packages.d.ts.map +1 -1
  21. package/dist/lib/injected-packages.js +36 -13
  22. package/dist/lib/loaders.d.ts +57 -0
  23. package/dist/lib/loaders.d.ts.map +1 -0
  24. package/dist/lib/loaders.js +1 -0
  25. package/dist/lib/module-store.d.ts +24 -0
  26. package/dist/lib/module-store.d.ts.map +1 -1
  27. package/dist/lib/module-store.js +136 -11
  28. package/dist/lib/routes.js +1 -1
  29. package/dist/lib/scripts/compiler.d.ts +24 -1
  30. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  31. package/dist/lib/scripts/compiler.js +183 -29
  32. package/dist/lib/scripts/conditions.d.ts +2 -0
  33. package/dist/lib/scripts/conditions.d.ts.map +1 -0
  34. package/dist/lib/scripts/conditions.js +1 -0
  35. package/dist/lib/scripts/emit.d.ts +3 -0
  36. package/dist/lib/scripts/emit.d.ts.map +1 -1
  37. package/dist/lib/scripts/emit.js +24 -5
  38. package/dist/lib/scripts/resolve.d.ts +4 -0
  39. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  40. package/dist/lib/scripts/resolve.js +70 -5
  41. package/dist/lib/scripts/transform.d.ts +9 -0
  42. package/dist/lib/scripts/transform.d.ts.map +1 -1
  43. package/dist/lib/scripts/transform.js +222 -18
  44. package/dist/lib/source-maps.js +1 -1
  45. package/dist/lib/styles/compiler.d.ts +14 -1
  46. package/dist/lib/styles/compiler.d.ts.map +1 -1
  47. package/dist/lib/styles/compiler.js +78 -14
  48. package/dist/lib/styles/emit.js +4 -4
  49. package/dist/lib/styles/resolve.d.ts.map +1 -1
  50. package/dist/lib/styles/resolve.js +8 -7
  51. package/dist/lib/styles/transform.js +3 -3
  52. package/dist/lib/target.d.ts +1 -1
  53. package/dist/lib/target.d.ts.map +1 -1
  54. package/dist/lib/watch.js +1 -1
  55. package/dist/types/hmr.d.ts +36 -0
  56. package/package.json +17 -11
  57. package/src/assets.ts +2 -1
  58. package/src/lib/access.ts +386 -5
  59. package/src/lib/asset-server.ts +429 -18
  60. package/src/lib/compilation-error.ts +1 -0
  61. package/src/lib/files/compiler.ts +7 -3
  62. package/src/lib/hmr.ts +397 -0
  63. package/src/lib/injected-packages.ts +41 -11
  64. package/src/lib/loaders.ts +80 -0
  65. package/src/lib/module-store.ts +190 -9
  66. package/src/lib/scripts/compiler.ts +248 -24
  67. package/src/lib/scripts/conditions.ts +1 -0
  68. package/src/lib/scripts/emit.ts +50 -5
  69. package/src/lib/scripts/resolve.ts +124 -2
  70. package/src/lib/scripts/transform.ts +290 -19
  71. package/src/lib/styles/compiler.ts +108 -8
  72. package/src/lib/styles/emit.ts +1 -1
  73. package/src/lib/styles/resolve.ts +11 -7
  74. package/src/types/hmr.d.ts +36 -0
@@ -2,13 +2,13 @@ import * as os from 'node:os';
2
2
  import * as path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { IfNoneMatch } from '@remix-run/headers/if-none-match';
5
- import { createFileMatcher } from "../file-matcher.js";
6
- import { formatFingerprintedPathname } from "../fingerprint.js";
7
- import { createModuleStore } from "../module-store.js";
8
- import { normalizeFilePath, resolveFilePath } from "../paths.js";
9
- import { emitResolvedStyle } from "./emit.js";
10
- import { resolveServedStyleOrThrow, resolveStyle } from "./resolve.js";
11
- import { transformStyle } from "./transform.js";
5
+ import { createFileMatcher } from '../file-matcher.js';
6
+ import { formatFingerprintedPathname } from '../fingerprint.js';
7
+ import { createModuleStore } from '../module-store.js';
8
+ import { normalizeFilePath, resolveFilePath } from '../paths.js';
9
+ import { emitResolvedStyle } from './emit.js';
10
+ import { resolveServedStyleOrThrow, resolveStyle } from './resolve.js';
11
+ import { transformStyle } from './transform.js';
12
12
  const preloadConcurrency = Math.max(1, Math.min(8, os.availableParallelism() - 1));
13
13
  const styleExtension = '.css';
14
14
  export function createStyleCompiler(options) {
@@ -17,7 +17,11 @@ export function createStyleCompiler(options) {
17
17
  watchIgnoreMatchers: (options.watchIgnore ?? []).map((pattern) => createFileMatcher(pattern, options.rootDir)),
18
18
  };
19
19
  let styleStore = createModuleStore({
20
+ getDependencies(resolvedStyle) {
21
+ return resolvedStyle.deps;
22
+ },
20
23
  onWatchDirectoriesChange: options.onWatchDirectoriesChange,
24
+ onWatchFilesChange: options.onWatchFilesChange,
21
25
  });
22
26
  let resolveInFlightByCacheKey = new Map();
23
27
  let emitInFlightByCacheKey = new Map();
@@ -74,7 +78,7 @@ export function createStyleCompiler(options) {
74
78
  async getStyle(filePath, getOptions) {
75
79
  let resolvedStyle = resolveServedStyleOrThrow(resolveInputFilePath(filePath), resolveArgs);
76
80
  let record = styleStore.get(resolvedStyle.identityPath);
77
- let notModified = getNotModifiedStyle(record.emitted, getOptions);
81
+ let notModified = getNotModifiedStyle(record, styleStore, getOptions, hasHmrTimestampedDependency);
78
82
  if (notModified)
79
83
  return notModified;
80
84
  let emitted = await getOrCreateEmittedStyle(record);
@@ -83,7 +87,23 @@ export function createStyleCompiler(options) {
83
87
  type: 'style',
84
88
  };
85
89
  },
86
- async handleFileEvent(filePath, event) {
90
+ async classifyHmrFileEvent(filePath, event) {
91
+ let normalizedFilePath = normalizeFilePath(filePath);
92
+ if (isWatchIgnored(normalizedFilePath))
93
+ return [];
94
+ let timestamp = Date.now();
95
+ let updatePathnames = event === 'change' ? getHmrUpdatePathnames(normalizedFilePath, timestamp) : [];
96
+ styleStore.invalidateForFileEvent(normalizedFilePath, event);
97
+ for (let updatePathname of updatePathnames) {
98
+ resolvedOptions.hmr?.send(updatePathname, timestamp);
99
+ }
100
+ return updatePathnames.map((path) => ({
101
+ filePath: normalizedFilePath,
102
+ path,
103
+ timestamp,
104
+ }));
105
+ },
106
+ invalidateFileEvent(filePath, event) {
87
107
  let normalizedFilePath = normalizeFilePath(filePath);
88
108
  if (isWatchIgnored(normalizedFilePath))
89
109
  return;
@@ -103,7 +123,7 @@ export function createStyleCompiler(options) {
103
123
  return mapWithConcurrency(records, preloadConcurrency, (record) => getOrCreateResolvedStyle(record));
104
124
  }
105
125
  async function getOrCreateResolvedStyle(record) {
106
- if (record.resolved)
126
+ if (record.resolved && styleStore.isResolvedFresh(record))
107
127
  return record.resolved;
108
128
  let cacheKey = getRecordCacheKey(record);
109
129
  let existing = resolveInFlightByCacheKey.get(cacheKey);
@@ -137,7 +157,7 @@ export function createStyleCompiler(options) {
137
157
  }
138
158
  }
139
159
  async function getOrCreateTransformedStyle(record) {
140
- if (record.transformed)
160
+ if (record.transformed && styleStore.isTransformedFresh(record))
141
161
  return record.transformed;
142
162
  let startedVersion = record.invalidationVersion;
143
163
  let transformStyleResult = await transformStyle(record, transformArgs);
@@ -155,8 +175,11 @@ export function createStyleCompiler(options) {
155
175
  return transformStyleResult.value;
156
176
  }
157
177
  async function getOrCreateEmittedStyle(record) {
158
- if (record.emitted)
178
+ if (record.emitted &&
179
+ styleStore.isEmittedFresh(record) &&
180
+ !hasHmrTimestampedDependency(record.resolved)) {
159
181
  return record.emitted;
182
+ }
160
183
  let cacheKey = getRecordCacheKey(record);
161
184
  let existing = emitInFlightByCacheKey.get(cacheKey);
162
185
  if (existing)
@@ -191,7 +214,37 @@ export function createStyleCompiler(options) {
191
214
  return getServedUrlForResolvedStyle(await getOrCreateResolvedStyle(styleStore.get(identityPath)));
192
215
  }
193
216
  function getServedUrlForResolvedStyle(resolvedStyle) {
194
- return formatFingerprintedPathname(resolvedStyle.stableUrlPathname, resolvedOptions.fingerprintAssets ? resolvedStyle.fingerprint : null);
217
+ let pathname = formatFingerprintedPathname(resolvedStyle.stableUrlPathname, resolvedOptions.fingerprintAssets ? resolvedStyle.fingerprint : null);
218
+ let timestamp = styleStore.getHmrUpdateTimestamp(resolvedStyle.identityPath);
219
+ return timestamp ? appendTimestamp(pathname, timestamp) : pathname;
220
+ }
221
+ function getHmrUpdatePathnames(identityPath, timestamp) {
222
+ let resolvedStyles = findHmrUpdateStyles(identityPath, new Set());
223
+ // Mark update timestamps before invalidating so re-emitted importer stylesheets
224
+ // can rewrite imports to the changed dependency with this HMR timestamp.
225
+ for (let resolvedStyle of resolvedStyles) {
226
+ styleStore.setHmrUpdateTimestamp(resolvedStyle.identityPath, timestamp);
227
+ }
228
+ return dedupeHmrUpdatePathnames(resolvedStyles
229
+ .filter((resolvedStyle) => styleStore.getImporters(resolvedStyle.identityPath).size === 0)
230
+ .map((resolvedStyle) => resolvedStyle.stableUrlPathname));
231
+ }
232
+ function findHmrUpdateStyles(identityPath, traversed) {
233
+ if (traversed.has(identityPath))
234
+ return [];
235
+ traversed.add(identityPath);
236
+ let resolvedStyle = styleStore.getLastResolved(identityPath);
237
+ if (!resolvedStyle)
238
+ return [];
239
+ let resolvedStyles = [resolvedStyle];
240
+ for (let importerPath of styleStore.getImporters(identityPath)) {
241
+ resolvedStyles.push(...findHmrUpdateStyles(importerPath, traversed));
242
+ }
243
+ return resolvedStyles;
244
+ }
245
+ function hasHmrTimestampedDependency(resolvedStyle) {
246
+ return (resolvedStyle?.deps.some((depPath) => styleStore.getHmrUpdateTimestamp(depPath) != null) ===
247
+ true);
195
248
  }
196
249
  function isWatchIgnored(filePath) {
197
250
  return resolvedOptions.watchIgnoreMatchers.some((matcher) => matcher(filePath));
@@ -203,7 +256,12 @@ function getRecordCacheKey(record) {
203
256
  function isFresh(record, version) {
204
257
  return record.invalidationVersion === version;
205
258
  }
206
- function getNotModifiedStyle(emittedStyle, options) {
259
+ function getNotModifiedStyle(record, styleStore, options, hasHmrTimestampedDependency) {
260
+ if (hasHmrTimestampedDependency(record.resolved))
261
+ return null;
262
+ if (!styleStore.isEmittedFresh(record))
263
+ return null;
264
+ let emittedStyle = record.emitted;
207
265
  if (!emittedStyle || options.ifNoneMatch === null)
208
266
  return null;
209
267
  if (options.requestedFingerprint !== null &&
@@ -217,6 +275,12 @@ function getNotModifiedStyle(emittedStyle, options) {
217
275
  return null;
218
276
  return { etag: asset.etag, type: 'not-modified' };
219
277
  }
278
+ function appendTimestamp(pathname, timestamp) {
279
+ return `${pathname}${pathname.includes('?') ? '&' : '?'}t=${timestamp}`;
280
+ }
281
+ function dedupeHmrUpdatePathnames(pathnames) {
282
+ return [...new Set(pathnames)];
283
+ }
220
284
  function getEmittedAssetForRequest(emittedStyle, isSourceMapRequest) {
221
285
  return isSourceMapRequest ? emittedStyle.sourceMap : emittedStyle.code;
222
286
  }
@@ -1,7 +1,7 @@
1
1
  import MagicString from 'magic-string';
2
- import { createAssetServerCompilationError, isAssetServerCompilationError, } from "../compilation-error.js";
3
- import { hashContent } from "../fingerprint.js";
4
- import { composeSourceMaps } from "../source-maps.js";
2
+ import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
3
+ import { hashContent } from '../fingerprint.js';
4
+ import { composeSourceMaps } from '../source-maps.js';
5
5
  export async function emitResolvedStyle(resolvedStyle, options) {
6
6
  try {
7
7
  let importUrls = await Promise.all(resolvedStyle.deps.map((depPath) => options.getServedUrl(depPath)));
@@ -47,7 +47,7 @@ async function rewriteDependencies(resolvedStyle, options) {
47
47
  let replacement = dependency.kind === 'external'
48
48
  ? dependency.replacement
49
49
  : dependency.kind === 'style'
50
- ? `${await options.getServedUrl(dependency.depPath)}${dependency.suffix}`
50
+ ? appendUrlSuffix(await options.getServedUrl(dependency.depPath), dependency.suffix)
51
51
  : appendUrlSuffix(await getServedFileUrl(options, resolvedStyle.identityPath, dependency.depPath, {
52
52
  transform: dependency.requestTransform,
53
53
  }), dependency.suffix);
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/resolve.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD,KAAK,WAAW,GAAG,YAAY,CAAC,gBAAgB,EAAE,aAAa,EAAE,YAAY,CAAC,CAAA;AAE9E,KAAK,kBAAkB,GACnB;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAEL,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,kBAAkB,EAAE,CAAA;IAClC,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,aAAa,CAAA;CACrB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CACJ,CAAA;AAQD,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,gBAAgB,EAC7B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA+DxB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,GAChB;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CA+BA"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/resolve.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD,KAAK,WAAW,GAAG,YAAY,CAAC,gBAAgB,EAAE,aAAa,EAAE,YAAY,CAAC,CAAA;AAE9E,KAAK,kBAAkB,GACnB;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,OAAO,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf,GACD;IACE,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAEL,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,kBAAkB,EAAE,CAAA;IAClC,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3C,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,aAAa,CAAA;CACrB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CACJ,CAAA;AAQD,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,gBAAgB,EAC7B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA+DxB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,GAChB;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAmCA"}
@@ -1,8 +1,8 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import { fileURLToPath, pathToFileURL } from 'node:url';
4
- import { createAssetServerCompilationError, isAssetServerCompilationError, } from "../compilation-error.js";
5
- import { normalizeFilePath } from "../paths.js";
4
+ import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
5
+ import { normalizeFilePath } from '../paths.js';
6
6
  export async function resolveStyle(record, transformed, args) {
7
7
  let trackedFiles = new Set(transformed.trackedFiles);
8
8
  let dependencies = [];
@@ -63,7 +63,8 @@ export function resolveServedStyleOrThrow(filePath, args) {
63
63
  });
64
64
  }
65
65
  if (!args.isAllowed(identityPath)) {
66
- throw createAssetServerCompilationError(`File is not allowed: ${identityPath}`, {
66
+ throw createAssetServerCompilationError(`File "${identityPath}" is not allowed by the asset server access configuration. ` +
67
+ `Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.`, {
67
68
  code: 'FILE_NOT_ALLOWED',
68
69
  });
69
70
  }
@@ -100,8 +101,8 @@ function resolveImportDependency(url, importerPath, placeholder, args) {
100
101
  });
101
102
  }
102
103
  if (!args.isAllowed(identityPath)) {
103
- throw createAssetServerCompilationError(`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is not allowed by the asset server allow/deny configuration. ` +
104
- `Add a matching allow rule for this file path, remove a conflicting deny rule for this file path, or mark this import as external.`, {
104
+ throw createAssetServerCompilationError(`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is not allowed by the asset server access configuration. ` +
105
+ `Add a matching allowFiles or allowPackages rule, remove a conflicting denyFiles rule, or mark this import as external.`, {
105
106
  code: 'IMPORT_NOT_ALLOWED',
106
107
  });
107
108
  }
@@ -149,8 +150,8 @@ function resolveUrlDependency(url, importerPath, placeholder, args) {
149
150
  });
150
151
  }
151
152
  if (!args.isAllowed(identityPath)) {
152
- throw createAssetServerCompilationError(`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is not allowed by the asset server allow/deny configuration. ` +
153
- `Add a matching allow rule for this file path or remove a conflicting deny rule for this file path.`, {
153
+ throw createAssetServerCompilationError(`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is not allowed by the asset server access configuration. ` +
154
+ `Add a matching allowFiles or allowPackages rule, or remove a conflicting denyFiles rule.`, {
154
155
  code: 'URL_NOT_ALLOWED',
155
156
  });
156
157
  }
@@ -1,8 +1,8 @@
1
1
  import * as fs from 'node:fs/promises';
2
2
  import { transform } from 'lightningcss';
3
- import { createAssetServerCompilationError, isAssetServerCompilationError, } from "../compilation-error.js";
4
- import { generateFingerprint } from "../fingerprint.js";
5
- import { rewriteSourceMapSources, stringifySourceMap } from "../source-maps.js";
3
+ import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
4
+ import { generateFingerprint } from '../fingerprint.js';
5
+ import { rewriteSourceMapSources, stringifySourceMap } from '../source-maps.js';
6
6
  export async function transformStyle(record, args) {
7
7
  let resolvedPath = record.identityPath;
8
8
  let trackedFiles = args.isWatchIgnored(resolvedPath) ? [] : [resolvedPath];
@@ -1,5 +1,5 @@
1
1
  import type { Targets as LightningCssTargets } from 'lightningcss';
2
- declare const browserTargetNames: readonly ["chrome", "edge", "firefox", "ie", "ios", "opera", "safari", "samsung"];
2
+ declare const browserTargetNames: readonly ['chrome', 'edge', 'firefox', 'ie', 'ios', 'opera', 'safari', 'samsung'];
3
3
  export type AssetTargetVersion = `${number}` | `${number}.${number}` | `${number}.${number}.${number}`;
4
4
  export type BrowserTargetName = (typeof browserTargetNames)[number];
5
5
  export type ResolvedScriptTarget = string[];
@@ -1 +1 @@
1
- {"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/lib/target.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElE,QAAA,MAAM,kBAAkB,mFASd,CAAA;AAeV,MAAM,MAAM,kBAAkB,GAC1B,GAAG,MAAM,EAAE,GACX,GAAG,MAAM,IAAI,MAAM,EAAE,GACrB,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAA;AACnC,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AACnE,MAAM,MAAM,oBAAoB,GAAG,MAAM,EAAE,CAAA;AAC3C,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAA;AAErD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,EAAE,CAAC,EAAE,kBAAkB,CAAA;IACvB,GAAG,CAAC,EAAE,kBAAkB,CAAA;IACxB,KAAK,CAAC,EAAE,kBAAkB,CAAA;IAC1B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAMD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,oBAAoB,GAAG,SAAS,CAgBlC;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,mBAAmB,GAAG,SAAS,CAajC"}
1
+ {"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/lib/target.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElE,QAAA,MAAM,kBAAkB,YACtB,QAAQ,EACR,MAAM,EACN,SAAS,EACT,IAAI,EACJ,KAAK,EACL,OAAO,EACP,QAAQ,EACR,SAAS,CACD,CAAA;AAeV,MAAM,MAAM,kBAAkB,GAC1B,GAAG,MAAM,EAAE,GACX,GAAG,MAAM,IAAI,MAAM,EAAE,GACrB,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAA;AACnC,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AACnE,MAAM,MAAM,oBAAoB,GAAG,MAAM,EAAE,CAAA;AAC3C,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAA;AAErD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,IAAI,CAAC,EAAE,kBAAkB,CAAA;IACzB,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,EAAE,CAAC,EAAE,kBAAkB,CAAA;IACvB,GAAG,CAAC,EAAE,kBAAkB,CAAA;IACxB,KAAK,CAAC,EAAE,kBAAkB,CAAA;IAC1B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAMD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,oBAAoB,GAAG,SAAS,CAgBlC;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,mBAAmB,GAAG,SAAS,CAajC"}
package/dist/lib/watch.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import chokidar from 'chokidar';
2
- import { getFilePathDirectory, normalizeFilePath } from "./paths.js";
2
+ import { getFilePathDirectory, normalizeFilePath } from './paths.js';
3
3
  export function createAssetServerWatcher(options) {
4
4
  let watcher = chokidar.watch([], {
5
5
  ignoreInitial: true,
@@ -0,0 +1,36 @@
1
+ interface ImportMetaHot {
2
+ /** Mutable state preserved for this module across accepted updates and passed to dispose handlers. */
3
+ readonly data: Record<string, unknown>
4
+ /** Accepts updates to this module, optionally receiving its newly evaluated namespace. */
5
+ accept(callback?: (module: HotModule) => HotCallbackResult): void
6
+ /** Accepts updates from one dependency, optionally receiving its newly evaluated namespace. */
7
+ accept(dep: string, callback?: (module: HotModule) => HotCallbackResult): void
8
+ /**
9
+ * Accepts updates from multiple dependencies. The callback array preserves `deps` order and
10
+ * contains the updated namespace only at the position of the dependency that changed.
11
+ */
12
+ accept(
13
+ deps: readonly string[],
14
+ callback?: (modules: Array<HotModule | undefined>) => HotCallbackResult,
15
+ ): void
16
+ /** Registers cleanup that runs before this module is re-evaluated or the runtime is disposed. */
17
+ dispose(callback: (data: Record<string, unknown>) => HotCallbackResult): void
18
+ /** Declines the current update and reloads the page if no importing boundary accepts it. */
19
+ invalidate(message?: string): void
20
+ /** Registers a listener for custom events from the browser HMR channel. */
21
+ on(event: string, callback: (data: unknown) => void | Promise<void>): void
22
+ }
23
+
24
+ type HotModule = Readonly<Record<string, unknown>> & {
25
+ readonly [Symbol.toStringTag]: 'Module'
26
+ }
27
+
28
+ type HotCallbackResult = void | Promise<void>
29
+
30
+ declare global {
31
+ interface ImportMeta {
32
+ readonly hot?: ImportMetaHot
33
+ }
34
+ }
35
+
36
+ export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/assets",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "description": "Fetch-based server for compiling browser JS/TS and CSS assets on demand",
5
5
  "author": "Michael Jackson <mjijackson@gmail.com>",
6
6
  "license": "MIT",
@@ -23,6 +23,9 @@
23
23
  "types": "./dist/assets.d.ts",
24
24
  "default": "./dist/assets.js"
25
25
  },
26
+ "./types/hmr": {
27
+ "types": "./dist/types/hmr.d.ts"
28
+ },
26
29
  "./package.json": "./package.json"
27
30
  },
28
31
  "dependencies": {
@@ -38,17 +41,20 @@
38
41
  "oxc-transform": "^0.121.0",
39
42
  "picomatch": "^4.0.4",
40
43
  "source-map-js": "^1.2.1",
41
- "@remix-run/headers": "0.21.1",
42
- "@remix-run/file-storage": "0.13.7",
43
- "@remix-run/route-pattern": "0.23.0",
44
- "@remix-run/mime": "0.4.2"
44
+ "@remix-run/file-storage": "^0.13.7",
45
+ "@remix-run/headers": "^0.21.1",
46
+ "@remix-run/mime": "^0.4.2",
47
+ "@remix-run/route-pattern": "^0.24.0"
45
48
  },
46
49
  "devDependencies": {
47
50
  "@types/node": "^24.6.0",
48
51
  "@types/picomatch": "^4.0.3",
49
- "@typescript/native-preview": "7.0.0-dev.20251125.1",
52
+ "typescript": "^7.0.2",
50
53
  "@remix-run/assert": "0.3.0",
51
- "@remix-run/test": "0.5.0"
54
+ "@remix-run/node-hmr": "^0.1.0",
55
+ "@remix-run/node-tsx": "^0.1.1",
56
+ "@remix-run/test": "0.6.0",
57
+ "@remix-run/ui": "0.5.0"
52
58
  },
53
59
  "keywords": [
54
60
  "remix",
@@ -61,10 +67,10 @@
61
67
  ],
62
68
  "scripts": {
63
69
  "bench": "pnpm --dir ./bench run bench",
64
- "build": "tsgo -p tsconfig.build.json",
70
+ "build": "tsc -p tsconfig.build.json && node ../../scripts/copy-package-type-only-exports.ts .",
65
71
  "clean": "git clean -fdX",
66
- "test": "remix-test",
67
- "test:bun": "bun x --bun remix-test",
68
- "typecheck": "tsgo --noEmit"
72
+ "test": "remix test",
73
+ "test:bun": "bun x --bun remix test --type server",
74
+ "typecheck": "tsc --noEmit"
69
75
  }
70
76
  }
package/src/assets.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { createAssetServer } from './lib/asset-server.ts'
2
2
  export { defineFileTransform } from './lib/files/config.ts'
3
- export type { AssetServer, AssetServerOptions } from './lib/asset-server.ts'
3
+ export type { AssetServer, AssetServerOptions, BrowserHmrChannel } from './lib/asset-server.ts'
4
+ export type { ModuleLoader } from './lib/loaders.ts'