@remix-run/assets 0.6.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 (72) hide show
  1. package/README.md +101 -13
  2. package/dist/assets.d.ts +2 -1
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/lib/asset-server.d.ts +41 -19
  5. package/dist/lib/asset-server.d.ts.map +1 -1
  6. package/dist/lib/asset-server.js +98 -41
  7. package/dist/lib/compilation-error.d.ts +1 -1
  8. package/dist/lib/compilation-error.d.ts.map +1 -1
  9. package/dist/lib/files/compiler.d.ts +1 -1
  10. package/dist/lib/files/compiler.d.ts.map +1 -1
  11. package/dist/lib/files/compiler.js +26 -29
  12. package/dist/lib/files/config.d.ts +6 -0
  13. package/dist/lib/files/config.d.ts.map +1 -1
  14. package/dist/lib/files/config.js +9 -0
  15. package/dist/lib/fingerprint.d.ts +0 -4
  16. package/dist/lib/fingerprint.d.ts.map +1 -1
  17. package/dist/lib/fingerprint.js +0 -4
  18. package/dist/lib/hmr.d.ts +7 -0
  19. package/dist/lib/hmr.d.ts.map +1 -1
  20. package/dist/lib/hmr.js +198 -25
  21. package/dist/lib/routes.d.ts +1 -0
  22. package/dist/lib/routes.d.ts.map +1 -1
  23. package/dist/lib/routes.js +1 -1
  24. package/dist/lib/scripts/compiler.d.ts +8 -2
  25. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  26. package/dist/lib/scripts/compiler.js +186 -36
  27. package/dist/lib/scripts/emit.d.ts +2 -1
  28. package/dist/lib/scripts/emit.d.ts.map +1 -1
  29. package/dist/lib/scripts/emit.js +25 -16
  30. package/dist/lib/scripts/resolve.d.ts +7 -1
  31. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  32. package/dist/lib/scripts/resolve.js +110 -3
  33. package/dist/lib/scripts/specifiers.d.ts +2 -0
  34. package/dist/lib/scripts/specifiers.d.ts.map +1 -0
  35. package/dist/lib/scripts/specifiers.js +9 -0
  36. package/dist/lib/scripts/transform.d.ts +2 -3
  37. package/dist/lib/scripts/transform.d.ts.map +1 -1
  38. package/dist/lib/scripts/transform.js +2 -16
  39. package/dist/lib/styles/compiler.d.ts +0 -1
  40. package/dist/lib/styles/compiler.d.ts.map +1 -1
  41. package/dist/lib/styles/compiler.js +105 -25
  42. package/dist/lib/styles/emit.d.ts +2 -1
  43. package/dist/lib/styles/emit.d.ts.map +1 -1
  44. package/dist/lib/styles/emit.js +12 -10
  45. package/dist/lib/styles/resolve.d.ts +0 -1
  46. package/dist/lib/styles/resolve.d.ts.map +1 -1
  47. package/dist/lib/styles/resolve.js +0 -1
  48. package/dist/lib/styles/transform.d.ts +0 -2
  49. package/dist/lib/styles/transform.d.ts.map +1 -1
  50. package/dist/lib/styles/transform.js +0 -7
  51. package/dist/lib/virtual-store.d.ts +8 -0
  52. package/dist/lib/virtual-store.d.ts.map +1 -0
  53. package/dist/lib/virtual-store.js +100 -0
  54. package/package.json +6 -5
  55. package/src/assets.ts +7 -1
  56. package/src/lib/asset-server.ts +175 -73
  57. package/src/lib/compilation-error.ts +1 -0
  58. package/src/lib/files/compiler.ts +30 -40
  59. package/src/lib/files/config.ts +17 -0
  60. package/src/lib/fingerprint.ts +0 -9
  61. package/src/lib/hmr.ts +210 -26
  62. package/src/lib/routes.ts +1 -1
  63. package/src/lib/scripts/compiler.ts +238 -52
  64. package/src/lib/scripts/emit.ts +34 -19
  65. package/src/lib/scripts/resolve.ts +166 -4
  66. package/src/lib/scripts/specifiers.ts +11 -0
  67. package/src/lib/scripts/transform.ts +4 -23
  68. package/src/lib/styles/compiler.ts +137 -39
  69. package/src/lib/styles/emit.ts +18 -13
  70. package/src/lib/styles/resolve.ts +0 -2
  71. package/src/lib/styles/transform.ts +0 -10
  72. package/src/lib/virtual-store.ts +124 -0
