@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
@@ -3,6 +3,7 @@ import * as path from 'node:path';
3
3
  import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
4
4
  import { getInjectedPackageNameForSpecifier, getInjectedPackageImporterPath, restoreAuthoredInjectedPackageSpecifier, } from '../injected-packages.js';
5
5
  import { normalizeFilePath } from '../paths.js';
6
+ import { isBareImportSpecifier } from './specifiers.js';
6
7
  export const resolverExtensionAlias = {
7
8
  '.js': ['.js', '.ts', '.tsx', '.jsx'],
8
9
  '.jsx': ['.jsx', '.tsx'],
@@ -27,15 +28,17 @@ export async function resolveModule(record, transformed, args) {
27
28
  });
28
29
  }
29
30
  let importsWithPaths = [];
31
+ let pendingBareImportScopes = [];
30
32
  let acceptedDepsWithPaths = [];
31
33
  let deps = new Set();
34
+ let staticDeps = new Set();
32
35
  for (let unresolved of transformed.unresolvedImports) {
33
36
  let displaySpecifier = getDisplayImportSpecifier(unresolved.specifier);
34
37
  let trackedResolution = getTrackedRelativeImportResolution(transformed.importerDir, displaySpecifier, args.isWatchIgnored);
35
38
  let resolvedSpec = resolvedImports.get(unresolved.specifier);
36
39
  if (!resolvedSpec?.absolutePath) {
37
40
  return failResolve(createAssetServerCompilationError(`Failed to resolve import "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
38
- `Ensure it resolves to a file within the configured asset server fileMap, or mark it as external.`, {
41
+ `Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
39
42
  code: 'IMPORT_RESOLUTION_FAILED',
40
43
  }), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
41
44
  }
@@ -54,12 +57,14 @@ export async function resolveModule(record, transformed, args) {
54
57
  }
55
58
  let stableUrlPathname = args.routes.toUrlPathname(resolvedImport.identityPath);
56
59
  if (!stableUrlPathname) {
57
- return failResolve(createAssetServerCompilationError(`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured fileMap entries. ` +
58
- `Add a matching fileMap entry for this file path, or mark this import as external.`, {
59
- code: 'IMPORT_OUTSIDE_FILE_MAP',
60
+ return failResolve(createAssetServerCompilationError(`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
61
+ `Add a matching mount for this file path, or mark this import as external.`, {
62
+ code: 'IMPORT_OUTSIDE_MOUNTS',
60
63
  }), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
61
64
  }
62
65
  deps.add(resolvedImport.identityPath);
66
+ if (!unresolved.dynamic)
67
+ staticDeps.add(resolvedImport.identityPath);
63
68
  if (transformed.packageSpecifiers.includes(unresolved.specifier)) {
64
69
  let packageJsonPath = resolvedSpec.packageJsonPath ?? findNearestPackageJsonPath(resolvedImport.resolvedPath);
65
70
  if (packageJsonPath && !args.isWatchIgnored(packageJsonPath)) {
@@ -72,12 +77,38 @@ export async function resolveModule(record, transformed, args) {
72
77
  resolvedIdentityPath: resolvedImport.identityPath,
73
78
  });
74
79
  }
75
- importsWithPaths.push({
80
+ let imported = {
81
+ compiledSpecifier: unresolved.specifier,
76
82
  depPath: resolvedImport.identityPath,
77
83
  end: unresolved.end,
78
84
  quote: unresolved.quote,
85
+ specifier: displaySpecifier,
79
86
  start: unresolved.start,
80
- });
87
+ };
88
+ importsWithPaths.push(imported);
89
+ if (isBareImportSpecifier(displaySpecifier)) {
90
+ pendingBareImportScopes.push({
91
+ imported,
92
+ resolvedIdentityPath: resolvedImport.identityPath,
93
+ specifier: normalizeSpecifierResolution(unresolved.specifier, transformed.resolvedPath)
94
+ .specifier,
95
+ trackedResolution,
96
+ });
97
+ }
98
+ }
99
+ if (pendingBareImportScopes.length > 0) {
100
+ let scopeResults = await resolveBareImportScopes(pendingBareImportScopes, transformed.resolvedPath, args);
101
+ for (let index = 0; index < scopeResults.length; index++) {
102
+ let result = scopeResults[index];
103
+ let pending = pendingBareImportScopes[index];
104
+ if (!result.ok) {
105
+ return failResolve(result.error, trackedFiles, trackedResolutions, transformed.resolvedPath, {
106
+ isWatchIgnored: args.isWatchIgnored,
107
+ trackedResolution: pending.trackedResolution,
108
+ });
109
+ }
110
+ pending.imported.scopePathname = result.scopePathname;
111
+ }
81
112
  }
82
113
  for (let unresolved of transformed.hmr.acceptedDeps) {
83
114
  if (isBrowserExternalModuleUrl(unresolved.specifier))
@@ -98,7 +129,7 @@ export async function resolveModule(record, transformed, args) {
98
129
  }
99
130
  if (!resolvedSpec?.absolutePath) {
100
131
  return failResolve(createAssetServerCompilationError(`Failed to resolve accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
101
- `Ensure it resolves to a file within the configured asset server fileMap, or mark it as external.`, {
132
+ `Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
102
133
  code: 'IMPORT_RESOLUTION_FAILED',
103
134
  }), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
104
135
  }
@@ -117,9 +148,9 @@ export async function resolveModule(record, transformed, args) {
117
148
  }
118
149
  let stableUrlPathname = args.routes.toUrlPathname(resolvedImport.identityPath);
119
150
  if (!stableUrlPathname) {
120
- return failResolve(createAssetServerCompilationError(`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured fileMap entries. ` +
121
- `Add a matching fileMap entry for this file path, or mark this import as external.`, {
122
- code: 'IMPORT_OUTSIDE_FILE_MAP',
151
+ return failResolve(createAssetServerCompilationError(`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
152
+ `Add a matching mount for this file path, or mark this import as external.`, {
153
+ code: 'IMPORT_OUTSIDE_MOUNTS',
123
154
  }), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
124
155
  }
125
156
  if (trackedResolution) {
@@ -129,9 +160,11 @@ export async function resolveModule(record, transformed, args) {
129
160
  });
130
161
  }
131
162
  acceptedDepsWithPaths.push({
163
+ compiledSpecifier: unresolved.specifier,
132
164
  depPath: resolvedImport.identityPath,
133
165
  end: unresolved.end,
134
166
  quote: unresolved.quote,
167
+ specifier: displaySpecifier,
135
168
  start: unresolved.start,
136
169
  });
137
170
  }
@@ -140,7 +173,6 @@ export async function resolveModule(record, transformed, args) {
140
173
  tracking: toResolveTracking(trackedFiles, trackedResolutions),
141
174
  value: {
142
175
  deps: [...deps],
143
- fingerprint: transformed.fingerprint,
144
176
  hmr: {
145
177
  acceptedDeps: acceptedDepsWithPaths,
146
178
  selfAccepting: transformed.hmr.selfAccepting,
@@ -152,10 +184,85 @@ export async function resolveModule(record, transformed, args) {
152
184
  rawCode: transformed.rawCode,
153
185
  resolvedPath: transformed.resolvedPath,
154
186
  sourceMap: transformed.sourceMap,
187
+ staticDeps: [...staticDeps],
155
188
  stableUrlPathname: transformed.stableUrlPathname,
156
189
  },
157
190
  };
158
191
  }
192
+ async function resolveBareImportScopes(pendingScopes, importerPath, args) {
193
+ let results = new Array(pendingScopes.length);
194
+ let nextIndex = 0;
195
+ async function worker() {
196
+ while (nextIndex < pendingScopes.length) {
197
+ let index = nextIndex++;
198
+ let pending = pendingScopes[index];
199
+ try {
200
+ results[index] = {
201
+ ok: true,
202
+ scopePathname: await getBareImportScopePathname({
203
+ importerPath,
204
+ resolvedIdentityPath: pending.resolvedIdentityPath,
205
+ specifier: pending.specifier,
206
+ ...args,
207
+ }),
208
+ };
209
+ }
210
+ catch (error) {
211
+ results[index] = {
212
+ ok: false,
213
+ error: isAssetServerCompilationError(error)
214
+ ? error
215
+ : createAssetServerCompilationError(`Failed to determine an import map scope for "${pending.imported.specifier}" in ${importerPath}. ${formatUnknownError(error)}`, { cause: error, code: 'IMPORT_RESOLUTION_FAILED' }),
216
+ };
217
+ }
218
+ }
219
+ }
220
+ if (pendingScopes.length === 1) {
221
+ await worker();
222
+ }
223
+ else {
224
+ await Promise.all(Array.from({ length: Math.min(args.concurrency, pendingScopes.length) }, () => worker()));
225
+ }
226
+ return results;
227
+ }
228
+ async function getBareImportScopePathname(args) {
229
+ let importerDirectory = normalizeFilePath(path.dirname(args.importerPath));
230
+ let importerScopePathname = args.routes.toUrlPathname(importerDirectory);
231
+ if (!importerScopePathname) {
232
+ throw new Error(`Expected a URL pathname for ${importerDirectory}`);
233
+ }
234
+ let importerDirectoryResolution = args.resolvedIdentityPath;
235
+ if (!args.isDirectoryResolutionFileIndependent(importerDirectory)) {
236
+ importerDirectoryResolution = await args.resolveDirectorySpecifierIdentity(importerDirectory, args.specifier);
237
+ if (importerDirectoryResolution !== args.resolvedIdentityPath) {
238
+ throw createAssetServerCompilationError(`Bare import "${args.specifier}" in ${args.importerPath} resolves differently based on the importer file. ` +
239
+ `Browser module resolution must be uniform for all files in the same directory.`, { code: 'IMPORT_RESOLUTION_NOT_DIRECTORY_UNIFORM' });
240
+ }
241
+ }
242
+ let directory = importerDirectory;
243
+ let scopePathname = importerScopePathname;
244
+ let broadestScopePathname = importerScopePathname;
245
+ while (true) {
246
+ let resolvedIdentityPath = directory === importerDirectory
247
+ ? importerDirectoryResolution
248
+ : await args.resolveDirectorySpecifierIdentity(directory, args.specifier);
249
+ if (resolvedIdentityPath !== args.resolvedIdentityPath)
250
+ break;
251
+ broadestScopePathname = scopePathname;
252
+ let parentDirectory = normalizeFilePath(path.dirname(directory));
253
+ if (parentDirectory === directory)
254
+ break;
255
+ let parentScopePathname = args.routes.toUrlPathname(parentDirectory);
256
+ if (!parentScopePathname)
257
+ break;
258
+ directory = parentDirectory;
259
+ scopePathname = parentScopePathname;
260
+ }
261
+ return ensureTrailingSlash(broadestScopePathname);
262
+ }
263
+ function ensureTrailingSlash(value) {
264
+ return value.endsWith('/') ? value : `${value}/`;
265
+ }
159
266
  function findNearestPackageJsonPath(filePath) {
160
267
  let directory = path.dirname(filePath);
161
268
  while (true) {
@@ -234,7 +341,7 @@ async function batchResolveSpecifiers(specifiers, importerPath, resolverFactory)
234
341
  throw createAssetServerCompilationError(normalizedResolution.importerPath === getInjectedPackageImporterPath()
235
342
  ? `Failed to resolve injected import "${specifier}" from asset server.`
236
343
  : `Failed to resolve import "${normalizedResolution.specifier}" in ${normalizedResolution.importerPath}. ` +
237
- `Ensure it resolves to a file within the configured asset server fileMap, or mark it as external.`, {
344
+ `Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
238
345
  code: 'IMPORT_RESOLUTION_FAILED',
239
346
  });
240
347
  }
@@ -0,0 +1,2 @@
1
+ export declare function isBareImportSpecifier(specifier: string): boolean;
2
+ //# sourceMappingURL=specifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specifiers.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/specifiers.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAUhE"}
@@ -0,0 +1,9 @@
1
+ export function isBareImportSpecifier(specifier) {
2
+ return (!specifier.startsWith('./') &&
3
+ !specifier.startsWith('../') &&
4
+ !specifier.startsWith('/') &&
5
+ !specifier.startsWith('file:') &&
6
+ !specifier.startsWith('data:') &&
7
+ !specifier.startsWith('http://') &&
8
+ !specifier.startsWith('https://'));
9
+ }
@@ -12,14 +12,14 @@ export type ResolveModuleResult = {
12
12
  resolvedPath: string;
13
13
  };
14
14
  type UnresolvedImport = {
15
+ dynamic: boolean;
15
16
  end: number;
16
17
  quote?: '"' | "'" | '`';
17
18
  specifier: string;
18
19
  start: number;
19
20
  };
20
- type HmrAcceptedDependency = UnresolvedImport;
21
+ type HmrAcceptedDependency = Omit<UnresolvedImport, 'dynamic'>;
21
22
  export type TransformedModule = {
22
- fingerprint: string | null;
23
23
  hmr: {
24
24
  acceptedDeps: HmrAcceptedDependency[];
25
25
  selfAccepting: boolean;
@@ -50,7 +50,6 @@ type TsconfigTransformOptions = {
50
50
  };
51
51
  type TsconfigTransformOptionsResolver = ReturnType<typeof createTsconfigTransformOptionsResolver>;
52
52
  export type TransformArgs = {
53
- buildId: string | null;
54
53
  define: Record<string, string> | null;
55
54
  externalSet: ReadonlySet<string>;
56
55
  isWatchIgnored(filePath: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/transform.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAS,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAS/D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAO1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD,KAAK,YAAY,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AA6BlF,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,qBAAqB,GAAG,gBAAgB,CAAA;AAE7C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,EAAE;QACH,YAAY,EAAE,qBAAqB,EAAE,CAAA;QACrC,aAAa,EAAE,OAAO,CAAA;QACtB,iBAAiB,EAAE,OAAO,CAAA;KAC3B,CAAA;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,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,iBAAiB,EAAE,gBAAgB,EAAE,CAAA;CACtC,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,iBAAiB,CAAA;CACzB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CACJ,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,oBAAoB,CAAA;CACnC,CAAA;AAED,KAAK,gCAAgC,GAAG,UAAU,CAAC,OAAO,sCAAsC,CAAC,CAAA;AAEjG,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IACrC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IAChC,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACtD,MAAM,EAAE,cAAc,CAAA;IACtB,oBAAoB,EAAE,UAAU,GAAG,KAAK,CAAA;IACxC,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAA;IACxC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACnC,gCAAgC,EAAE,gCAAgC,CAAA;CACnE,CAAA;AAED,wBAAgB,sCAAsC;IAKlD,KAAK;IAIL,mBAAmB,WACP,MAAM,kBACA,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAC5C,wBAAwB;EAsB9B;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,CAAC,CAgI1B;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAuDxE"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/transform.ts"],"names":[],"mappings":"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"}
@@ -10,11 +10,11 @@ import { transform as oxcTransform } from 'oxc-transform';
10
10
  import { init as esModuleLexerInit, parse as esModuleLexer } from 'es-module-lexer';
11
11
  import { isCommonJS, mayContainCommonJSModuleGlobals } from './cjs-check.js';
12
12
  import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
13
- import { generateFingerprint } from '../fingerprint.js';
14
13
  import { maskAuthoredInjectedPackageSpecifier, mayContainInjectedPackageSpecifier, restoreAuthoredInjectedPackageSpecifier, } from '../injected-packages.js';
15
14
  import { normalizeFilePath } from '../paths.js';
16
15
  import { composeSourceMaps, rewriteSourceMapSources, stringifySourceMap } from '../source-maps.js';
17
16
  import { scriptLoaderConditions } from './conditions.js';
17
+ import { isBareImportSpecifier } from './specifiers.js';
18
18
  const scriptModuleTypes = [
19
19
  { extension: '.js', lang: 'js' },
20
20
  { extension: '.jsx', lang: 'jsx' },
@@ -109,8 +109,8 @@ export async function transformModule(record, args) {
109
109
  try {
110
110
  let stableUrlPathname = args.routes.toUrlPathname(record.identityPath);
111
111
  if (!stableUrlPathname) {
112
- throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured fileMap entries.`, {
113
- code: 'FILE_OUTSIDE_FILE_MAP',
112
+ throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured mounts.`, {
113
+ code: 'FILE_OUTSIDE_MOUNTS',
114
114
  });
115
115
  }
116
116
  let analysis = await analyzeModuleSource(sourceText, resolvedPath, transformOptions, {
@@ -138,12 +138,6 @@ export async function transformModule(record, args) {
138
138
  trackedFiles,
139
139
  },
140
140
  value: {
141
- fingerprint: args.buildId === null
142
- ? null
143
- : await generateFingerprint({
144
- buildId: args.buildId,
145
- content: sourceText,
146
- }),
147
141
  hmr: getHmrAnalysis(analysis.rawCode),
148
142
  identityPath: record.identityPath,
149
143
  importerDir: path.dirname(resolvedPath),
@@ -281,15 +275,6 @@ function findNearestTsconfigPath(directory) {
281
275
  currentDirectory = parentDirectory;
282
276
  }
283
277
  }
284
- function isBareImportSpecifier(specifier) {
285
- return (!specifier.startsWith('./') &&
286
- !specifier.startsWith('../') &&
287
- !specifier.startsWith('/') &&
288
- !specifier.startsWith('file:') &&
289
- !specifier.startsWith('data:') &&
290
- !specifier.startsWith('http://') &&
291
- !specifier.startsWith('https://'));
292
- }
293
278
  async function analyzeModuleSource(sourceText, resolvedPath, transformOptions, options) {
294
279
  let maskedSourceText = maskAuthoredInjectedPackageImports(sourceText, resolvedPath);
295
280
  let transformResult;
@@ -533,6 +518,7 @@ async function getUnresolvedImportsFromLexer(rawCode) {
533
518
  if (specifier == null || isBrowserExternalModuleUrl(specifier))
534
519
  continue;
535
520
  unresolvedImports.push({
521
+ dynamic: imported.d !== -1,
536
522
  specifier,
537
523
  start: imported.s,
538
524
  end: imported.e,
@@ -19,7 +19,6 @@ type StyleGetOptions = {
19
19
  requestedFingerprint: string | null;
20
20
  };
21
21
  type StyleCompilerOptions = {
22
- buildId?: string;
23
22
  fingerprintAssets: boolean;
24
23
  getServedFileUrl?(identityPath: string, options: {
25
24
  transform: readonly string[] | null;
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/compiler.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ 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 { createAssetServerCompilationError } from '../compilation-error.js';
5
6
  import { createFileMatcher } from '../file-matcher.js';
6
7
  import { formatFingerprintedPathname } from '../fingerprint.js';
7
8
  import { createModuleStore } from '../module-store.js';
@@ -32,7 +33,6 @@ export function createStyleCompiler(options) {
32
33
  routes: resolvedOptions.routes,
33
34
  };
34
35
  let transformArgs = {
35
- buildId: resolvedOptions.buildId ?? null,
36
36
  isWatchIgnored,
37
37
  minify: resolvedOptions.minify,
38
38
  routes: resolvedOptions.routes,
@@ -43,7 +43,8 @@ export function createStyleCompiler(options) {
43
43
  return {
44
44
  async getHref(filePath) {
45
45
  let resolvedStyle = resolveServedStyleOrThrow(resolveInputFilePath(filePath), resolveArgs);
46
- return getServedUrl(resolvedStyle.identityPath);
46
+ let graph = await resolveStyleGraph(resolvedStyle.identityPath);
47
+ return getServedUrlFromGraph(resolvedStyle.identityPath, graph);
47
48
  },
48
49
  async getPreloadLayers(filePath) {
49
50
  let resolvedEntries = [];
@@ -57,13 +58,17 @@ export function createStyleCompiler(options) {
57
58
  let visited = new Set(resolvedEntries);
58
59
  let queue = [...resolvedEntries];
59
60
  let layers = [];
61
+ let graph = await resolveStyleGraph(resolvedEntries);
60
62
  while (queue.length > 0) {
61
63
  let frontier = queue;
62
64
  queue = [];
63
- let resolvedStyles = await getOrCreateResolvedStyles(frontier.map((identityPath) => styleStore.get(identityPath)));
64
65
  let layer = [];
65
- for (let resolvedStyle of resolvedStyles) {
66
- layer.push(getServedUrlForResolvedStyle(resolvedStyle));
66
+ for (let identityPath of frontier) {
67
+ let graphEntry = graph.get(identityPath);
68
+ if (!graphEntry)
69
+ throw new Error(`Missing resolved style ${identityPath}`);
70
+ let resolvedStyle = graphEntry.resolvedStyle;
71
+ layer.push(await getServedUrlFromGraph(identityPath, graph));
67
72
  for (let dep of resolvedStyle.deps) {
68
73
  if (visited.has(dep))
69
74
  continue;
@@ -119,9 +124,6 @@ export function createStyleCompiler(options) {
119
124
  }
120
125
  return resolveFilePath(resolvedOptions.rootDir, filePath);
121
126
  }
122
- async function getOrCreateResolvedStyles(records) {
123
- return mapWithConcurrency(records, preloadConcurrency, (record) => getOrCreateResolvedStyle(record));
124
- }
125
127
  async function getOrCreateResolvedStyle(record) {
126
128
  if (record.resolved && styleStore.isResolvedFresh(record))
127
129
  return record.resolved;
@@ -180,22 +182,37 @@ export function createStyleCompiler(options) {
180
182
  !hasHmrTimestampedDependency(record.resolved)) {
181
183
  return record.emitted;
182
184
  }
183
- let cacheKey = getRecordCacheKey(record);
185
+ let graph = await resolveStyleGraph(record.identityPath);
186
+ return getOrCreateEmittedStyleFromGraph(record, graph);
187
+ }
188
+ async function getOrCreateEmittedStyleFromGraph(record, graph) {
189
+ let graphEntry = graph.get(record.identityPath);
190
+ if (!graphEntry) {
191
+ throw new Error(`Missing resolved style ${record.identityPath}`);
192
+ }
193
+ if (record.invalidationVersion === graphEntry.invalidationVersion &&
194
+ record.emitted &&
195
+ styleStore.isEmittedFresh(record) &&
196
+ !hasHmrTimestampedDependency(record.resolved)) {
197
+ return record.emitted;
198
+ }
199
+ let cacheKey = getCacheKey(record.identityPath, graphEntry.invalidationVersion);
184
200
  let existing = emitInFlightByCacheKey.get(cacheKey);
185
201
  if (existing)
186
202
  return existing;
187
203
  let promise = (async () => {
188
- let startedVersion = record.invalidationVersion;
189
- let resolvedStyle = await getOrCreateResolvedStyle(record);
190
- let emitResolvedStyleResult = await emitResolvedStyle(resolvedStyle, {
204
+ let emitResolvedStyleResult = await emitResolvedStyle(graphEntry.resolvedStyle, {
205
+ fingerprintAssets: resolvedOptions.fingerprintAssets,
191
206
  getServedFileUrl: resolvedOptions.getServedFileUrl,
192
- getServedUrl,
207
+ getServedUrl(identityPath) {
208
+ return getServedUrlFromGraph(identityPath, graph);
209
+ },
193
210
  sourceMaps: resolvedOptions.sourceMaps,
194
211
  });
195
212
  if (!emitResolvedStyleResult.ok) {
196
213
  throw emitResolvedStyleResult.error;
197
214
  }
198
- if (isFresh(record, startedVersion)) {
215
+ if (isFresh(record, graphEntry.invalidationVersion)) {
199
216
  styleStore.setEmitted(record.identityPath, emitResolvedStyleResult.value, null);
200
217
  }
201
218
  return emitResolvedStyleResult.value;
@@ -210,14 +227,75 @@ export function createStyleCompiler(options) {
210
227
  }
211
228
  }
212
229
  }
213
- async function getServedUrl(identityPath) {
214
- return getServedUrlForResolvedStyle(await getOrCreateResolvedStyle(styleStore.get(identityPath)));
215
- }
216
- function getServedUrlForResolvedStyle(resolvedStyle) {
217
- let pathname = formatFingerprintedPathname(resolvedStyle.stableUrlPathname, resolvedOptions.fingerprintAssets ? resolvedStyle.fingerprint : null);
218
- let timestamp = styleStore.getHmrUpdateTimestamp(resolvedStyle.identityPath);
230
+ async function getServedUrlFromGraph(identityPath, graph) {
231
+ let graphEntry = graph.get(identityPath);
232
+ if (!graphEntry)
233
+ throw new Error(`Missing resolved style ${identityPath}`);
234
+ let pathname = graphEntry.resolvedStyle.stableUrlPathname;
235
+ if (resolvedOptions.fingerprintAssets) {
236
+ let emittedStyle = await getOrCreateEmittedStyleFromGraph(styleStore.get(identityPath), graph);
237
+ pathname = formatFingerprintedPathname(graphEntry.resolvedStyle.stableUrlPathname, emittedStyle.fingerprint);
238
+ }
239
+ let timestamp = styleStore.getHmrUpdateTimestamp(graphEntry.resolvedStyle.identityPath);
219
240
  return timestamp ? appendTimestamp(pathname, timestamp) : pathname;
220
241
  }
242
+ async function resolveStyleGraph(rootPath) {
243
+ let resolvedByPath = new Map();
244
+ let rootPaths = Array.isArray(rootPath) ? rootPath : [rootPath];
245
+ let discovered = new Set(rootPaths);
246
+ let queue = [...rootPaths];
247
+ while (queue.length > 0) {
248
+ let frontier = queue;
249
+ queue = [];
250
+ let graphEntries = await mapWithConcurrency(frontier, preloadConcurrency, async (identityPath) => {
251
+ let record = styleStore.get(identityPath);
252
+ let invalidationVersion = record.invalidationVersion;
253
+ let resolvedStyle = await getOrCreateResolvedStyle(record);
254
+ return {
255
+ invalidationVersion,
256
+ resolvedStyle,
257
+ };
258
+ });
259
+ for (let [index, identityPath] of frontier.entries()) {
260
+ let graphEntry = graphEntries[index];
261
+ resolvedByPath.set(identityPath, graphEntry);
262
+ for (let depPath of graphEntry.resolvedStyle.deps) {
263
+ if (discovered.has(depPath))
264
+ continue;
265
+ discovered.add(depPath);
266
+ queue.push(depPath);
267
+ }
268
+ }
269
+ }
270
+ assertNoCircularImports(resolvedByPath, rootPaths);
271
+ return resolvedByPath;
272
+ }
273
+ function assertNoCircularImports(graph, rootPaths) {
274
+ let visited = new Set();
275
+ let path = [];
276
+ let pathIndexByIdentity = new Map();
277
+ function visit(identityPath) {
278
+ let cycleStart = pathIndexByIdentity.get(identityPath);
279
+ if (cycleStart !== undefined) {
280
+ let cycle = [...path.slice(cycleStart), identityPath];
281
+ throw createAssetServerCompilationError(`Circular CSS imports are not supported: ${cycle.join(' -> ')}`, { code: 'EMIT_FAILED' });
282
+ }
283
+ if (visited.has(identityPath))
284
+ return;
285
+ let graphEntry = graph.get(identityPath);
286
+ if (!graphEntry)
287
+ throw new Error(`Missing resolved style ${identityPath}`);
288
+ pathIndexByIdentity.set(identityPath, path.length);
289
+ path.push(identityPath);
290
+ for (let depPath of graphEntry.resolvedStyle.deps)
291
+ visit(depPath);
292
+ path.pop();
293
+ pathIndexByIdentity.delete(identityPath);
294
+ visited.add(identityPath);
295
+ }
296
+ for (let identityPath of rootPaths)
297
+ visit(identityPath);
298
+ }
221
299
  function getHmrUpdatePathnames(identityPath, timestamp) {
222
300
  let resolvedStyles = findHmrUpdateStyles(identityPath, new Set());
223
301
  // Mark update timestamps before invalidating so re-emitted importer stylesheets
@@ -251,7 +329,10 @@ export function createStyleCompiler(options) {
251
329
  }
252
330
  }
253
331
  function getRecordCacheKey(record) {
254
- return `${record.identityPath}\0${record.invalidationVersion}`;
332
+ return getCacheKey(record.identityPath, record.invalidationVersion);
333
+ }
334
+ function getCacheKey(identityPath, version) {
335
+ return `${identityPath}\0${version}`;
255
336
  }
256
337
  function isFresh(record, version) {
257
338
  return record.invalidationVersion === version;
@@ -264,13 +345,12 @@ function getNotModifiedStyle(record, styleStore, options, hasHmrTimestampedDepen
264
345
  let emittedStyle = record.emitted;
265
346
  if (!emittedStyle || options.ifNoneMatch === null)
266
347
  return null;
267
- if (options.requestedFingerprint !== null &&
268
- emittedStyle.fingerprint !== options.requestedFingerprint) {
269
- return null;
270
- }
271
348
  let asset = getEmittedAssetForRequest(emittedStyle, options.isSourceMapRequest);
272
349
  if (!asset)
273
350
  return null;
351
+ if (options.requestedFingerprint !== null && asset.fingerprint !== options.requestedFingerprint) {
352
+ return null;
353
+ }
274
354
  if (!IfNoneMatch.from(options.ifNoneMatch).matches(asset.etag))
275
355
  return null;
276
356
  return { etag: asset.etag, type: 'not-modified' };
@@ -3,11 +3,11 @@ import type { ResolvedStyle } from './resolve.ts';
3
3
  export type EmittedAsset = {
4
4
  content: string;
5
5
  etag: string;
6
+ fingerprint: string;
6
7
  };
7
8
  export type EmittedStyle = {
8
9
  code: EmittedAsset;
9
10
  fingerprint: string | null;
10
- importUrls: string[];
11
11
  sourceMap: EmittedAsset | null;
12
12
  };
13
13
  type EmitResult = {
@@ -18,6 +18,7 @@ type EmitResult = {
18
18
  ok: false;
19
19
  };
20
20
  export declare function emitResolvedStyle(resolvedStyle: ResolvedStyle, options: {
21
+ fingerprintAssets: boolean;
21
22
  getServedFileUrl?(identityPath: string, options: {
22
23
  transform: readonly string[] | null;
23
24
  }): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/emit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,YAAY,GAAG,IAAI,CAAA;CAC/B,CAAA;AAED,KAAK,UAAU,GACX;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,YAAY,CAAA;CACpB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CAAA;AAEL,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;IACP,gBAAgB,CAAC,CACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;QACP,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;KACpC,GACA,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,GACA,OAAO,CAAC,UAAU,CAAC,CAkCrB"}
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/emit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,YAAY,GAAG,IAAI,CAAA;CAC/B,CAAA;AAED,KAAK,UAAU,GACX;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,YAAY,CAAA;CACpB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CAAA;AAEL,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;IACP,iBAAiB,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,CACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;QACP,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;KACpC,GACA,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,GACA,OAAO,CAAC,UAAU,CAAC,CAoCrB"}
@@ -1,30 +1,30 @@
1
1
  import MagicString from 'magic-string';
2
2
  import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
3
- import { hashContent } from '../fingerprint.js';
3
+ import { formatFingerprintedPathname, hashContent } from '../fingerprint.js';
4
4
  import { composeSourceMaps } from '../source-maps.js';
5
5
  export async function emitResolvedStyle(resolvedStyle, options) {
6
6
  try {
7
- let importUrls = await Promise.all(resolvedStyle.deps.map((depPath) => options.getServedUrl(depPath)));
8
7
  let rewriteResult = await rewriteDependencies(resolvedStyle, options);
9
8
  let finalCode = rewriteResult.code;
9
+ let sourceMap = rewriteResult.sourceMap
10
+ ? await createEmittedAsset(rewriteResult.sourceMap)
11
+ : null;
10
12
  if (rewriteResult.sourceMap) {
11
13
  if (options.sourceMaps === 'inline') {
12
14
  let encoded = Buffer.from(rewriteResult.sourceMap).toString('base64');
13
15
  finalCode += `\n/*# sourceMappingURL=data:application/json;base64,${encoded} */`;
14
16
  }
15
17
  else if (options.sourceMaps === 'external') {
16
- finalCode += `\n/*# sourceMappingURL=${await options.getServedUrl(resolvedStyle.identityPath)}.map */`;
18
+ finalCode += `\n/*# sourceMappingURL=${formatFingerprintedPathname(resolvedStyle.stableUrlPathname, options.fingerprintAssets && sourceMap ? sourceMap.fingerprint : null)}.map */`;
17
19
  }
18
20
  }
21
+ let code = await createEmittedAsset(finalCode);
19
22
  return {
20
23
  ok: true,
21
24
  value: {
22
- code: await createEmittedAsset(finalCode),
23
- fingerprint: resolvedStyle.fingerprint,
24
- importUrls,
25
- sourceMap: rewriteResult.sourceMap
26
- ? await createEmittedAsset(rewriteResult.sourceMap)
27
- : null,
25
+ code,
26
+ fingerprint: options.fingerprintAssets ? code.fingerprint : null,
27
+ sourceMap,
28
28
  },
29
29
  };
30
30
  }
@@ -98,9 +98,11 @@ async function getServedFileUrl(options, importerPath, identityPath, request) {
98
98
  }
99
99
  }
100
100
  async function createEmittedAsset(content) {
101
+ let fingerprint = await hashContent(content);
101
102
  return {
102
103
  content,
103
- etag: `W/"${await hashContent(content)}"`,
104
+ etag: `W/"${fingerprint}"`,
105
+ fingerprint,
104
106
  };
105
107
  }
106
108
  function toEmitError(error, identityPath) {