@remix-run/assets 0.4.4 → 0.6.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 (83) hide show
  1. package/README.md +331 -72
  2. package/dist/assets.d.ts +4 -1
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/assets.js +2 -2
  5. package/dist/lib/access.d.ts +35 -4
  6. package/dist/lib/access.d.ts.map +1 -1
  7. package/dist/lib/access.js +332 -11
  8. package/dist/lib/asset-server.d.ts +138 -11
  9. package/dist/lib/asset-server.d.ts.map +1 -1
  10. package/dist/lib/asset-server.js +281 -30
  11. package/dist/lib/compilation-error.d.ts +1 -1
  12. package/dist/lib/compilation-error.d.ts.map +1 -1
  13. package/dist/lib/file-matcher.js +1 -1
  14. package/dist/lib/files/compiler.d.ts.map +1 -1
  15. package/dist/lib/files/compiler.js +9 -8
  16. package/dist/lib/files/config.js +1 -1
  17. package/dist/lib/hmr.d.ts +37 -0
  18. package/dist/lib/hmr.d.ts.map +1 -0
  19. package/dist/lib/hmr.js +357 -0
  20. package/dist/lib/injected-packages.d.ts +3 -2
  21. package/dist/lib/injected-packages.d.ts.map +1 -1
  22. package/dist/lib/injected-packages.js +43 -17
  23. package/dist/lib/inspection.d.ts +39 -0
  24. package/dist/lib/inspection.d.ts.map +1 -0
  25. package/dist/lib/inspection.js +160 -0
  26. package/dist/lib/loaders.d.ts +57 -0
  27. package/dist/lib/loaders.d.ts.map +1 -0
  28. package/dist/lib/loaders.js +1 -0
  29. package/dist/lib/module-store.d.ts +24 -0
  30. package/dist/lib/module-store.d.ts.map +1 -1
  31. package/dist/lib/module-store.js +136 -11
  32. package/dist/lib/routes.d.ts +11 -3
  33. package/dist/lib/routes.d.ts.map +1 -1
  34. package/dist/lib/routes.js +124 -80
  35. package/dist/lib/scripts/compiler.d.ts +24 -1
  36. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  37. package/dist/lib/scripts/compiler.js +183 -29
  38. package/dist/lib/scripts/conditions.d.ts +2 -0
  39. package/dist/lib/scripts/conditions.d.ts.map +1 -0
  40. package/dist/lib/scripts/conditions.js +1 -0
  41. package/dist/lib/scripts/emit.d.ts +3 -0
  42. package/dist/lib/scripts/emit.d.ts.map +1 -1
  43. package/dist/lib/scripts/emit.js +24 -5
  44. package/dist/lib/scripts/resolve.d.ts +4 -0
  45. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  46. package/dist/lib/scripts/resolve.js +75 -10
  47. package/dist/lib/scripts/transform.d.ts +9 -0
  48. package/dist/lib/scripts/transform.d.ts.map +1 -1
  49. package/dist/lib/scripts/transform.js +222 -18
  50. package/dist/lib/source-maps.js +1 -1
  51. package/dist/lib/styles/compiler.d.ts +14 -1
  52. package/dist/lib/styles/compiler.d.ts.map +1 -1
  53. package/dist/lib/styles/compiler.js +78 -14
  54. package/dist/lib/styles/emit.js +4 -4
  55. package/dist/lib/styles/resolve.d.ts.map +1 -1
  56. package/dist/lib/styles/resolve.js +16 -15
  57. package/dist/lib/styles/transform.js +5 -5
  58. package/dist/lib/target.d.ts +1 -1
  59. package/dist/lib/target.d.ts.map +1 -1
  60. package/dist/lib/watch.js +1 -1
  61. package/dist/types/hmr.d.ts +36 -0
  62. package/package.json +16 -11
  63. package/src/assets.ts +4 -1
  64. package/src/lib/access.ts +445 -11
  65. package/src/lib/asset-server.ts +466 -27
  66. package/src/lib/compilation-error.ts +4 -3
  67. package/src/lib/files/compiler.ts +9 -5
  68. package/src/lib/hmr.ts +397 -0
  69. package/src/lib/injected-packages.ts +52 -16
  70. package/src/lib/inspection.ts +229 -0
  71. package/src/lib/loaders.ts +80 -0
  72. package/src/lib/module-store.ts +190 -9
  73. package/src/lib/routes.ts +158 -126
  74. package/src/lib/scripts/compiler.ts +248 -24
  75. package/src/lib/scripts/conditions.ts +1 -0
  76. package/src/lib/scripts/emit.ts +50 -5
  77. package/src/lib/scripts/resolve.ts +129 -7
  78. package/src/lib/scripts/transform.ts +290 -19
  79. package/src/lib/styles/compiler.ts +108 -8
  80. package/src/lib/styles/emit.ts +1 -1
  81. package/src/lib/styles/resolve.ts +19 -15
  82. package/src/lib/styles/transform.ts +2 -2
  83. package/src/types/hmr.d.ts +36 -0