@@ -3,17 +3,19 @@ import * as os from 'node:os';
3
3
  import * as path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { IfNoneMatch } from '@remix-run/headers/if-none-match';
6
+ import { getTsconfig } from 'get-tsconfig';
6
7
  import { createAssetServerCompilationError } from '../compilation-error.js';
7
8
  import { createFileMatcher } from '../file-matcher.js';
8
9
  import { formatFingerprintedPathname, getFingerprintRequestCacheControl, parseFingerprintSuffix, } from '../fingerprint.js';
9
10
  import { emitResolvedModule } from './emit.js';
10
11
  import { normalizeFilePath, resolveFilePath } from '../paths.js';
11
12
  import { resolveModule, resolverExtensionAlias, resolverExtensions, supportedScriptExtensions, } from './resolve.js';
13
+ import { isBareImportSpecifier } from './specifiers.js';
12
14
  import { createModuleStore } from '../module-store.js';
13
15
  import { createTsconfigTransformOptionsResolver, transformModule } from './transform.js';
14
16
  import { ResolverFactory } from 'oxc-resolver';
15
17
  const supportedScriptExtensionSet = new Set(supportedScriptExtensions);
16
- const preloadConcurrency = Math.max(1, Math.min(8, os.availableParallelism() - 1));
18
+ const scriptConcurrency = Math.max(1, Math.min(8, os.availableParallelism() - 1));
17
19
  export function createScriptCompiler(options) {
18
20
  let resolvedOptions = {
19
21
  ...options,
@@ -31,18 +33,21 @@ export function createScriptCompiler(options) {
31
33
  onWatchFilesChange: options.onWatchFilesChange,
32
34
  });
33
35
  let tsconfigTransformOptionsResolver = createTsconfigTransformOptionsResolver();
34
- let resolverFactory = new ResolverFactory({
36
+ let resolverOptions = {
35
37
  aliasFields: [['browser']],
36
38
  conditionNames: ['browser', 'import', 'module', 'default'],
37
39
  extensionAlias: resolverExtensionAlias,
38
40
  extensions: resolverExtensions,
39
41
  mainFields: ['browser', 'module', 'main'],
40
- tsconfig: 'auto',
41
- });
42
+ };
43
+ let resolverFactory = new ResolverFactory({ ...resolverOptions, tsconfig: 'auto' });
44
+ let directoryResolverByTsconfig = new Map();
45
+ let tsconfigByDirectory = new Map();
46
+ let directoryResolutionIdentityByCacheKey = new Map();
42
47
  let resolveInFlightByCacheKey = new Map();
43
48
  let emitInFlightByCacheKey = new Map();
49
+ let hasResolvedScripts = false;
44
50
  let transformArgs = {
45
- buildId: resolvedOptions.buildId ?? null,
46
51
  define: resolvedOptions.define ?? null,
47
52
  externalSet: resolvedOptions.externalSet,
48
53
  isWatchIgnored,
@@ -56,10 +61,13 @@ export function createScriptCompiler(options) {
56
61
  tsconfigTransformOptionsResolver,
57
62
  };
58
63
  let resolveArgs = {
64
+ concurrency: scriptConcurrency,
65
+ isDirectoryResolutionFileIndependent,
59
66
  isAllowed: resolvedOptions.isAllowed,
60
67
  isWatchIgnored,
61
68
  resolveModulePath,
62
69
  resolverFactory,
70
+ resolveDirectorySpecifierIdentity,
63
71
  routes: resolvedOptions.routes,
64
72
  };
65
73
  return {
@@ -76,14 +84,7 @@ export function createScriptCompiler(options) {
76
84
  };
77
85
  },
78
86
  async getPreloadLayers(filePath) {
79
- let resolvedEntries = [];
80
- let seen = new Set();
81
- for (let resolvedModule of (Array.isArray(filePath) ? filePath : [filePath]).map((nextPath) => resolveServedScriptOrThrow(resolveInputFilePath(nextPath)))) {
82
- if (seen.has(resolvedModule.identityPath))
83
- continue;
84
- seen.add(resolvedModule.identityPath);
85
- resolvedEntries.push(resolvedModule.identityPath);
86
- }
87
+ let resolvedEntries = resolveInputScriptRoots(filePath);
87
88
  let visited = new Set(resolvedEntries);
88
89
  let queue = [...resolvedEntries];
89
90
  let layers = [];
@@ -93,8 +94,8 @@ export function createScriptCompiler(options) {
93
94
  let resolvedModules = await getOrCreateResolvedScripts(frontier.map((identityPath) => scriptStore.get(identityPath)));
94
95
  let layer = [];
95
96
  for (let resolvedModule of resolvedModules) {
96
- layer.push(getServedUrlForResolvedScript(resolvedModule));
97
- for (let dep of resolvedModule.deps) {
97
+ layer.push(await getServedUrl(resolvedModule.identityPath));
98
+ for (let dep of resolvedModule.staticDeps) {
98
99
  if (visited.has(dep))
99
100
  continue;
100
101
  visited.add(dep);
@@ -105,10 +106,66 @@ export function createScriptCompiler(options) {
105
106
  }
106
107
  return layers;
107
108
  },
109
+ async getImportMap(filePath) {
110
+ let resolvedEntries = resolveInputScriptRoots(filePath);
111
+ let resolvedEntrySet = new Set(resolvedEntries);
112
+ let visited = new Set();
113
+ let queue = [...resolvedEntries];
114
+ let imports = {};
115
+ let scopes = {};
116
+ while (queue.length > 0) {
117
+ let frontier = queue;
118
+ queue = [];
119
+ let resolvedModules = await getOrCreateResolvedScripts(frontier.map((identityPath) => scriptStore.get(identityPath)));
120
+ for (let resolvedModule of resolvedModules) {
121
+ if (visited.has(resolvedModule.identityPath))
122
+ continue;
123
+ visited.add(resolvedModule.identityPath);
124
+ if (!resolvedEntrySet.has(resolvedModule.identityPath)) {
125
+ addImportMapEntry(imports, resolvedModule.stableUrlPathname, await getServedUrl(resolvedModule.identityPath));
126
+ }
127
+ for (let imported of resolvedModule.imports) {
128
+ let depUrl = await getServedUrl(imported.depPath);
129
+ if (isBareImportSpecifier(imported.specifier)) {
130
+ let scopePathname = imported.scopePathname;
131
+ if (!scopePathname) {
132
+ throw new Error(`Expected import map scope for bare import "${imported.specifier}" in ${resolvedModule.identityPath}`);
133
+ }
134
+ let scopeImports = (scopes[scopePathname] ??= {});
135
+ addImportMapEntry(scopeImports, imported.specifier, depUrl);
136
+ }
137
+ else {
138
+ let browserResolvedSpecifier = resolveImportMapUrlSpecifier(imported.specifier, resolvedModule.stableUrlPathname);
139
+ addImportMapEntry(imports, browserResolvedSpecifier, depUrl);
140
+ }
141
+ }
142
+ for (let dep of resolvedModule.deps) {
143
+ if (!visited.has(dep)) {
144
+ queue.push(dep);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ for (let [scopePathname, scopeImports] of Object.entries(scopes)) {
150
+ if (Object.keys(scopeImports).length === 0) {
151
+ delete scopes[scopePathname];
152
+ }
153
+ }
154
+ return Object.keys(scopes).length > 0 ? { imports, scopes } : { imports };
155
+ },
108
156
  async getHref(filePath) {
109
157
  let resolvedModule = resolveServedScriptOrThrow(resolveInputFilePath(filePath));
110
158
  return getServedUrl(resolvedModule.identityPath);
111
159
  },
160
+ async resolveSpecifierFromRoot(specifier) {
161
+ let importerPath = path.join(resolvedOptions.rootDir, '__remix_virtual_entry__.js');
162
+ let resolutionResult = await resolverFactory.resolveFileAsync(importerPath, specifier);
163
+ if (resolutionResult.error || !resolutionResult.path) {
164
+ throw createAssetServerCompilationError(`Failed to resolve browser module "${specifier}" from asset server root.`, { code: 'IMPORT_RESOLUTION_FAILED' });
165
+ }
166
+ let resolvedModule = resolveServedScriptOrThrow(resolutionResult.path);
167
+ return getServedUrl(resolvedModule.identityPath);
168
+ },
112
169
  async classifyHmrFileEvent(filePath, event) {
113
170
  let normalizedFilePath = normalizeFilePath(filePath);
114
171
  if (isWatchIgnored(normalizedFilePath))
@@ -116,7 +173,20 @@ export function createScriptCompiler(options) {
116
173
  let timestamp = Date.now();
117
174
  let previousResolvedModule = scriptStore.getLastResolved(normalizedFilePath);
118
175
  let updatePathname = previousResolvedModule?.stableUrlPathname;
176
+ let resolutionMetadataChanged = isPackageJsonPath(normalizedFilePath) || isTsconfigPath(normalizedFilePath);
119
177
  invalidateScriptFileEvent(normalizedFilePath, event);
178
+ if (resolutionMetadataChanged && hasResolvedScripts) {
179
+ let hmrUpdate = [
180
+ {
181
+ accepted: false,
182
+ filePath: normalizedFilePath,
183
+ path: normalizedFilePath,
184
+ timestamp,
185
+ },
186
+ ];
187
+ resolvedOptions.hmr?.send(hmrUpdate);
188
+ return hmrUpdate;
189
+ }
120
190
  let resolvedModule = event === 'change' && updatePathname
121
191
  ? await tryGetOrCreateResolvedScript(scriptStore.get(normalizedFilePath))
122
192
  : undefined;
@@ -160,6 +230,11 @@ export function createScriptCompiler(options) {
160
230
  return;
161
231
  if (shouldClearResolverCacheForFileEvent(normalizedFilePath, event)) {
162
232
  resolverFactory.clearCache();
233
+ for (let directoryResolver of directoryResolverByTsconfig.values()) {
234
+ directoryResolver.clearCache();
235
+ }
236
+ tsconfigByDirectory.clear();
237
+ directoryResolutionIdentityByCacheKey.clear();
163
238
  }
164
239
  if (isTsconfigPath(normalizedFilePath)) {
165
240
  tsconfigTransformOptionsResolver.clear();
@@ -172,6 +247,44 @@ export function createScriptCompiler(options) {
172
247
  }
173
248
  scriptStore.invalidateForFileEvent(normalizedFilePath, event);
174
249
  }
250
+ function isDirectoryResolutionFileIndependent(directory) {
251
+ return getDirectoryTsconfig(directory).fileIndependent;
252
+ }
253
+ function getDirectoryTsconfig(directory) {
254
+ let existing = tsconfigByDirectory.get(directory);
255
+ if (existing)
256
+ return existing;
257
+ let tsconfig = getTsconfig(directory);
258
+ let result = {
259
+ fileIndependent: !tsconfig?.config.references?.length,
260
+ path: tsconfig?.path ?? null,
261
+ };
262
+ tsconfigByDirectory.set(directory, result);
263
+ return result;
264
+ }
265
+ async function resolveDirectorySpecifierIdentity(directory, specifier) {
266
+ let cacheKey = `${directory}\0${specifier}`;
267
+ let existing = directoryResolutionIdentityByCacheKey.get(cacheKey);
268
+ if (existing)
269
+ return existing;
270
+ let promise = (async () => {
271
+ let tsconfigPath = getDirectoryTsconfig(directory).path;
272
+ let directoryResolver = directoryResolverByTsconfig.get(tsconfigPath);
273
+ if (!directoryResolver) {
274
+ directoryResolver = new ResolverFactory({
275
+ ...resolverOptions,
276
+ tsconfig: tsconfigPath ? { configFile: tsconfigPath } : undefined,
277
+ });
278
+ directoryResolverByTsconfig.set(tsconfigPath, directoryResolver);
279
+ }
280
+ let result = await directoryResolver.async(directory, specifier);
281
+ if (!result.path || !path.isAbsolute(result.path))
282
+ return null;
283
+ return resolveModulePath(normalizeFilePath(result.path))?.identityPath ?? null;
284
+ })();
285
+ directoryResolutionIdentityByCacheKey.set(cacheKey, promise);
286
+ return promise;
287
+ }
175
288
  function resolveServedScriptOrThrow(absolutePath) {
176
289
  let resolvedModule = resolveModulePath(absolutePath);
177
290
  if (!resolvedModule) {
@@ -187,6 +300,18 @@ export function createScriptCompiler(options) {
187
300
  }
188
301
  return resolvedModule;
189
302
  }
303
+ function resolveInputScriptRoots(filePath) {
304
+ let resolvedEntries = [];
305
+ let seen = new Set();
306
+ for (let nextPath of Array.isArray(filePath) ? filePath : [filePath]) {
307
+ let resolvedModule = resolveServedScriptOrThrow(resolveInputFilePath(nextPath));
308
+ if (seen.has(resolvedModule.identityPath))
309
+ continue;
310
+ seen.add(resolvedModule.identityPath);
311
+ resolvedEntries.push(resolvedModule.identityPath);
312
+ }
313
+ return resolvedEntries;
314
+ }
190
315
  function getNotModifiedScript(record, options) {
191
316
  if (hasHmrTimestampedDependency(record.resolved)) {
192
317
  return null;
@@ -202,7 +327,7 @@ export function createScriptCompiler(options) {
202
327
  return getNotModifiedResult(record.staleEmitted, options);
203
328
  }
204
329
  async function getOrCreateResolvedScripts(records) {
205
- return mapWithConcurrency(records, preloadConcurrency, (record) => getOrCreateResolvedScript(record));
330
+ return mapWithConcurrency(records, scriptConcurrency, (record) => getOrCreateResolvedScript(record));
206
331
  }
207
332
  async function getOrCreateResolvedScript(record) {
208
333
  if (record.resolved && scriptStore.isResolvedFresh(record))
@@ -230,6 +355,7 @@ export function createScriptCompiler(options) {
230
355
  resolveModuleResult.tracking,
231
356
  ]);
232
357
  }
358
+ hasResolvedScripts = true;
233
359
  return resolveModuleResult.value;
234
360
  })();
235
361
  resolveInFlightByCacheKey.set(cacheKey, promise);
@@ -281,10 +407,12 @@ export function createScriptCompiler(options) {
281
407
  let promise = (async () => {
282
408
  let startedVersion = record.invalidationVersion;
283
409
  let resolvedModule = await getOrCreateResolvedScript(record);
410
+ await resolveScriptGraph(resolvedModule);
284
411
  let emitResolvedModuleResult = await emitResolvedModule(resolvedModule, {
412
+ fingerprintAssets: resolvedOptions.fingerprintAssets,
413
+ getHmrImportTimestamp,
285
414
  getServedUrl,
286
415
  getStableUrl,
287
- getHmrImportTimestamp,
288
416
  hmrClientPathname: resolvedOptions.hmr?.clientPathname,
289
417
  sourceMaps: resolvedOptions.sourceMaps,
290
418
  });
@@ -306,11 +434,33 @@ export function createScriptCompiler(options) {
306
434
  }
307
435
  }
308
436
  }
309
- async function getServedUrl(identityPath) {
310
- return getServedUrlForResolvedScript(await getOrCreateResolvedScript(scriptStore.get(identityPath)));
437
+ async function resolveScriptGraph(root) {
438
+ let visited = new Set([root.identityPath]);
439
+ let queue = [...root.deps];
440
+ while (queue.length > 0) {
441
+ let frontier = queue;
442
+ queue = [];
443
+ let resolvedModules = await getOrCreateResolvedScripts(frontier
444
+ .filter((identityPath) => !visited.has(identityPath))
445
+ .map((identityPath) => scriptStore.get(identityPath)));
446
+ for (let resolvedModule of resolvedModules) {
447
+ if (visited.has(resolvedModule.identityPath))
448
+ continue;
449
+ visited.add(resolvedModule.identityPath);
450
+ for (let dep of resolvedModule.deps) {
451
+ if (!visited.has(dep))
452
+ queue.push(dep);
453
+ }
454
+ }
455
+ }
311
456
  }
312
- function getServedUrlForResolvedScript(resolvedModule) {
313
- return formatFingerprintedPathname(resolvedModule.stableUrlPathname, resolvedOptions.fingerprintAssets ? resolvedModule.fingerprint : null);
457
+ async function getServedUrl(identityPath) {
458
+ let resolvedModule = await getOrCreateResolvedScript(scriptStore.get(identityPath));
459
+ if (!resolvedOptions.fingerprintAssets) {
460
+ return resolvedModule.stableUrlPathname;
461
+ }
462
+ let emittedModule = await getOrCreateEmittedScript(scriptStore.get(identityPath));
463
+ return formatFingerprintedPathname(resolvedModule.stableUrlPathname, emittedModule.fingerprint);
314
464
  }
315
465
  function getStableUrl(identityPath) {
316
466
  let stableUrlPathname = resolvedOptions.routes.toUrlPathname(identityPath);
@@ -335,7 +485,8 @@ export function createScriptCompiler(options) {
335
485
  return [
336
486
  {
337
487
  accepted: true,
338
- acceptedPath: updatePathname,
488
+ acceptedFilePath: resolvedModule.identityPath,
489
+ acceptedUrlPathname: updatePathname,
339
490
  filePath: resolvedModule.identityPath,
340
491
  path: updatePathname,
341
492
  timestamp,
@@ -347,7 +498,8 @@ export function createScriptCompiler(options) {
347
498
  if (sourceFilePath !== undefined && boundaries) {
348
499
  return dedupeHmrBoundaries(boundaries).map(({ acceptedModule, boundaryModule }) => ({
349
500
  accepted: true,
350
- acceptedPath: acceptedModule.stableUrlPathname,
501
+ acceptedFilePath: acceptedModule.identityPath,
502
+ acceptedUrlPathname: acceptedModule.stableUrlPathname,
351
503
  filePath: sourceFilePath,
352
504
  path: boundaryModule.stableUrlPathname,
353
505
  timestamp,
@@ -409,6 +561,14 @@ export function createScriptCompiler(options) {
409
561
  return resolvedOptions.watchIgnoreMatchers.some((matcher) => matcher(filePath));
410
562
  }
411
563
  }
564
+ function resolveImportMapUrlSpecifier(specifier, importerUrlPathname) {
565
+ return new URL(specifier, `http://localhost${importerUrlPathname}`).pathname;
566
+ }
567
+ function addImportMapEntry(imports, specifier, url) {
568
+ if (specifier === url)
569
+ return;
570
+ imports[specifier] = url;
571
+ }
412
572
  function dedupeHmrBoundaries(boundaries) {
413
573
  let seen = new Set();
414
574
  let result = [];
@@ -430,13 +590,12 @@ function isFresh(record, version) {
430
590
  function getNotModifiedResult(emittedModule, options) {
431
591
  if (!emittedModule || options.ifNoneMatch === null)
432
592
  return null;
433
- if (options.requestedFingerprint !== null &&
434
- emittedModule.fingerprint !== options.requestedFingerprint) {
435
- return null;
436
- }
437
593
  let asset = getEmittedAssetForRequest(emittedModule, options.isSourceMapRequest);
438
594
  if (!asset)
439
595
  return null;
596
+ if (options.requestedFingerprint !== null && asset.fingerprint !== options.requestedFingerprint) {
597
+ return null;
598
+ }
440
599
  if (!IfNoneMatch.from(options.ifNoneMatch).matches(asset.etag))
441
600
  return null;
442
601
  return { type: 'not-modified', etag: asset.etag };
@@ -548,15 +707,6 @@ function resolveActualPath(identityPath) {
548
707
  throw error;
549
708
  }
550
709
  }
551
- function isBareImportSpecifier(specifier) {
552
- return (!specifier.startsWith('./') &&
553
- !specifier.startsWith('../') &&
554
- !specifier.startsWith('/') &&
555
- !specifier.startsWith('file:') &&
556
- !specifier.startsWith('data:') &&
557
- !specifier.startsWith('http://') &&
558
- !specifier.startsWith('https://'));
559
- }
560
710
  function isNoEntityError(error) {
561
711
  return (error instanceof Error &&
562
712
  'code' in error &&
@@ -3,11 +3,11 @@ import type { AssetServerCompilationError } from '../compilation-error.ts';
3
3
  export type EmittedAsset = {
4
4
  content: string;
5
5
  etag: string;
6
+ fingerprint: string;
6
7
  };
7
8
  export type EmittedModule = {
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
  error: AssetServerCompilationError;
19
19
  };
20
20
  export declare function emitResolvedModule(resolvedModule: ResolvedModule, options: {
21
+ fingerprintAssets: boolean;
21
22
  getHmrImportTimestamp(identityPath: string): number | null;
22
23
  getServedUrl(identityPath: string): Promise<string>;
23
24
  getStableUrl(identityPath: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/emit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAE1E,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,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,aAAa,CAAA;CACrB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CAAA;AAQL,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE;IACP,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1D,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,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/scripts/emit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAE1E,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,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,aAAa,CAAA;CACrB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CAAA;AAQL,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE;IACP,iBAAiB,EAAE,OAAO,CAAA;IAC1B,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1D,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,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 emitResolvedModule(resolvedModule, options) {
6
6
  try {
7
- let importUrls = await Promise.all(resolvedModule.deps.map((depPath) => options.getServedUrl(depPath)));
8
7
  let rewriteResult = await rewriteImports(resolvedModule, options);
9
8
  let finalCode = prependHmrContext(resolvedModule, rewriteResult.code, options);
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(resolvedModule.identityPath)}.map`;
18
+ finalCode += `\n//# sourceMappingURL=${formatFingerprintedPathname(resolvedModule.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: resolvedModule.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
  }
@@ -37,21 +37,28 @@ export async function emitResolvedModule(resolvedModule, options) {
37
37
  }
38
38
  async function rewriteImports(resolvedModule, options) {
39
39
  let rewrittenSource = new MagicString(resolvedModule.rawCode);
40
+ let changed = false;
40
41
  for (let imported of resolvedModule.imports) {
41
- let url = await options.getServedUrl(imported.depPath);
42
42
  let hmrImportTimestamp = options.getHmrImportTimestamp(imported.depPath);
43
+ let replacementSpecifier = imported.specifier;
43
44
  if (hmrImportTimestamp !== null) {
44
- url = addTimestampQuery(url, hmrImportTimestamp);
45
+ replacementSpecifier = addTimestampQuery(await options.getServedUrl(imported.depPath), hmrImportTimestamp);
45
46
  }
46
- rewrittenSource.overwrite(imported.start, imported.end, imported.quote ? `${imported.quote}${url}${imported.quote}` : url);
47
+ else if (imported.compiledSpecifier === imported.specifier) {
48
+ continue;
49
+ }
50
+ rewrittenSource.overwrite(imported.start, imported.end, imported.quote
51
+ ? `${imported.quote}${replacementSpecifier}${imported.quote}`
52
+ : replacementSpecifier);
53
+ changed = true;
47
54
  }
48
55
  for (let acceptedDep of resolvedModule.hmr.acceptedDeps) {
49
56
  let url = options.getStableUrl(acceptedDep.depPath);
50
57
  rewrittenSource.overwrite(acceptedDep.start, acceptedDep.end, acceptedDep.quote ? `${acceptedDep.quote}${url}${acceptedDep.quote}` : url);
58
+ changed = true;
51
59
  }
52
- let code = rewrittenSource.toString();
53
- let sourceMap = resolvedModule.sourceMap &&
54
- (resolvedModule.imports.length > 0 || resolvedModule.hmr.acceptedDeps.length > 0)
60
+ let code = changed ? rewrittenSource.toString() : resolvedModule.rawCode;
61
+ let sourceMap = resolvedModule.sourceMap && changed
55
62
  ? composeSourceMaps(rewrittenSource.generateMap({ hires: true }).toString(), resolvedModule.sourceMap)
56
63
  : resolvedModule.sourceMap;
57
64
  return { code, sourceMap };
@@ -67,9 +74,11 @@ function prependHmrContext(resolvedModule, code, options) {
67
74
  code);
68
75
  }
69
76
  async function createEmittedAsset(content) {
77
+ let fingerprint = await hashContent(content);
70
78
  return {
71
79
  content,
72
- etag: `W/"${await hashContent(content)}"`,
80
+ etag: `W/"${fingerprint}"`,
81
+ fingerprint,
73
82
  };
74
83
  }
75
84
  function toEmitError(error, identityPath) {
@@ -13,15 +13,17 @@ export declare const resolverExtensionAlias: {
13
13
  export declare const resolverExtensions: string[];
14
14
  export declare const supportedScriptExtensions: string[];
15
15
  type ResolvedImport = {
16
+ compiledSpecifier: string;
16
17
  depPath: string;
17
18
  end: number;
18
19
  quote?: '"' | "'" | '`';
20
+ scopePathname?: string;
21
+ specifier: string;
19
22
  start: number;
20
23
  };
21
24
  type ResolvedHmrAcceptedDependency = ResolvedImport;
22
25
  export type ResolvedModule = {
23
26
  deps: string[];
24
- fingerprint: string | null;
25
27
  hmr: Omit<TransformedModule['hmr'], 'acceptedDeps'> & {
26
28
  acceptedDeps: ResolvedHmrAcceptedDependency[];
27
29
  };
@@ -31,6 +33,7 @@ export type ResolvedModule = {
31
33
  rawCode: string;
32
34
  resolvedPath: string;
33
35
  sourceMap: string | null;
36
+ staticDeps: string[];
34
37
  stableUrlPathname: string;
35
38
  };
36
39
  type ResolveResult = {
@@ -43,10 +46,13 @@ type ResolveResult = {
43
46
  error: AssetServerCompilationError;
44
47
  });
45
48
  export type ResolveArgs = {
49
+ concurrency: number;
50
+ isDirectoryResolutionFileIndependent(directory: string): boolean;
46
51
  isAllowed(absolutePath: string): boolean;
47
52
  isWatchIgnored(filePath: string): boolean;
48
53
  resolveModulePath(absolutePath: string): ResolveModuleResult | null;
49
54
  resolverFactory: ResolverFactory;
55
+ resolveDirectorySpecifierIdentity(directory: string, specifier: string): Promise<string | null>;
50
56
  routes: CompiledRoutes;
51
57
  };
52
58
  export declare function resolveModule(record: ScriptRecord, transformed: TransformedModule, args: ResolveArgs): Promise<ResolveResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAM1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAE9C,KAAK,YAAY,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AAElF,eAAO,MAAM,sBAAsB;;;;CAIC,CAAA;AAEpC,eAAO,MAAM,kBAAkB,UAAiD,CAAA;AAChF,eAAO,MAAM,yBAAyB,UAAiD,CAAA;AAGvF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,6BAA6B,GAAG,cAAc,CAAA;AAYnD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,GAAG;QACpD,YAAY,EAAE,6BAA6B,EAAE,CAAA;KAC9C,CAAA;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,cAAc,CAAA;CACtB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CACJ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAA;IACnE,eAAe,EAAE,eAAe,CAAA;IAChC,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAaD,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,iBAAiB,EAC9B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CA2PxB"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAM1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAG9C,KAAK,YAAY,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AAElF,eAAO,MAAM,sBAAsB;;;;CAIC,CAAA;AAEpC,eAAO,MAAM,kBAAkB,UAAiD,CAAA;AAChF,eAAO,MAAM,yBAAyB,UAAiD,CAAA;AAGvF,KAAK,cAAc,GAAG;IACpB,iBAAiB,EAAE,MAAM,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,6BAA6B,GAAG,cAAc,CAAA;AAmBnD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,GAAG;QACpD,YAAY,EAAE,6BAA6B,EAAE,CAAA;KAC9C,CAAA;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,cAAc,CAAA;CACtB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CACJ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IAChE,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAA;IACnE,eAAe,EAAE,eAAe,CAAA;IAChC,iCAAiC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC/F,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAaD,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,iBAAiB,EAC9B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CAsSxB"}