@remix-run/assets 0.5.0 → 0.7.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 (84) hide show
  1. package/README.md +185 -104
  2. package/dist/assets.d.ts +4 -1
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/lib/access.d.ts +29 -2
  5. package/dist/lib/access.d.ts.map +1 -1
  6. package/dist/lib/access.js +52 -26
  7. package/dist/lib/asset-server.d.ts +61 -25
  8. package/dist/lib/asset-server.d.ts.map +1 -1
  9. package/dist/lib/asset-server.js +127 -55
  10. package/dist/lib/compilation-error.d.ts +1 -1
  11. package/dist/lib/compilation-error.d.ts.map +1 -1
  12. package/dist/lib/files/compiler.d.ts +1 -1
  13. package/dist/lib/files/compiler.d.ts.map +1 -1
  14. package/dist/lib/files/compiler.js +28 -31
  15. package/dist/lib/files/config.d.ts +6 -0
  16. package/dist/lib/files/config.d.ts.map +1 -1
  17. package/dist/lib/files/config.js +9 -0
  18. package/dist/lib/fingerprint.d.ts +0 -4
  19. package/dist/lib/fingerprint.d.ts.map +1 -1
  20. package/dist/lib/fingerprint.js +0 -4
  21. package/dist/lib/hmr.d.ts +7 -0
  22. package/dist/lib/hmr.d.ts.map +1 -1
  23. package/dist/lib/hmr.js +198 -25
  24. package/dist/lib/injected-packages.d.ts +3 -2
  25. package/dist/lib/injected-packages.d.ts.map +1 -1
  26. package/dist/lib/injected-packages.js +11 -8
  27. package/dist/lib/inspection.d.ts +39 -0
  28. package/dist/lib/inspection.d.ts.map +1 -0
  29. package/dist/lib/inspection.js +160 -0
  30. package/dist/lib/routes.d.ts +12 -3
  31. package/dist/lib/routes.d.ts.map +1 -1
  32. package/dist/lib/routes.js +124 -80
  33. package/dist/lib/scripts/compiler.d.ts +8 -2
  34. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  35. package/dist/lib/scripts/compiler.js +188 -38
  36. package/dist/lib/scripts/emit.d.ts +2 -1
  37. package/dist/lib/scripts/emit.d.ts.map +1 -1
  38. package/dist/lib/scripts/emit.js +25 -16
  39. package/dist/lib/scripts/resolve.d.ts +7 -1
  40. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  41. package/dist/lib/scripts/resolve.js +119 -12
  42. package/dist/lib/scripts/specifiers.d.ts +2 -0
  43. package/dist/lib/scripts/specifiers.d.ts.map +1 -0
  44. package/dist/lib/scripts/specifiers.js +9 -0
  45. package/dist/lib/scripts/transform.d.ts +2 -3
  46. package/dist/lib/scripts/transform.d.ts.map +1 -1
  47. package/dist/lib/scripts/transform.js +4 -18
  48. package/dist/lib/styles/compiler.d.ts +0 -1
  49. package/dist/lib/styles/compiler.d.ts.map +1 -1
  50. package/dist/lib/styles/compiler.js +105 -25
  51. package/dist/lib/styles/emit.d.ts +2 -1
  52. package/dist/lib/styles/emit.d.ts.map +1 -1
  53. package/dist/lib/styles/emit.js +12 -10
  54. package/dist/lib/styles/resolve.d.ts +0 -1
  55. package/dist/lib/styles/resolve.d.ts.map +1 -1
  56. package/dist/lib/styles/resolve.js +8 -9
  57. package/dist/lib/styles/transform.d.ts +0 -2
  58. package/dist/lib/styles/transform.d.ts.map +1 -1
  59. package/dist/lib/styles/transform.js +2 -9
  60. package/dist/lib/virtual-store.d.ts +8 -0
  61. package/dist/lib/virtual-store.d.ts.map +1 -0
  62. package/dist/lib/virtual-store.js +100 -0
  63. package/package.json +6 -6
  64. package/src/assets.ts +9 -1
  65. package/src/lib/access.ts +83 -30
  66. package/src/lib/asset-server.ts +224 -94
  67. package/src/lib/compilation-error.ts +4 -3
  68. package/src/lib/files/compiler.ts +32 -42
  69. package/src/lib/files/config.ts +17 -0
  70. package/src/lib/fingerprint.ts +0 -9
  71. package/src/lib/hmr.ts +210 -26
  72. package/src/lib/injected-packages.ts +16 -10
  73. package/src/lib/inspection.ts +229 -0
  74. package/src/lib/routes.ts +158 -126
  75. package/src/lib/scripts/compiler.ts +240 -54
  76. package/src/lib/scripts/emit.ts +34 -19
  77. package/src/lib/scripts/resolve.ts +175 -13
  78. package/src/lib/scripts/specifiers.ts +11 -0
  79. package/src/lib/scripts/transform.ts +6 -25
  80. package/src/lib/styles/compiler.ts +137 -39
  81. package/src/lib/styles/emit.ts +18 -13
  82. package/src/lib/styles/resolve.ts +8 -10
  83. package/src/lib/styles/transform.ts +2 -12
  84. package/src/lib/virtual-store.ts +124 -0