@@ -1,10 +1,41 @@
1
- type AccessPolicy = {
1
+ /** Access-policy result for an inspected asset file. */
2
+ export interface AssetAccessDetails {
3
+ /** Whether the asset server may serve the file. */
4
+ allowed: boolean;
5
+ /** The first configured rule that allowed the file, when one matched. */
6
+ allowedBy?: AssetAccessRule;
7
+ /** The first matching `denyFiles` pattern, when access was denied. */
8
+ deniedBy?: string;
9
+ }
10
+ /** Rule that allows an inspected asset file to be served. */
11
+ export type AssetAccessRule =
12
+ /** A matching `allowFiles` entry. */
13
+ {
14
+ kind: 'file';
15
+ value: string;
16
+ }
17
+ /** A runtime file provided internally by the asset server. */
18
+ | {
19
+ kind: 'injected';
20
+ value: string;
21
+ }
22
+ /** A matching `allowPackages` entry. */
23
+ | {
24
+ kind: 'package';
25
+ value: string;
26
+ };
27
+ export type AccessPolicy = {
28
+ getAllowedPackageRoots(): readonly string[];
29
+ getPackageWatchDirectories(): readonly string[];
30
+ handleFileEvent(filePath: string): void;
31
+ inspect(filePath: string): AssetAccessDetails;
2
32
  isAllowed(filePath: string): boolean;
3
33
  };
4
34
  export declare function createAccessPolicy(options: {
5
- allow: readonly string[];
6
- deny?: readonly string[];
35
+ allowFiles: readonly string[];
36
+ allowPackages?: readonly string[];
37
+ denyFiles?: readonly string[];
38
+ packageSearchRoots?: readonly string[];
7
39
  rootDir: string;
8
40
  }): AccessPolicy;
9
- export {};
10
41
  //# sourceMappingURL=access.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/lib/access.ts"],"names":[],"mappings":"AAGA,KAAK,YAAY,GAAG;IAClB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CACrC,CAAA;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,YAAY,CAcf"}
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/lib/access.ts"],"names":[],"mappings":"AAMA,wDAAwD;AACxD,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAA;IAChB,yEAAyE;IACzE,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,6DAA6D;AAC7D,MAAM,MAAM,eAAe;AACzB,qCAAqC;AACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACjC,8DAA8D;GAC5D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACrC,wCAAwC;GACtC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtC,MAAM,MAAM,YAAY,GAAG;IACzB,sBAAsB,IAAI,SAAS,MAAM,EAAE,CAAA;IAC3C,0BAA0B,IAAI,SAAS,MAAM,EAAE,CAAA;IAC/C,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAAA;IAC7C,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CACrC,CAAA;AAcD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7B,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7B,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,YAAY,CAoFf"}
@@ -1,17 +1,338 @@
1
- import { createFileMatcher } from "./file-matcher.js";
2
- import { isInjectedPackageFilePath } from "./injected-packages.js";
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { createFileMatcher } from './file-matcher.js';
4
+ import { isInjectedPackageFilePath } from './injected-packages.js';
5
+ import { normalizeFilePath } from './paths.js';
6
+ const packageStateFileNames = new Set([
7
+ 'bun.lock',
8
+ 'bun.lockb',
9
+ 'npm-shrinkwrap.json',
10
+ 'package-lock.json',
11
+ 'pnpm-lock.yaml',
12
+ 'pnpm-workspace.yaml',
13
+ 'yarn.lock',
14
+ ]);
15
+ const packageManagerRootFileNames = packageStateFileNames;
16
+ const packageNamePartPattern = /^[A-Za-z0-9._~-]+$/;
3
17
  export function createAccessPolicy(options) {
4
- let allowMatchers = options.allow.map((pattern) => createFileMatcher(pattern, options.rootDir));
5
- let denyMatchers = (options.deny ?? []).map((pattern) => createFileMatcher(pattern, options.rootDir));
18
+ let allowMatchers = options.allowFiles.map((pattern) => ({
19
+ matcher: createFileMatcher(pattern, options.rootDir),
20
+ pattern,
21
+ }));
22
+ let allowPackageNames = normalizePackageNames(options.allowPackages, 'allowPackages');
23
+ let denyMatchers = (options.denyFiles ?? []).map((pattern) => ({
24
+ matcher: createFileMatcher(pattern, options.rootDir),
25
+ pattern,
26
+ }));
27
+ let packageSearchRoots = [options.rootDir, ...(options.packageSearchRoots ?? [])];
28
+ let packageRootPaths = createPackageRootPaths({
29
+ allowPackageNames,
30
+ searchRoots: packageSearchRoots,
31
+ });
32
+ let allowPackageRootPathTrie = createPackageRootPathTrie(packageRootPaths);
33
+ let packageStateDirectories = allowPackageNames.size === 0 ? [] : getPackageStateDirectories(packageSearchRoots);
34
+ let packageRootsDirty = false;
35
+ function refreshPackageRootPathTries() {
36
+ if (!packageRootsDirty)
37
+ return;
38
+ packageRootPaths = createPackageRootPaths({
39
+ allowPackageNames,
40
+ searchRoots: packageSearchRoots,
41
+ });
42
+ allowPackageRootPathTrie = createPackageRootPathTrie(packageRootPaths);
43
+ packageRootsDirty = false;
44
+ }
45
+ function getAllowedPackageName(filePath) {
46
+ if (allowPackageNames.size === 0)
47
+ return undefined;
48
+ refreshPackageRootPathTries();
49
+ return getPackageNameFromRootPathTrie(filePath, allowPackageRootPathTrie);
50
+ }
51
+ function inspect(filePath) {
52
+ if (isInjectedPackageFilePath(filePath)) {
53
+ return { allowed: true, allowedBy: { kind: 'injected', value: '@remix-run/assets' } };
54
+ }
55
+ let allowedBy;
56
+ let allowMatch = allowMatchers.find(({ matcher }) => matcher(filePath));
57
+ if (allowMatch) {
58
+ allowedBy = { kind: 'file', value: allowMatch.pattern };
59
+ }
60
+ else {
61
+ let packageName = getAllowedPackageName(filePath);
62
+ if (packageName !== undefined) {
63
+ allowedBy = { kind: 'package', value: packageName };
64
+ }
65
+ }
66
+ if (!allowedBy)
67
+ return { allowed: false };
68
+ let denyMatch = denyMatchers.find(({ matcher }) => matcher(filePath));
69
+ if (denyMatch) {
70
+ return { allowed: false, allowedBy, deniedBy: denyMatch.pattern };
71
+ }
72
+ return { allowed: true, allowedBy };
73
+ }
6
74
  return {
75
+ getAllowedPackageRoots() {
76
+ refreshPackageRootPathTries();
77
+ return [...packageRootPaths.keys()];
78
+ },
79
+ getPackageWatchDirectories() {
80
+ if (allowPackageNames.size === 0)
81
+ return [];
82
+ return packageStateDirectories;
83
+ },
84
+ handleFileEvent(filePath) {
85
+ if (allowPackageNames.size === 0)
86
+ return;
87
+ if (!isPackageStateFileEvent(filePath, packageStateDirectories))
88
+ return;
89
+ packageRootsDirty = true;
90
+ },
91
+ inspect,
7
92
  isAllowed(filePath) {
8
- if (isInjectedPackageFilePath(filePath))
9
- return true;
10
- if (!allowMatchers.some((matcher) => matcher(filePath)))
11
- return false;
12
- if (denyMatchers.length > 0 && denyMatchers.some((matcher) => matcher(filePath)))
13
- return false;
14
- return true;
93
+ return inspect(filePath).allowed;
15
94
  },
16
95
  };
17
96
  }
97
+ function normalizePackageNames(packageOption, optionName) {
98
+ let packageNames = new Set();
99
+ for (let packageName of packageOption ?? []) {
100
+ if (typeof packageName !== 'string') {
101
+ throw new TypeError(`${optionName} values must be strings`);
102
+ }
103
+ let normalizedPackageName = packageName.trim();
104
+ if (!isValidPackageName(normalizedPackageName)) {
105
+ throw new TypeError(`${optionName} values must be package names. Received "${packageName}".`);
106
+ }
107
+ packageNames.add(normalizedPackageName);
108
+ }
109
+ return packageNames;
110
+ }
111
+ function validatePackageName(packageName, message) {
112
+ if (!isValidPackageName(packageName)) {
113
+ throw new TypeError(message);
114
+ }
115
+ }
116
+ function createPackageRootPaths(options) {
117
+ let allowPackageRootPaths = new Map();
118
+ let allowQueue = [];
119
+ let seenAllowedPackageRoots = new Set();
120
+ let searchRoots = normalizePackageSearchRoots(options.searchRoots);
121
+ for (let packageName of options.allowPackageNames) {
122
+ let foundPackage = false;
123
+ for (let searchRoot of searchRoots) {
124
+ let packageJsonPath = findPackageJsonPath(packageName, searchRoot);
125
+ if (packageJsonPath === null)
126
+ continue;
127
+ foundPackage = true;
128
+ allowQueue.push({ packageJsonPath, packageName });
129
+ }
130
+ if (!foundPackage) {
131
+ throw new TypeError(`Could not resolve allowed package "${packageName}".`);
132
+ }
133
+ }
134
+ while (allowQueue.length > 0) {
135
+ let { packageJsonPath, packageName } = allowQueue.shift();
136
+ let packageRootPath = normalizeFilePath(path.dirname(packageJsonPath));
137
+ if (seenAllowedPackageRoots.has(packageRootPath))
138
+ continue;
139
+ seenAllowedPackageRoots.add(packageRootPath);
140
+ let packageJson = readPackageJson(packageJsonPath);
141
+ allowPackageRootPaths.set(packageRootPath, packageName);
142
+ for (let dependencyName of Object.keys(packageJson.dependencies ?? {})) {
143
+ validatePackageName(dependencyName, `Dependency "${dependencyName}" from ${packageJsonPath} must be a package name.`);
144
+ let dependencyPackageJsonPath = findPackageJsonPath(dependencyName, packageRootPath);
145
+ if (dependencyPackageJsonPath === null) {
146
+ throw new TypeError(`Could not resolve dependency "${dependencyName}" from ${packageJsonPath}.`);
147
+ }
148
+ allowQueue.push({
149
+ packageJsonPath: dependencyPackageJsonPath,
150
+ packageName: dependencyName,
151
+ });
152
+ }
153
+ for (let dependencyName of Object.keys(packageJson.optionalDependencies ?? {})) {
154
+ validatePackageName(dependencyName, `Optional dependency "${dependencyName}" from ${packageJsonPath} must be a package name.`);
155
+ let dependencyPackageJsonPath = findPackageJsonPath(dependencyName, packageRootPath);
156
+ if (dependencyPackageJsonPath !== null) {
157
+ allowQueue.push({
158
+ packageJsonPath: dependencyPackageJsonPath,
159
+ packageName: dependencyName,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ return allowPackageRootPaths;
165
+ }
166
+ function createPackageRootPathTrie(packageRootPaths) {
167
+ let rootNode = createPackageRootPathTrieNode();
168
+ for (let [packageRootPath, packageName] of packageRootPaths) {
169
+ let node = rootNode;
170
+ for (let segment of getFilePathSegments(packageRootPath)) {
171
+ let childNode = node.children.get(segment);
172
+ if (!childNode) {
173
+ childNode = createPackageRootPathTrieNode();
174
+ node.children.set(segment, childNode);
175
+ }
176
+ node = childNode;
177
+ }
178
+ node.packageName = packageName;
179
+ }
180
+ return rootNode;
181
+ }
182
+ function createPackageRootPathTrieNode() {
183
+ return {
184
+ children: new Map(),
185
+ };
186
+ }
187
+ function getPackageNameFromRootPathTrie(filePath, trie) {
188
+ let node = trie;
189
+ if (node.packageName !== undefined)
190
+ return node.packageName;
191
+ for (let segment of getFilePathSegments(filePath)) {
192
+ let childNode = node.children.get(segment);
193
+ if (!childNode)
194
+ return undefined;
195
+ if (childNode.packageName !== undefined)
196
+ return childNode.packageName;
197
+ node = childNode;
198
+ }
199
+ return undefined;
200
+ }
201
+ function getFilePathSegments(filePath) {
202
+ return normalizeFilePath(filePath).split('/');
203
+ }
204
+ function normalizePackageSearchRoots(searchRoots) {
205
+ let normalizedSearchRoots = new Set();
206
+ for (let searchRoot of searchRoots) {
207
+ let normalizedSearchRoot = normalizeFilePath(searchRoot);
208
+ normalizedSearchRoots.add(normalizedSearchRoot);
209
+ if (path.basename(normalizedSearchRoot) === 'node_modules') {
210
+ normalizedSearchRoots.add(path.dirname(normalizedSearchRoot));
211
+ }
212
+ }
213
+ return [...normalizedSearchRoots];
214
+ }
215
+ function getPackageStateDirectories(searchRoots) {
216
+ let packageStateDirectories = new Set();
217
+ for (let searchRoot of searchRoots) {
218
+ let packageManagerRoot = findPackageManagerRoot(searchRoot);
219
+ if (packageManagerRoot !== null) {
220
+ packageStateDirectories.add(packageManagerRoot);
221
+ }
222
+ }
223
+ return [...packageStateDirectories];
224
+ }
225
+ function isPackageStateFileEvent(filePath, packageStateDirectories) {
226
+ let normalizedFilePath = normalizeFilePath(filePath);
227
+ let fileName = path.basename(normalizedFilePath);
228
+ if (!packageStateFileNames.has(fileName))
229
+ return false;
230
+ let directory = path.dirname(normalizedFilePath);
231
+ return packageStateDirectories.some((packageStateDirectory) => directory === packageStateDirectory);
232
+ }
233
+ function findPackageManagerRoot(startDirectory) {
234
+ let directory = normalizePackageStateSearchRoot(startDirectory);
235
+ while (true) {
236
+ if (hasPackageManagerRootFile(directory))
237
+ return directory;
238
+ let parentDirectory = path.dirname(directory);
239
+ if (parentDirectory === directory)
240
+ return null;
241
+ directory = parentDirectory;
242
+ }
243
+ }
244
+ function normalizePackageStateSearchRoot(searchRoot) {
245
+ let normalizedSearchRoot = normalizeFilePath(searchRoot);
246
+ return path.basename(normalizedSearchRoot) === 'node_modules'
247
+ ? path.dirname(normalizedSearchRoot)
248
+ : normalizedSearchRoot;
249
+ }
250
+ function hasPackageManagerRootFile(directory) {
251
+ for (let fileName of packageManagerRootFileNames) {
252
+ try {
253
+ let stat = fs.statSync(path.join(directory, fileName));
254
+ if (stat.isFile())
255
+ return true;
256
+ }
257
+ catch (error) {
258
+ if (isPathNotFoundError(error))
259
+ continue;
260
+ throw error;
261
+ }
262
+ }
263
+ return false;
264
+ }
265
+ function findPackageJsonPath(packageName, startDirectory) {
266
+ let directory = normalizeFilePath(startDirectory);
267
+ while (true) {
268
+ let packageJsonPath = resolvePackageJsonPath(directory, packageName);
269
+ if (packageJsonPath !== null)
270
+ return packageJsonPath;
271
+ let parentDirectory = path.dirname(directory);
272
+ if (parentDirectory === directory)
273
+ return null;
274
+ directory = parentDirectory;
275
+ }
276
+ }
277
+ function resolvePackageJsonPath(directory, packageName) {
278
+ let packagePath = path.basename(directory) === 'node_modules'
279
+ ? path.join(directory, packageName, 'package.json')
280
+ : path.join(directory, 'node_modules', packageName, 'package.json');
281
+ try {
282
+ return normalizeFilePath(fs.realpathSync(packagePath));
283
+ }
284
+ catch (error) {
285
+ if (isPathNotFoundError(error))
286
+ return null;
287
+ throw error;
288
+ }
289
+ }
290
+ function readPackageJson(packageJsonPath) {
291
+ let packageJson;
292
+ try {
293
+ packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
294
+ }
295
+ catch (error) {
296
+ if (isPathNotFoundError(error))
297
+ return {};
298
+ throw error;
299
+ }
300
+ if (packageJson === null || typeof packageJson !== 'object') {
301
+ return {};
302
+ }
303
+ return {
304
+ dependencies: readDependencyMap(packageJson, 'dependencies'),
305
+ optionalDependencies: readDependencyMap(packageJson, 'optionalDependencies'),
306
+ };
307
+ }
308
+ function readDependencyMap(packageJson, key) {
309
+ if (!(key in packageJson))
310
+ return undefined;
311
+ let value = packageJson[key];
312
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
313
+ return undefined;
314
+ }
315
+ let dependencies = {};
316
+ for (let [dependencyName, dependencyVersion] of Object.entries(value)) {
317
+ if (typeof dependencyVersion === 'string') {
318
+ dependencies[dependencyName] = dependencyVersion;
319
+ }
320
+ }
321
+ return dependencies;
322
+ }
323
+ function isValidPackageName(packageName) {
324
+ if (packageName.length === 0)
325
+ return false;
326
+ let packageNameParts = packageName.startsWith('@')
327
+ ? packageName.slice(1).split('/')
328
+ : packageName.split('/');
329
+ if (packageNameParts.length !== (packageName.startsWith('@') ? 2 : 1))
330
+ return false;
331
+ return packageNameParts.every((part) => part.length > 0 && part !== '.' && part !== '..' && packageNamePartPattern.test(part));
332
+ }
333
+ function isPathNotFoundError(error) {
334
+ return (error instanceof Error &&
335
+ 'code' in error &&
336
+ (error.code === 'ENOENT' ||
337
+ error.code === 'ENOTDIR'));
338
+ }
@@ -1,5 +1,9 @@
1
1
  import type { AssetRequestTransformMap, AssetServerFilesOptions, AssetTransformInvocation } from './files/config.ts';
2
+ import type { HmrPayload } from './hmr.ts';
3
+ import type { ModuleLoader } from './loaders.ts';
4
+ import type { ScriptHmrUpdate } from './scripts/compiler.ts';
2
5
  import type { AssetTarget } from './target.ts';
6
+ import { type AssetDetails } from './inspection.ts';
3
7
  import type { ChokidarWatcher } from './watch.ts';
4
8
  interface AssetServerWatchOptions {
5
9
  /**
@@ -16,6 +20,88 @@ interface AssetServerWatchOptions {
16
20
  */
17
21
  pollInterval?: number;
18
22
  }
23
+ /**
24
+ * Bridge used by an asset server to watch browser source files and publish update events through a
25
+ * server-level HMR runtime.
26
+ *
27
+ * The asset server registers its file handler, keeps the channel's watched-file set in sync with
28
+ * compiled assets, injects `url` into its browser HMR client, and closes the channel when the asset
29
+ * server closes.
30
+ */
31
+ export interface BrowserHmrChannel {
32
+ /** Absolute EventSource URL that receives the browser HMR events produced by this channel. */
33
+ readonly url: string;
34
+ /** Releases the channel and all file-watching resources it owns. */
35
+ close(): void;
36
+ /**
37
+ * Registers the asset server's handler for file changes reported by the channel's watcher.
38
+ *
39
+ * @param handler Callback that converts a batch of file changes into browser update or reload
40
+ * events.
41
+ * @returns A cleanup function that stops forwarding file changes to this handler.
42
+ */
43
+ onFileEvents(handler: BrowserHmrFileEventHandler): () => void;
44
+ /**
45
+ * Applies additions and removals to the channel's set of watched absolute file paths.
46
+ *
47
+ * @param delta Files to add and remove from the watcher.
48
+ */
49
+ updateWatchedFiles(delta: BrowserHmrWatchedFileDelta): void;
50
+ }
51
+ /**
52
+ * Creates the browser HMR channel owned by an asset server instance.
53
+ *
54
+ * Returning `undefined` leaves browser HMR inactive. The asset server invokes this factory once,
55
+ * after construction, and closes a returned channel from `assetServer.close()`.
56
+ *
57
+ * @returns A channel, no channel, or a promise for either result.
58
+ */
59
+ export type BrowserHmrChannelFactory = () => BrowserHmrChannel | undefined | Promise<BrowserHmrChannel | undefined>;
60
+ /**
61
+ * Converts a watcher batch into ordered browser update or reload events.
62
+ *
63
+ * @param events File additions, changes, and removals reported together by the watcher.
64
+ * @returns Browser events to publish in their returned order.
65
+ */
66
+ export type BrowserHmrFileEventHandler = (events: readonly BrowserHmrFileEvent[]) => Promise<readonly BrowserHmrEvent[]>;
67
+ /**
68
+ * Watched file delta for a browser HMR channel.
69
+ */
70
+ export interface BrowserHmrWatchedFileDelta {
71
+ /** Absolute source file paths newly required by the asset server's compiled module graph. */
72
+ add: readonly string[];
73
+ /** Absolute source file paths no longer required by the asset server's compiled module graph. */
74
+ remove: readonly string[];
75
+ }
76
+ /**
77
+ * File watcher event reported to a browser HMR channel.
78
+ */
79
+ export type BrowserHmrFileEvent = {
80
+ /** Filesystem operation observed by the channel's watcher. */
81
+ event: 'add' | 'change' | 'unlink';
82
+ /** Absolute path of the source file that changed. */
83
+ filePath: string;
84
+ };
85
+ /**
86
+ * Browser HMR event emitted to connected clients.
87
+ */
88
+ export type BrowserHmrEvent = {
89
+ /** Absolute source file paths that triggered this update. */
90
+ files?: string[];
91
+ /** Update time used to bypass browser module and stylesheet caches. */
92
+ timestamp: number;
93
+ /** Browser update event. */
94
+ type: 'update';
95
+ /** Accepted JavaScript and CSS module updates for the browser to apply in place. */
96
+ updates: Extract<HmrPayload, {
97
+ type: 'browser:update';
98
+ }>['updates'];
99
+ } | {
100
+ /** Absolute source file paths that could not be handled in place. */
101
+ files?: string[];
102
+ /** Browser reload event. */
103
+ type: 'reload';
104
+ };
19
105
  interface FingerprintOptions {
20
106
  /**
21
107
  * Per-build invalidation token that must change whenever fingerprinted asset URLs
@@ -33,6 +119,16 @@ interface AssetServerScriptOptions {
33
119
  define?: Record<string, string>;
34
120
  /** Import specifiers to leave unrewritten (CDN URLs, import map entries, etc.) */
35
121
  external?: string[];
122
+ /**
123
+ * Synchronous loaders that post-process compiled JavaScript.
124
+ *
125
+ * Loaders use Node's synchronous `load` hook signature. Later loaders wrap earlier loaders: for
126
+ * `[first, second]`, `second` is entered first and delegates through `first` to the default
127
+ * behavior. As a result, transformations performed after `nextLoad()` are applied in array order.
128
+ * Loaders run after TypeScript/JavaScript transformation and before HMR analysis and minification.
129
+ * Only `format: 'module'` is supported, and import attributes are unsupported.
130
+ */
131
+ loaders?: readonly ModuleLoader[];
36
132
  }
37
133
  /**
38
134
  * Options used to construct an {@link AssetServer} via {@link createAssetServer}.
@@ -40,9 +136,14 @@ interface AssetServerScriptOptions {
40
136
  export interface AssetServerOptions<transforms extends AssetRequestTransformMap = {}> {
41
137
  /** Public mount path for this asset server, e.g. `'/assets'`. */
42
138
  basePath: string;
43
- /** File patterns keyed by public URL patterns relative to `basePath`. */
44
- /** File patterns keyed by public URL patterns. */
45
- fileMap: Readonly<Record<string, string>>;
139
+ /**
140
+ * Directories to mount at public URL paths.
141
+ *
142
+ * Each key is a public URL path and its value is a directory relative to `rootDir`. Defaults to
143
+ * `{ app: 'app', npm: 'node_modules' }`. Public paths must not contain query strings, fragments,
144
+ * or encoded dot segments.
145
+ */
146
+ mounts?: Readonly<Record<string, string>>;
46
147
  /**
47
148
  * Root directory used to resolve relative file paths. Defaults to `process.cwd()`.
48
149
  */
@@ -50,11 +151,16 @@ export interface AssetServerOptions<transforms extends AssetRequestTransformMap
50
151
  /**
51
152
  * Glob patterns or file paths that are allowed to be served. Relative values are resolved from `rootDir`.
52
153
  */
53
- allow: readonly string[];
154
+ allowFiles: readonly string[];
155
+ /**
156
+ * Exact package names whose files are allowed to be served. Dependencies and installed optional
157
+ * dependencies are allowed automatically. Package files must still be within a configured mount.
158
+ */
159
+ allowPackages?: readonly string[];
54
160
  /**
55
161
  * Glob patterns or file paths that are denied from being served. Relative values are resolved from `rootDir`.
56
162
  */
57
- deny?: readonly string[];
163
+ denyFiles?: readonly string[];
58
164
  /**
59
165
  * Controls optional source-based URL fingerprinting for rewritten asset URLs.
60
166
  *
@@ -93,6 +199,13 @@ export interface AssetServerOptions<transforms extends AssetRequestTransformMap
93
199
  * module extensions are not allowed here.
94
200
  */
95
201
  files?: AssetServerFilesOptions<transforms>;
202
+ /**
203
+ * Enables `import.meta.hot` and coordinates browser updates through a server-level HMR runtime.
204
+ *
205
+ * HMR requires `watch` to be enabled. The factory is called once for this asset server. Returning
206
+ * `undefined` leaves HMR inactive; a returned channel is closed by `assetServer.close()`.
207
+ */
208
+ hmr?: BrowserHmrChannelFactory;
96
209
  /**
97
210
  * Enable filesystem-backed cache invalidation for long-lived server instances.
98
211
  * Enabled by default. Pass `true` to use the default watcher options, an options
@@ -132,7 +245,19 @@ export interface AssetServer<transforms extends AssetRequestTransformMap = {}> {
132
245
  */
133
246
  getPreloads(filePath: string | readonly string[]): Promise<string[]>;
134
247
  /**
135
- * Closes any watcher resources owned by this server instance.
248
+ * Returns diagnostic details about one public asset URL or file path, including the matched mount
249
+ * roots, access rules, file type, and browser-reachability status.
250
+ */
251
+ getAssetDetails(input: string): Promise<AssetDetails>;
252
+ /**
253
+ * Returns every file currently reachable through this asset server, sorted by public URL and
254
+ * then absolute file path.
255
+ */
256
+ getAssets(): Promise<AssetDetails[]>;
257
+ /**
258
+ * Closes this server's filesystem watcher and browser HMR channel.
259
+ *
260
+ * @returns A promise that resolves after owned development resources have been released.
136
261
  */
137
262
  close(): Promise<void>;
138
263
  }
@@ -142,7 +267,7 @@ export declare function getInternalWatchTargets<transforms extends AssetRequestT
142
267
  * Create an asset server instance
143
268
  *
144
269
  * Compiles TypeScript/JavaScript scripts and CSS styles on demand with optional
145
- * source-based URL fingerprinting, caching, and configurable file mapping.
270
+ * source-based URL fingerprinting, caching, and configurable directory mounts.
146
271
  *
147
272
  * @param options Server configuration
148
273
  * @returns A {@link AssetServer} with `fetch()`, `getHref()`, and `getPreloads()` methods
@@ -151,15 +276,17 @@ export declare function getInternalWatchTargets<transforms extends AssetRequestT
151
276
  * ```ts
152
277
  * let assetServer = createAssetServer({
153
278
  * basePath: '/assets',
154
- * fileMap: {
155
- * '/app/*path': 'app/*path',
156
- * },
157
- * allow: ['app/**'],
279
+ * allowFiles: ['app/routes.ts', 'app/**\/public/**'],
280
+ * allowPackages: ['remix'],
281
+ * denyFiles: ['app/**\/*.test.*'],
158
282
  * })
159
283
  *
160
284
  * route('/assets/*path', ({ request }) => assetServer.fetch(request))
161
285
  * ```
162
286
  */
163
287
  export declare function createAssetServer<const transforms extends AssetRequestTransformMap = {}>(options: AssetServerCreateOptions<transforms>): AssetServer<transforms>;
288
+ export declare function createScriptHmrPayload(updates: ScriptHmrUpdate[]): Extract<HmrPayload, {
289
+ type: 'browser:reload' | 'browser:update';
290
+ }> | null;
164
291
  export {};
165
292
  //# sourceMappingURL=asset-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset-server.d.ts","sourceRoot":"","sources":["../../src/lib/asset-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"asset-server.d.ts","sourceRoot":"","sources":["../../src/lib/asset-server.ts"],"names":[],"mappings":"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"}