@@ -23,7 +23,6 @@ type ResolvedDependency = {
23
23
  export type ResolvedStyle = {
24
24
  dependencies: ResolvedDependency[];
25
25
  deps: string[];
26
- fingerprint: string | null;
27
26
  identityPath: string;
28
27
  rawCode: string;
29
28
  resolvedPath: string;
@@ -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,CAmCA"}
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,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,CA8DxB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,WAAW,GAChB;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAmCA"}
@@ -40,7 +40,6 @@ export async function resolveStyle(record, transformed, args) {
40
40
  value: {
41
41
  dependencies,
42
42
  deps: [...deps],
43
- fingerprint: transformed.fingerprint,
44
43
  identityPath: record.identityPath,
45
44
  rawCode: transformed.rawCode,
46
45
  resolvedPath: transformed.resolvedPath,
@@ -70,8 +69,8 @@ export function resolveServedStyleOrThrow(filePath, args) {
70
69
  }
71
70
  let stableUrlPathname = args.routes.toUrlPathname(identityPath);
72
71
  if (!stableUrlPathname) {
73
- throw createAssetServerCompilationError(`File ${identityPath} is outside all configured fileMap entries.`, {
74
- code: 'FILE_OUTSIDE_FILE_MAP',
72
+ throw createAssetServerCompilationError(`File ${identityPath} is outside all configured mounts.`, {
73
+ code: 'FILE_OUTSIDE_MOUNTS',
75
74
  });
76
75
  }
77
76
  return { identityPath, stableUrlPathname };
@@ -107,9 +106,9 @@ function resolveImportDependency(url, importerPath, placeholder, args) {
107
106
  });
108
107
  }
109
108
  if (!args.routes.toUrlPathname(identityPath)) {
110
- throw createAssetServerCompilationError(`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured fileMap entries. ` +
111
- `Add a matching fileMap entry for this file path, or mark this import as external.`, {
112
- code: 'IMPORT_OUTSIDE_FILE_MAP',
109
+ throw createAssetServerCompilationError(`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured mounts. ` +
110
+ `Add a matching mount for this file path, or mark this import as external.`, {
111
+ code: 'IMPORT_OUTSIDE_MOUNTS',
113
112
  });
114
113
  }
115
114
  return {
@@ -156,9 +155,9 @@ function resolveUrlDependency(url, importerPath, placeholder, args) {
156
155
  });
157
156
  }
158
157
  if (!args.routes.toUrlPathname(identityPath)) {
159
- throw createAssetServerCompilationError(`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured fileMap entries. ` +
160
- `Add a matching fileMap entry for this file path.`, {
161
- code: 'URL_OUTSIDE_FILE_MAP',
158
+ throw createAssetServerCompilationError(`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured mounts. ` +
159
+ `Add a matching mount for this file path.`, {
160
+ code: 'URL_OUTSIDE_MOUNTS',
162
161
  });
163
162
  }
164
163
  let parsedRequest = parseResolvedFileRequest({ hash, search });
@@ -12,7 +12,6 @@ type TransformedStyleDependency = {
12
12
  url: string;
13
13
  };
14
14
  export type TransformedStyle = {
15
- fingerprint: string | null;
16
15
  identityPath: string;
17
16
  rawCode: string;
18
17
  resolvedPath: string;
@@ -31,7 +30,6 @@ type TransformResult = {
31
30
  ok: false;
32
31
  });
33
32
  export type TransformArgs = {
34
- buildId: string | null;
35
33
  isWatchIgnored(filePath: string): boolean;
36
34
  minify: boolean;
37
35
  routes: CompiledRoutes;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/transform.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAEvD,KAAK,0BAA0B,GAC3B;IACE,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ,GACD;IACE,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAEL,MAAM,MAAM,gBAAgB,GAAG;IAC7B,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;IACtB,sBAAsB,EAAE,0BAA0B,EAAE,CAAA;CACrD,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,gBAAgB,CAAA;CACxB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CACJ,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAA;IACxC,oBAAoB,EAAE,UAAU,GAAG,KAAK,CAAA;IACxC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAA;CACpC,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,CAAC,CA6G1B"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/transform.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAEvD,KAAK,0BAA0B,GAC3B;IACE,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ,GACD;IACE,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAEL,MAAM,MAAM,gBAAgB,GAAG;IAC7B,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;IACtB,sBAAsB,EAAE,0BAA0B,EAAE,CAAA;CACrD,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,gBAAgB,CAAA;CACxB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CACJ,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAA;IACxC,oBAAoB,EAAE,UAAU,GAAG,KAAK,CAAA;IACxC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAA;CACpC,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,CAAC,CAsG1B"}
@@ -1,7 +1,6 @@
1
1
  import * as fs from 'node:fs/promises';
2
2
  import { transform } from 'lightningcss';
3
3
  import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
4
- import { generateFingerprint } from '../fingerprint.js';
5
4
  import { rewriteSourceMapSources, stringifySourceMap } from '../source-maps.js';
6
5
  export async function transformStyle(record, args) {
7
6
  let resolvedPath = record.identityPath;
@@ -34,8 +33,8 @@ export async function transformStyle(record, args) {
34
33
  try {
35
34
  let stableUrlPathname = args.routes.toUrlPathname(record.identityPath);
36
35
  if (!stableUrlPathname) {
37
- throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured fileMap entries.`, {
38
- code: 'FILE_OUTSIDE_FILE_MAP',
36
+ throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured mounts.`, {
37
+ code: 'FILE_OUTSIDE_MOUNTS',
39
38
  });
40
39
  }
41
40
  let transformResult = runLightningTransform(resolvedPath, rawBytes, {
@@ -72,12 +71,6 @@ export async function transformStyle(record, args) {
72
71
  trackedFiles,
73
72
  },
74
73
  value: {
75
- fingerprint: args.buildId === null
76
- ? null
77
- : await generateFingerprint({
78
- buildId: args.buildId,
79
- content: sourceText,
80
- }),
81
74
  identityPath: record.identityPath,
82
75
  rawCode: Buffer.from(transformResult.code).toString('utf8'),
83
76
  resolvedPath,
@@ -0,0 +1,8 @@
1
+ export declare function getVirtualStoreMountConfigs(options: {
2
+ mounts: Readonly<Record<string, string>>;
3
+ rootDir: string;
4
+ }): {
5
+ mounts: Record<string, string>;
6
+ rootDir: string;
7
+ }[];
8
+ //# sourceMappingURL=virtual-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-store.d.ts","sourceRoot":"","sources":["../../src/lib/virtual-store.ts"],"names":[],"mappings":"AAkBA,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACnD,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxC,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,MAAM,CAAA;CAChB,EAAE,CAcF"}
@@ -0,0 +1,100 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { getFilePathBaseName, getFilePathDirectory, normalizeFilePath, resolveFilePath, } from './paths.js';
4
+ import { resolveMountFileRoot } from './routes.js';
5
+ const modulesStateFileName = '.modules.yaml';
6
+ const virtualStoreBasePath = '/__@remix/virtual-store';
7
+ const virtualStoreDirLineRE = /^virtualStoreDir:[ \t]*(.+)$/m;
8
+ // pnpm's global virtual store links packages from a machine-wide directory, so package realpaths
9
+ // land outside `rootDir` and would otherwise have no public URL. The store location comes from
10
+ // `node_modules/.modules.yaml`, which pnpm rewrites on every install.
11
+ export function getVirtualStoreMountConfigs(options) {
12
+ let virtualStoreDir = findVirtualStoreDir(options.rootDir);
13
+ if (virtualStoreDir === null)
14
+ return [];
15
+ // A store inside a mount, such as pnpm's default `node_modules/.pnpm`, already has URLs.
16
+ if (isWithinMounts(virtualStoreDir, options))
17
+ return [];
18
+ return [
19
+ {
20
+ mounts: {
21
+ [virtualStoreBasePath]: getFilePathBaseName(virtualStoreDir),
22
+ },
23
+ rootDir: getFilePathDirectory(virtualStoreDir),
24
+ },
25
+ ];
26
+ }
27
+ function findVirtualStoreDir(rootDir) {
28
+ let directory = normalizeFilePath(rootDir);
29
+ // Workspace members share the workspace root's file, so walk up to the nearest one.
30
+ while (true) {
31
+ let modulesDir = `${directory}/node_modules`;
32
+ let modulesState = readModulesState(`${modulesDir}/${modulesStateFileName}`);
33
+ if (modulesState !== null) {
34
+ let virtualStoreDir = readVirtualStoreDir(modulesState);
35
+ if (virtualStoreDir === null)
36
+ return null;
37
+ return realpathDirectory(resolveFilePath(modulesDir, virtualStoreDir));
38
+ }
39
+ let parentDirectory = normalizeFilePath(path.dirname(directory));
40
+ if (parentDirectory === directory)
41
+ return null;
42
+ directory = parentDirectory;
43
+ }
44
+ }
45
+ function readVirtualStoreDir(modulesState) {
46
+ // pnpm 10.34 and later write JSON, earlier versions write YAML, and package managers that
47
+ // mirror the global virtual store write either one. Reading the one scalar this needs keeps
48
+ // both formats working without a YAML parser.
49
+ try {
50
+ let parsedState = JSON.parse(modulesState);
51
+ if (parsedState === null || typeof parsedState !== 'object')
52
+ return null;
53
+ let virtualStoreDir = parsedState.virtualStoreDir;
54
+ return typeof virtualStoreDir === 'string' ? virtualStoreDir : null;
55
+ }
56
+ catch {
57
+ let match = virtualStoreDirLineRE.exec(modulesState);
58
+ return match === null ? null : unquoteScalar(match[1].trim());
59
+ }
60
+ }
61
+ function unquoteScalar(value) {
62
+ let quote = value[0];
63
+ if (value.length > 1 && (quote === "'" || quote === '"') && value.endsWith(quote)) {
64
+ return value.slice(1, -1);
65
+ }
66
+ return value;
67
+ }
68
+ function isWithinMounts(directory, options) {
69
+ return Object.values(options.mounts).some((fileRoot) => {
70
+ let mountRoot = resolveMountFileRoot(options.rootDir, fileRoot);
71
+ return directory === mountRoot || directory.startsWith(`${mountRoot}/`);
72
+ });
73
+ }
74
+ function readModulesState(filePath) {
75
+ try {
76
+ return fs.readFileSync(filePath, 'utf-8');
77
+ }
78
+ catch (error) {
79
+ if (isPathNotFoundError(error))
80
+ return null;
81
+ throw error;
82
+ }
83
+ }
84
+ function realpathDirectory(filePath) {
85
+ try {
86
+ let realPath = fs.realpathSync(filePath);
87
+ return fs.statSync(realPath).isDirectory() ? normalizeFilePath(realPath) : null;
88
+ }
89
+ catch (error) {
90
+ if (isPathNotFoundError(error))
91
+ return null;
92
+ throw error;
93
+ }
94
+ }
95
+ function isPathNotFoundError(error) {
96
+ return (error instanceof Error &&
97
+ 'code' in error &&
98
+ (error.code === 'ENOENT' ||
99
+ error.code === 'ENOTDIR'));
100
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/assets",
3
- "version": "0.5.0",
3
+ "version": "0.7.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",
@@ -41,20 +41,20 @@
41
41
  "oxc-transform": "^0.121.0",
42
42
  "picomatch": "^4.0.4",
43
43
  "source-map-js": "^1.2.1",
44
- "@remix-run/file-storage": "^0.13.7",
45
- "@remix-run/headers": "^0.21.1",
46
44
  "@remix-run/mime": "^0.4.2",
47
- "@remix-run/route-pattern": "^0.24.0"
45
+ "@remix-run/file-storage": "^0.13.7",
46
+ "@remix-run/headers": "^0.21.1"
48
47
  },
49
48
  "devDependencies": {
50
49
  "@types/node": "^24.6.0",
51
50
  "@types/picomatch": "^4.0.3",
51
+ "playwright": "^1.60.0",
52
52
  "typescript": "^7.0.2",
53
53
  "@remix-run/assert": "0.3.0",
54
- "@remix-run/node-hmr": "^0.1.0",
55
54
  "@remix-run/node-tsx": "^0.1.1",
55
+ "@remix-run/node-hmr": "^0.2.0",
56
56
  "@remix-run/test": "0.6.0",
57
- "@remix-run/ui": "0.5.0"
57
+ "@remix-run/ui": "0.9.0"
58
58
  },
59
59
  "keywords": [
60
60
  "remix",
package/src/assets.ts CHANGED
@@ -1,4 +1,12 @@
1
1
  export { createAssetServer } from './lib/asset-server.ts'
2
2
  export { defineFileTransform } from './lib/files/config.ts'
3
- export type { AssetServer, AssetServerOptions, BrowserHmrChannel } from './lib/asset-server.ts'
3
+ export type { AssetAccessDetails, AssetAccessRule } from './lib/access.ts'
4
+ export type {
5
+ AssetServer,
6
+ AssetServerOptions,
7
+ BrowserHmrChannel,
8
+ ScriptEntry,
9
+ } from './lib/asset-server.ts'
10
+ export type { AssetDetails, AssetKind, AssetStatus } from './lib/inspection.ts'
11
+ export type { ScriptImportMap } from './lib/scripts/compiler.ts'
4
12
  export type { ModuleLoader } from './lib/loaders.ts'
package/src/lib/access.ts CHANGED
@@ -4,9 +4,30 @@ import { createFileMatcher } from './file-matcher.ts'
4
4
  import { isInjectedPackageFilePath } from './injected-packages.ts'
5
5
  import { normalizeFilePath } from './paths.ts'
6
6
 
7
- type AccessPolicy = {
7
+ /** Access-policy result for an inspected asset file. */
8
+ export interface AssetAccessDetails {
9
+ /** Whether the asset server may serve the file. */
10
+ allowed: boolean
11
+ /** The first configured rule that allowed the file, when one matched. */
12
+ allowedBy?: AssetAccessRule
13
+ /** The first matching `denyFiles` pattern, when access was denied. */
14
+ deniedBy?: string
15
+ }
16
+
17
+ /** Rule that allows an inspected asset file to be served. */
18
+ export type AssetAccessRule =
19
+ /** A matching `allowFiles` entry. */
20
+ | { kind: 'file'; value: string }
21
+ /** A runtime file provided internally by the asset server. */
22
+ | { kind: 'injected'; value: string }
23
+ /** A matching `allowPackages` entry. */
24
+ | { kind: 'package'; value: string }
25
+
26
+ export type AccessPolicy = {
27
+ getAllowedPackageRoots(): readonly string[]
8
28
  getPackageWatchDirectories(): readonly string[]
9
29
  handleFileEvent(filePath: string): void
30
+ inspect(filePath: string): AssetAccessDetails
10
31
  isAllowed(filePath: string): boolean
11
32
  }
12
33
 
@@ -29,13 +50,15 @@ export function createAccessPolicy(options: {
29
50
  packageSearchRoots?: readonly string[]
30
51
  rootDir: string
31
52
  }): AccessPolicy {
32
- let allowMatchers = options.allowFiles.map((pattern) =>
33
- createFileMatcher(pattern, options.rootDir),
34
- )
53
+ let allowMatchers = options.allowFiles.map((pattern) => ({
54
+ matcher: createFileMatcher(pattern, options.rootDir),
55
+ pattern,
56
+ }))
35
57
  let allowPackageNames = normalizePackageNames(options.allowPackages, 'allowPackages')
36
- let denyMatchers = (options.denyFiles ?? []).map((pattern) =>
37
- createFileMatcher(pattern, options.rootDir),
38
- )
58
+ let denyMatchers = (options.denyFiles ?? []).map((pattern) => ({
59
+ matcher: createFileMatcher(pattern, options.rootDir),
60
+ pattern,
61
+ }))
39
62
  let packageSearchRoots = [options.rootDir, ...(options.packageSearchRoots ?? [])]
40
63
  let packageRootPaths = createPackageRootPaths({
41
64
  allowPackageNames,
@@ -57,14 +80,44 @@ export function createAccessPolicy(options: {
57
80
  packageRootsDirty = false
58
81
  }
59
82
 
60
- function isAllowedPackage(filePath: string): boolean {
61
- if (allowPackageNames.size === 0) return false
83
+ function getAllowedPackageName(filePath: string): string | undefined {
84
+ if (allowPackageNames.size === 0) return undefined
62
85
  refreshPackageRootPathTries()
63
86
 
64
- return isPathInPackageRootPathTrie(filePath, allowPackageRootPathTrie)
87
+ return getPackageNameFromRootPathTrie(filePath, allowPackageRootPathTrie)
88
+ }
89
+
90
+ function inspect(filePath: string): AssetAccessDetails {
91
+ if (isInjectedPackageFilePath(filePath)) {
92
+ return { allowed: true, allowedBy: { kind: 'injected', value: '@remix-run/assets' } }
93
+ }
94
+
95
+ let allowedBy: AssetAccessRule | undefined
96
+ let allowMatch = allowMatchers.find(({ matcher }) => matcher(filePath))
97
+ if (allowMatch) {
98
+ allowedBy = { kind: 'file', value: allowMatch.pattern }
99
+ } else {
100
+ let packageName = getAllowedPackageName(filePath)
101
+ if (packageName !== undefined) {
102
+ allowedBy = { kind: 'package', value: packageName }
103
+ }
104
+ }
105
+
106
+ if (!allowedBy) return { allowed: false }
107
+
108
+ let denyMatch = denyMatchers.find(({ matcher }) => matcher(filePath))
109
+ if (denyMatch) {
110
+ return { allowed: false, allowedBy, deniedBy: denyMatch.pattern }
111
+ }
112
+
113
+ return { allowed: true, allowedBy }
65
114
  }
66
115
 
67
116
  return {
117
+ getAllowedPackageRoots() {
118
+ refreshPackageRootPathTries()
119
+ return [...packageRootPaths.keys()]
120
+ },
68
121
  getPackageWatchDirectories() {
69
122
  if (allowPackageNames.size === 0) return []
70
123
  return packageStateDirectories
@@ -75,13 +128,9 @@ export function createAccessPolicy(options: {
75
128
 
76
129
  packageRootsDirty = true
77
130
  },
131
+ inspect,
78
132
  isAllowed(filePath) {
79
- if (isInjectedPackageFilePath(filePath)) return true
80
- if (!allowMatchers.some((matcher) => matcher(filePath)) && !isAllowedPackage(filePath)) {
81
- return false
82
- }
83
- if (denyMatchers.length > 0 && denyMatchers.some((matcher) => matcher(filePath))) return false
84
- return true
133
+ return inspect(filePath).allowed
85
134
  },
86
135
  }
87
136
  }
@@ -121,7 +170,7 @@ type PackageJson = {
121
170
 
122
171
  type PackageRootPathTrie = {
123
172
  children: Map<string, PackageRootPathTrie>
124
- packageRoot: boolean
173
+ packageName?: string
125
174
  }
126
175
 
127
176
  type PackageRootQueueItem = {
@@ -132,8 +181,8 @@ type PackageRootQueueItem = {
132
181
  function createPackageRootPaths(options: {
133
182
  allowPackageNames: ReadonlySet<string>
134
183
  searchRoots: readonly string[]
135
- }): Set<string> {
136
- let allowPackageRootPaths = new Set<string>()
184
+ }): Map<string, string> {
185
+ let allowPackageRootPaths = new Map<string, string>()
137
186
  let allowQueue: PackageRootQueueItem[] = []
138
187
  let seenAllowedPackageRoots = new Set<string>()
139
188
  let searchRoots = normalizePackageSearchRoots(options.searchRoots)
@@ -155,13 +204,13 @@ function createPackageRootPaths(options: {
155
204
  }
156
205
 
157
206
  while (allowQueue.length > 0) {
158
- let { packageJsonPath } = allowQueue.shift()!
207
+ let { packageJsonPath, packageName } = allowQueue.shift()!
159
208
  let packageRootPath = normalizeFilePath(path.dirname(packageJsonPath))
160
209
  if (seenAllowedPackageRoots.has(packageRootPath)) continue
161
210
  seenAllowedPackageRoots.add(packageRootPath)
162
211
 
163
212
  let packageJson = readPackageJson(packageJsonPath)
164
- allowPackageRootPaths.add(packageRootPath)
213
+ allowPackageRootPaths.set(packageRootPath, packageName)
165
214
 
166
215
  for (let dependencyName of Object.keys(packageJson.dependencies ?? {})) {
167
216
  validatePackageName(
@@ -197,10 +246,12 @@ function createPackageRootPaths(options: {
197
246
  return allowPackageRootPaths
198
247
  }
199
248
 
200
- function createPackageRootPathTrie(packageRootPaths: ReadonlySet<string>): PackageRootPathTrie {
249
+ function createPackageRootPathTrie(
250
+ packageRootPaths: ReadonlyMap<string, string>,
251
+ ): PackageRootPathTrie {
201
252
  let rootNode = createPackageRootPathTrieNode()
202
253
 
203
- for (let packageRootPath of packageRootPaths) {
254
+ for (let [packageRootPath, packageName] of packageRootPaths) {
204
255
  let node = rootNode
205
256
  for (let segment of getFilePathSegments(packageRootPath)) {
206
257
  let childNode = node.children.get(segment)
@@ -210,7 +261,7 @@ function createPackageRootPathTrie(packageRootPaths: ReadonlySet<string>): Packa
210
261
  }
211
262
  node = childNode
212
263
  }
213
- node.packageRoot = true
264
+ node.packageName = packageName
214
265
  }
215
266
 
216
267
  return rootNode
@@ -219,22 +270,24 @@ function createPackageRootPathTrie(packageRootPaths: ReadonlySet<string>): Packa
219
270
  function createPackageRootPathTrieNode(): PackageRootPathTrie {
220
271
  return {
221
272
  children: new Map(),
222
- packageRoot: false,
223
273
  }
224
274
  }
225
275
 
226
- function isPathInPackageRootPathTrie(filePath: string, trie: PackageRootPathTrie): boolean {
276
+ function getPackageNameFromRootPathTrie(
277
+ filePath: string,
278
+ trie: PackageRootPathTrie,
279
+ ): string | undefined {
227
280
  let node = trie
228
- if (node.packageRoot) return true
281
+ if (node.packageName !== undefined) return node.packageName
229
282
 
230
283
  for (let segment of getFilePathSegments(filePath)) {
231
284
  let childNode = node.children.get(segment)
232
- if (!childNode) return false
233
- if (childNode.packageRoot) return true
285
+ if (!childNode) return undefined
286
+ if (childNode.packageName !== undefined) return childNode.packageName
234
287
  node = childNode
235
288
  }
236
289
 
237
- return false
290
+ return undefined
238
291
  }
239
292
 
240
293
  function getFilePathSegments(filePath: string): string[] {