@remix-run/assets 0.3.0 → 0.4.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 (61) hide show
  1. package/README.md +206 -8
  2. package/dist/assets.d.ts +1 -0
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/assets.js +1 -0
  5. package/dist/lib/access.d.ts +1 -0
  6. package/dist/lib/access.d.ts.map +1 -1
  7. package/dist/lib/access.js +7 -1
  8. package/dist/lib/asset-server.d.ts +29 -6
  9. package/dist/lib/asset-server.d.ts.map +1 -1
  10. package/dist/lib/asset-server.js +176 -17
  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/files/compiler.d.ts +71 -0
  14. package/dist/lib/files/compiler.d.ts.map +1 -0
  15. package/dist/lib/files/compiler.js +552 -0
  16. package/dist/lib/files/config.d.ts +101 -0
  17. package/dist/lib/files/config.d.ts.map +1 -0
  18. package/dist/lib/files/config.js +219 -0
  19. package/dist/lib/files/store.d.ts +31 -0
  20. package/dist/lib/files/store.d.ts.map +1 -0
  21. package/dist/lib/files/store.js +63 -0
  22. package/dist/lib/fingerprint.d.ts +3 -3
  23. package/dist/lib/fingerprint.d.ts.map +1 -1
  24. package/dist/lib/fingerprint.js +5 -5
  25. package/dist/lib/routes.d.ts.map +1 -1
  26. package/dist/lib/routes.js +28 -20
  27. package/dist/lib/scripts/compiler.d.ts +1 -0
  28. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  29. package/dist/lib/scripts/compiler.js +30 -5
  30. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  31. package/dist/lib/scripts/resolve.js +22 -2
  32. package/dist/lib/scripts/transform.js +1 -1
  33. package/dist/lib/styles/compiler.d.ts +4 -0
  34. package/dist/lib/styles/compiler.d.ts.map +1 -1
  35. package/dist/lib/styles/compiler.js +2 -0
  36. package/dist/lib/styles/emit.d.ts +3 -0
  37. package/dist/lib/styles/emit.d.ts.map +1 -1
  38. package/dist/lib/styles/emit.js +36 -1
  39. package/dist/lib/styles/resolve.d.ts +8 -1
  40. package/dist/lib/styles/resolve.d.ts.map +1 -1
  41. package/dist/lib/styles/resolve.js +85 -32
  42. package/dist/lib/watch.d.ts +2 -0
  43. package/dist/lib/watch.d.ts.map +1 -1
  44. package/dist/lib/watch.js +25 -8
  45. package/package.json +6 -4
  46. package/src/assets.ts +1 -0
  47. package/src/lib/access.ts +8 -1
  48. package/src/lib/asset-server.ts +273 -28
  49. package/src/lib/compilation-error.ts +9 -0
  50. package/src/lib/files/compiler.ts +885 -0
  51. package/src/lib/files/config.ts +479 -0
  52. package/src/lib/files/store.ts +109 -0
  53. package/src/lib/fingerprint.ts +8 -7
  54. package/src/lib/routes.ts +36 -33
  55. package/src/lib/scripts/compiler.ts +43 -5
  56. package/src/lib/scripts/resolve.ts +35 -3
  57. package/src/lib/scripts/transform.ts +1 -1
  58. package/src/lib/styles/compiler.ts +9 -0
  59. package/src/lib/styles/emit.ts +75 -1
  60. package/src/lib/styles/resolve.ts +132 -35
  61. package/src/lib/watch.ts +34 -12
@@ -0,0 +1,219 @@
1
+ import { supportedScriptExtensions } from "../scripts/resolve.js";
2
+ export function defineFileTransform(transform) {
3
+ return transform;
4
+ }
5
+ const reservedFileExtensions = new Set([...supportedScriptExtensions, '.css', '.map']);
6
+ const defaultMaxRequestTransforms = 5;
7
+ export function normalizeFilesOptions(files) {
8
+ if (files == null) {
9
+ return {
10
+ extensions: [],
11
+ globalTransforms: [],
12
+ hasTransforms: false,
13
+ maxRequestTransforms: defaultMaxRequestTransforms,
14
+ transforms: new Map(),
15
+ };
16
+ }
17
+ if (!Array.isArray(files.extensions)) {
18
+ throw new TypeError('files.extensions must be an array');
19
+ }
20
+ let normalizedExtensions = [];
21
+ let seen = new Set();
22
+ for (let extension of files.extensions) {
23
+ if (typeof extension !== 'string') {
24
+ throw new TypeError('files.extensions values must be strings');
25
+ }
26
+ let normalizedExtension = extension.trim().toLowerCase();
27
+ if (!/^\.[A-Za-z0-9_-]+$/.test(normalizedExtension)) {
28
+ throw new TypeError(`files.extensions values must use ".ext" format. Received "${extension}".`);
29
+ }
30
+ if (reservedFileExtensions.has(normalizedExtension)) {
31
+ throw new TypeError(`files.extensions cannot include compiled asset extensions like "${normalizedExtension}".`);
32
+ }
33
+ if (seen.has(normalizedExtension))
34
+ continue;
35
+ seen.add(normalizedExtension);
36
+ normalizedExtensions.push(normalizedExtension);
37
+ }
38
+ let transforms = files.transforms ?? {};
39
+ if (transforms === null || typeof transforms !== 'object' || Array.isArray(transforms)) {
40
+ throw new TypeError('files.transforms must be an object');
41
+ }
42
+ let normalizedTransforms = new Map();
43
+ for (let [name, transform] of Object.entries(transforms)) {
44
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) {
45
+ throw new TypeError(`files.transforms keys must use "transform-name" format. Received "${name}".`);
46
+ }
47
+ if (transform === null ||
48
+ typeof transform !== 'object' ||
49
+ typeof transform.transform !== 'function') {
50
+ throw new TypeError(`files.transforms.${name} must define a transform() function`);
51
+ }
52
+ if ('param' in transform &&
53
+ transform.param !== undefined &&
54
+ transform.param !== true &&
55
+ transform.param !== 'optional') {
56
+ throw new TypeError(`files.transforms.${name}.param must be true or "optional"`);
57
+ }
58
+ normalizedTransforms.set(name, {
59
+ ...transform,
60
+ extensions: normalizeTransformExtensions(transform.extensions, `files.transforms.${name}.extensions`),
61
+ });
62
+ }
63
+ let globalTransforms = files.globalTransforms ?? [];
64
+ if (!Array.isArray(globalTransforms)) {
65
+ throw new TypeError('files.globalTransforms must be an array');
66
+ }
67
+ let normalizedGlobalTransforms = [];
68
+ for (let [index, transform] of globalTransforms.entries()) {
69
+ if (typeof transform === 'function') {
70
+ normalizedGlobalTransforms.push({ transform });
71
+ continue;
72
+ }
73
+ if (transform === null || typeof transform !== 'object') {
74
+ throw new TypeError(`files.globalTransforms[${index}] must be a function or object`);
75
+ }
76
+ if ('name' in transform && transform.name !== undefined && typeof transform.name !== 'string') {
77
+ throw new TypeError(`files.globalTransforms[${index}].name must be a string`);
78
+ }
79
+ if (typeof transform.transform !== 'function') {
80
+ throw new TypeError(`files.globalTransforms[${index}] must define a transform() function`);
81
+ }
82
+ normalizedGlobalTransforms.push({
83
+ ...transform,
84
+ extensions: normalizeTransformExtensions(transform.extensions, `files.globalTransforms[${index}].extensions`),
85
+ });
86
+ }
87
+ let maxRequestTransforms = files.maxRequestTransforms ?? defaultMaxRequestTransforms;
88
+ if (!Number.isInteger(maxRequestTransforms) || maxRequestTransforms < 1) {
89
+ throw new TypeError('files.maxRequestTransforms must be a positive integer');
90
+ }
91
+ if (files.cache !== undefined) {
92
+ if (files.cache === null ||
93
+ typeof files.cache !== 'object' ||
94
+ typeof files.cache.get !== 'function' ||
95
+ typeof files.cache.set !== 'function') {
96
+ throw new TypeError('files.cache must implement the FileStorage interface');
97
+ }
98
+ }
99
+ return {
100
+ cache: files.cache,
101
+ extensions: normalizedExtensions,
102
+ globalTransforms: normalizedGlobalTransforms,
103
+ hasTransforms: normalizedTransforms.size > 0 || normalizedGlobalTransforms.length > 0,
104
+ maxRequestTransforms,
105
+ transforms: normalizedTransforms,
106
+ };
107
+ }
108
+ function normalizeTransformExtensions(extensions, optionPath) {
109
+ if (extensions === undefined)
110
+ return undefined;
111
+ if (!Array.isArray(extensions)) {
112
+ throw new TypeError(`${optionPath} must be an array`);
113
+ }
114
+ if (extensions.length === 0) {
115
+ throw new TypeError(`${optionPath} must include at least one extension`);
116
+ }
117
+ let normalizedExtensions = [];
118
+ let seen = new Set();
119
+ for (let extension of extensions) {
120
+ if (typeof extension !== 'string') {
121
+ throw new TypeError(`${optionPath} values must be strings`);
122
+ }
123
+ let normalizedExtension = extension.trim().toLowerCase();
124
+ if (!/^\.[A-Za-z0-9_-]+$/.test(normalizedExtension)) {
125
+ throw new TypeError(`${optionPath} values must use ".ext" format. Received "${extension}".`);
126
+ }
127
+ if (seen.has(normalizedExtension))
128
+ continue;
129
+ seen.add(normalizedExtension);
130
+ normalizedExtensions.push(normalizedExtension);
131
+ }
132
+ return normalizedExtensions;
133
+ }
134
+ export function serializeAssetTransformInvocations(transforms, transformsByName, maxTransforms = defaultMaxRequestTransforms) {
135
+ if (transforms.length > maxTransforms) {
136
+ throw new TypeError(`Expected at most ${maxTransforms} request transforms`);
137
+ }
138
+ return transforms.map((transformInvocation) => normalizeAssetTransformInvocation(transformInvocation, transformsByName, (message) => {
139
+ throw new TypeError(message);
140
+ }));
141
+ }
142
+ export function parseAssetTransformInvocations(transformsQuery, transformsByName, maxTransforms = defaultMaxRequestTransforms) {
143
+ if (transformsQuery.length > maxTransforms) {
144
+ throw new TypeError(`Expected at most ${maxTransforms} request transforms`);
145
+ }
146
+ return transformsQuery.map((transformQuery) => parseSerializedAssetTransformInvocation(transformQuery, transformsByName, (message) => {
147
+ throw new TypeError(message);
148
+ }));
149
+ }
150
+ function normalizeAssetTransformInvocation(transformInvocation, transformsByName, onError) {
151
+ if (typeof transformInvocation === 'string') {
152
+ if (!/^[A-Za-z0-9_-]+$/.test(transformInvocation)) {
153
+ return onError('Expected each transform name to use "transform-name" format');
154
+ }
155
+ let transform = transformsByName.get(transformInvocation);
156
+ if (transform === undefined) {
157
+ return onError(`Unknown file transform "${transformInvocation}"`);
158
+ }
159
+ if (transform.param === true) {
160
+ return onError(`File transform "${transformInvocation}" requires a param`);
161
+ }
162
+ return transformInvocation;
163
+ }
164
+ if (!Array.isArray(transformInvocation)) {
165
+ return onError('Expected each transform to be a string name or tuple');
166
+ }
167
+ if (transformInvocation.length === 0 || transformInvocation.length > 2) {
168
+ return onError('Expected each transform tuple to have one or two items');
169
+ }
170
+ let [name, rawParam] = transformInvocation;
171
+ if (typeof name !== 'string' || !/^[A-Za-z0-9_-]+$/.test(name)) {
172
+ return onError('Expected each transform name to use "transform-name" format');
173
+ }
174
+ let transform = transformsByName.get(name);
175
+ if (transform === undefined) {
176
+ return onError(`Unknown file transform "${name}"`);
177
+ }
178
+ if (transformInvocation.length === 1) {
179
+ if (transform.param === true) {
180
+ return onError(`File transform "${name}" requires a param`);
181
+ }
182
+ return name;
183
+ }
184
+ if (typeof rawParam !== 'string') {
185
+ return onError(`Invalid param for file transform "${name}": expected a string`);
186
+ }
187
+ if (transform.param === undefined) {
188
+ if (transformInvocation.length === 2) {
189
+ return onError(`File transform "${name}" does not accept a param`);
190
+ }
191
+ return name;
192
+ }
193
+ return `${name}:${rawParam}`;
194
+ }
195
+ function parseSerializedAssetTransformInvocation(transformQuery, transformsByName, onError) {
196
+ let separatorIndex = transformQuery.indexOf(':');
197
+ let name = separatorIndex === -1 ? transformQuery : transformQuery.slice(0, separatorIndex);
198
+ let param = separatorIndex === -1 ? undefined : transformQuery.slice(separatorIndex + 1);
199
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) {
200
+ return onError('Expected each transform name to use "transform-name" format');
201
+ }
202
+ let transform = transformsByName.get(name);
203
+ if (transform === undefined) {
204
+ return onError(`Unknown file transform "${name}"`);
205
+ }
206
+ if (transform.param === undefined) {
207
+ if (param !== undefined) {
208
+ return onError(`File transform "${name}" does not accept a param`);
209
+ }
210
+ return name;
211
+ }
212
+ if (transform.param === true && param === undefined) {
213
+ return onError(`File transform "${name}" requires a param`);
214
+ }
215
+ if (param === undefined) {
216
+ return name;
217
+ }
218
+ return [name, param];
219
+ }
@@ -0,0 +1,31 @@
1
+ export type FileSnapshot = {
2
+ filePath: string;
3
+ mtimeNs: bigint;
4
+ size: bigint;
5
+ };
6
+ export type SourceFileMetadata = {
7
+ contentType: string;
8
+ etag: string;
9
+ extension: string;
10
+ fingerprint: string | null;
11
+ };
12
+ type SourceFileRecordState = {
13
+ metadata?: SourceFileMetadata;
14
+ metadataSnapshot?: FileSnapshot;
15
+ identityPath: string;
16
+ invalidationVersion: number;
17
+ staleMetadata?: SourceFileMetadata;
18
+ staleMetadataSnapshot?: FileSnapshot;
19
+ };
20
+ export type SourceFileRecord = Readonly<SourceFileRecordState>;
21
+ export type SourceFileStore = {
22
+ get(identityPath: string): SourceFileRecord;
23
+ invalidate(identityPath: string, options?: {
24
+ retainStale: boolean;
25
+ }): void;
26
+ invalidateForFileEvent(filePath: string, event: 'add' | 'change' | 'unlink'): void;
27
+ set(identityPath: string, metadata: SourceFileMetadata, snapshot: FileSnapshot | null): void;
28
+ };
29
+ export declare function createSourceFileStore(): SourceFileStore;
30
+ export {};
31
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/lib/files/store.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,gBAAgB,CAAC,EAAE,YAAY,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,qBAAqB,CAAC,EAAE,YAAY,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAA;AAW9D,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAAA;IAC3C,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;IAC1E,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAA;IAClF,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAAA;CAC7F,CAAA;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAoEvD"}
@@ -0,0 +1,63 @@
1
+ export function createSourceFileStore() {
2
+ let recordsByIdentityPath = new Map();
3
+ let invalidationVersionByIdentityPath = new Map();
4
+ return {
5
+ get(identityPath) {
6
+ return getOrCreateRecord(identityPath);
7
+ },
8
+ invalidate(identityPath, options = { retainStale: false }) {
9
+ let record = recordsByIdentityPath.get(identityPath);
10
+ if (!record)
11
+ return;
12
+ invalidateRecord(record, options);
13
+ },
14
+ invalidateForFileEvent(filePath, event) {
15
+ let record = recordsByIdentityPath.get(filePath);
16
+ if (!record)
17
+ return;
18
+ invalidateRecord(record, { retainStale: event === 'change' });
19
+ if (event === 'unlink') {
20
+ recordsByIdentityPath.delete(filePath);
21
+ }
22
+ },
23
+ set(identityPath, metadata, snapshot) {
24
+ let record = recordsByIdentityPath.get(identityPath);
25
+ if (!record) {
26
+ record = getOrCreateRecord(identityPath);
27
+ }
28
+ record.metadata = metadata;
29
+ record.metadataSnapshot = snapshot ?? undefined;
30
+ record.staleMetadata = undefined;
31
+ record.staleMetadataSnapshot = undefined;
32
+ },
33
+ };
34
+ function invalidateRecord(record, options) {
35
+ if (!options.retainStale) {
36
+ record.staleMetadata = undefined;
37
+ record.staleMetadataSnapshot = undefined;
38
+ }
39
+ else if (record.metadata && record.metadataSnapshot) {
40
+ record.staleMetadata = record.metadata;
41
+ record.staleMetadataSnapshot = record.metadataSnapshot;
42
+ }
43
+ else if (!record.staleMetadata || !record.staleMetadataSnapshot) {
44
+ record.staleMetadata = undefined;
45
+ record.staleMetadataSnapshot = undefined;
46
+ }
47
+ record.metadata = undefined;
48
+ record.metadataSnapshot = undefined;
49
+ record.invalidationVersion += 1;
50
+ invalidationVersionByIdentityPath.set(record.identityPath, record.invalidationVersion);
51
+ }
52
+ function getOrCreateRecord(identityPath) {
53
+ let existing = recordsByIdentityPath.get(identityPath);
54
+ if (existing)
55
+ return existing;
56
+ let record = {
57
+ identityPath,
58
+ invalidationVersion: invalidationVersionByIdentityPath.get(identityPath) ?? 0,
59
+ };
60
+ recordsByIdentityPath.set(identityPath, record);
61
+ return record;
62
+ }
63
+ }
@@ -1,7 +1,7 @@
1
- export declare function hashContent(content: string): Promise<string>;
2
- export declare function generateFingerprint(options: {
1
+ export declare function hashContent(content: string | Uint8Array<ArrayBufferLike>): Promise<string>;
2
+ export declare function generateFingerprint(args: {
3
3
  buildId: string;
4
- content: string;
4
+ content: string | Uint8Array<ArrayBufferLike>;
5
5
  }): Promise<string>;
6
6
  export declare function parseFingerprintSuffix(pathname: string): {
7
7
  pathname: string;
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKlE;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAElB;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACxD,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAyBA;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAahG;AAED,wBAAgB,iCAAiC,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE7F"}
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAIhG;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,CAAA;CAC9C,GAAG,OAAO,CAAC,MAAM,CAAC,CAIlB;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACxD,QAAQ,EAAE,MAAM,CAAA;IAChB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAyBA;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAahG;AAED,wBAAgB,iCAAiC,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE7F"}
@@ -1,13 +1,13 @@
1
1
  const fingerprintedExtensionRE = /^(.+)\.@([A-Za-z0-9_-]+)(\.[^./]+)$/;
2
2
  const fingerprintedBasenameRE = /^(.+)\.@([A-Za-z0-9_-]+)$/;
3
3
  export async function hashContent(content) {
4
- let encoder = new TextEncoder();
5
- let data = encoder.encode(content);
6
- let hashBuffer = await crypto.subtle.digest('SHA-256', data);
4
+ let bytes = typeof content === 'string' ? new TextEncoder().encode(content) : Buffer.from(content);
5
+ let hashBuffer = await crypto.subtle.digest('SHA-256', bytes);
7
6
  return Buffer.from(hashBuffer).toString('base64url').slice(0, 6);
8
7
  }
9
- export async function generateFingerprint(options) {
10
- return hashContent(JSON.stringify([options.content, options.buildId]));
8
+ export async function generateFingerprint(args) {
9
+ let content = typeof args.content === 'string' ? args.content : Buffer.from(args.content).toString('base64');
10
+ return hashContent(JSON.stringify([content, args.buildId]));
11
11
  }
12
12
  export function parseFingerprintSuffix(pathname) {
13
13
  let lastSlashIndex = pathname.lastIndexOf('/');
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/lib/routes.ts"],"names":[],"mappings":"AAeA,UAAU,WAAW;IACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACzC,OAAO,EAAE,MAAM,CAAA;CAChB;AAQD,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAC/C;AAYD,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,SAAS,WAAW,EAAE,GACnC,cAAc,CA8ChB"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/lib/routes.ts"],"names":[],"mappings":"AAiBA,UAAU,WAAW;IACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACzC,OAAO,EAAE,MAAM,CAAA;CAChB;AAUD,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAC/C;AAYD,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,SAAS,WAAW,EAAE,GACnC,cAAc,CA8ChB"}
@@ -1,4 +1,6 @@
1
1
  import { RoutePattern } from '@remix-run/route-pattern';
2
+ import { createHref } from '@remix-run/route-pattern/href';
3
+ import { createMatcher } from '@remix-run/route-pattern/match';
2
4
  import { getRelativeFilePath, isAbsoluteFilePath, normalizeFilePath, normalizePathname, resolveFilePath, } from "./paths.js";
3
5
  function normalizeFilePattern(pattern) {
4
6
  if (isAbsoluteFilePath(pattern)) {
@@ -21,10 +23,10 @@ export function compileRoutes(basePath, routeConfigs) {
21
23
  resolveUrlPathname(pathname) {
22
24
  let normalizedPathname = normalizePathname(pathname);
23
25
  for (let route of compiledRoutes) {
24
- let match = route.urlPattern.match(`http://remix.run${normalizedPathname}`);
26
+ let match = route.urlMatcher.match(`http://remix.run${normalizedPathname}`);
25
27
  if (!match)
26
28
  continue;
27
- let relativeFilePath = route.filePattern.href(match.params).replace(/^\/+/, '');
29
+ let relativeFilePath = createHref(route.filePattern, match.params).replace(/^\/+/, '');
28
30
  return resolveFilePath(route.rootDir, relativeFilePath);
29
31
  }
30
32
  return null;
@@ -33,10 +35,10 @@ export function compileRoutes(basePath, routeConfigs) {
33
35
  let normalizedFilePath = normalizeFilePath(filePath);
34
36
  for (let route of compiledRoutes) {
35
37
  let relativeFilePath = getRelativeFilePath(route.rootDir, normalizedFilePath);
36
- let match = route.filePattern.ast.pathname.match(relativeFilePath);
38
+ let match = route.fileMatcher.match(`http://remix.run/${relativeFilePath}`);
37
39
  if (!match)
38
40
  continue;
39
- return normalizePathname(route.urlPattern.href(getPathnameParams(route.filePattern, match)));
41
+ return normalizePathname(createHref(route.urlPattern, match.params));
40
42
  }
41
43
  return null;
42
44
  },
@@ -47,45 +49,51 @@ function compileRoute(route, options) {
47
49
  let relativeUrlPattern = normalizePathname(route.urlPattern);
48
50
  let urlPatternSource = normalizePathname(`${basePath.replace(/\/+$/, '')}/${relativeUrlPattern.replace(/^\/+/, '')}`);
49
51
  let filePatternSource = normalizeFilePattern(route.filePattern);
50
- let urlPattern = new RoutePattern(urlPatternSource);
51
- let filePattern = new RoutePattern(filePatternSource);
52
+ let urlPattern = RoutePattern.parse(urlPatternSource);
53
+ let filePattern = RoutePattern.parse(filePatternSource);
52
54
  validateNoUnnamedWildcards(urlPattern, 'URL');
53
55
  validateNoUnnamedWildcards(filePattern, 'File');
54
56
  validateRoutePatterns(urlPattern, filePattern);
55
57
  return {
56
58
  rootDir: normalizeFilePath(options.rootDir).replace(/\/+$/, ''),
57
59
  urlPattern,
60
+ urlMatcher: createMatcher(urlPattern),
58
61
  filePattern,
62
+ fileMatcher: createMatcher(stripDotSegments(filePatternSource)),
59
63
  };
60
64
  }
61
- function getPathnameParams(pattern, match) {
62
- let params = {};
63
- for (let param of pattern.ast.pathname.params) {
64
- if (param.name === '*')
65
+ function stripDotSegments(pattern) {
66
+ let segments = [];
67
+ for (let segment of pattern.split('/')) {
68
+ if (segment === '' || segment === '.')
65
69
  continue;
66
- params[param.name] = undefined;
67
- }
68
- for (let param of match) {
69
- if (param.name === '*')
70
+ if (segment === '..') {
71
+ segments.pop();
70
72
  continue;
71
- params[param.name] = param.value;
73
+ }
74
+ segments.push(segment);
72
75
  }
73
- return params;
76
+ return segments.join('/');
74
77
  }
75
78
  function validateRoutePatterns(urlPattern, filePattern) {
76
- let urlParams = urlPattern.ast.pathname.params.map((param) => `${param.type}:${param.name}`);
77
- let fileParams = filePattern.ast.pathname.params.map((param) => `${param.type}:${param.name}`);
79
+ let urlParams = getPathnameParams(urlPattern);
80
+ let fileParams = getPathnameParams(filePattern);
78
81
  if (urlParams.length !== fileParams.length) {
79
82
  throw new Error(`Route patterns must have matching capture structure.\nURL: ${urlPattern}\nFile: ${filePattern}`);
80
83
  }
81
84
  for (let i = 0; i < urlParams.length; i++) {
82
- if (urlParams[i] !== fileParams[i]) {
85
+ let urlParam = urlParams[i];
86
+ let fileParam = fileParams[i];
87
+ if (urlParam.type !== fileParam.type || urlParam.name !== fileParam.name) {
83
88
  throw new Error(`Route patterns must have matching capture structure.\nURL: ${urlPattern}\nFile: ${filePattern}`);
84
89
  }
85
90
  }
86
91
  }
87
92
  function validateNoUnnamedWildcards(pattern, label) {
88
- if (pattern.ast.pathname.params.some((param) => param.type === '*' && param.name === '*')) {
93
+ if (pattern.pathname.tokens.some((token) => token.type === '*' && token.name === '*')) {
89
94
  throw new Error(`${label} route patterns must use named wildcards for reversible mapping.\nPattern: ${pattern}`);
90
95
  }
91
96
  }
97
+ function getPathnameParams(pattern) {
98
+ return pattern.pathname.tokens.filter((token) => token.type === ':' || token.type === '*');
99
+ }
@@ -25,6 +25,7 @@ type ScriptCompilerOptions = {
25
25
  external: string[];
26
26
  fingerprintAssets: boolean;
27
27
  isAllowed(absolutePath: string): boolean;
28
+ isDenied(absolutePath: string): boolean;
28
29
  minify: boolean;
29
30
  onWatchDirectoriesChange?: (delta: {
30
31
  add: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/compiler.ts"],"names":[],"mappings":"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"}
@@ -30,8 +30,14 @@ export function createScriptCompiler(options) {
30
30
  extensionAlias: resolverExtensionAlias,
31
31
  extensions: resolverExtensions,
32
32
  mainFields: ['browser', 'module', 'main'],
33
+ symlinks: false,
33
34
  tsconfig: 'auto',
34
35
  });
36
+ let resolveModulePathOptions = {
37
+ isAllowed: resolvedOptions.isAllowed,
38
+ isDenied: resolvedOptions.isDenied,
39
+ routes: resolvedOptions.routes,
40
+ };
35
41
  let resolveInFlightByCacheKey = new Map();
36
42
  let emitInFlightByCacheKey = new Map();
37
43
  let transformArgs = {
@@ -50,7 +56,9 @@ export function createScriptCompiler(options) {
50
56
  let resolveArgs = {
51
57
  isAllowed: resolvedOptions.isAllowed,
52
58
  isWatchIgnored,
53
- resolveModulePath,
59
+ resolveModulePath(absolutePath) {
60
+ return resolveModulePath(absolutePath, resolveModulePathOptions);
61
+ },
54
62
  resolverFactory,
55
63
  routes: resolvedOptions.routes,
56
64
  };
@@ -144,7 +152,7 @@ export function createScriptCompiler(options) {
144
152
  return resolveFilePath(resolvedOptions.rootDir, filePath);
145
153
  }
146
154
  function resolveServedScriptOrThrow(absolutePath) {
147
- let resolvedModule = resolveModulePath(absolutePath);
155
+ let resolvedModule = resolveModulePath(absolutePath, resolveModulePathOptions);
148
156
  if (!resolvedModule) {
149
157
  throw createAssetServerCompilationError(`File not found: ${absolutePath}`, {
150
158
  code: 'FILE_NOT_FOUND',
@@ -366,10 +374,11 @@ function isTsconfigPath(filePath) {
366
374
  function shouldClearResolverCacheForFileEvent(filePath, event) {
367
375
  return event !== 'change' || isPackageJsonPath(filePath) || isTsconfigPath(filePath);
368
376
  }
369
- function resolveModulePath(absolutePath) {
377
+ function resolveModulePath(absolutePath, options) {
378
+ let candidateIdentityPath = normalizeFilePath(absolutePath);
370
379
  let resolvedPath;
371
380
  try {
372
- resolvedPath = normalizeFilePath(fs.realpathSync(normalizeFilePath(absolutePath)));
381
+ resolvedPath = normalizeFilePath(fs.realpathSync(candidateIdentityPath));
373
382
  }
374
383
  catch (error) {
375
384
  if (isNoEntityError(error))
@@ -380,10 +389,26 @@ function resolveModulePath(absolutePath) {
380
389
  return null;
381
390
  }
382
391
  return {
383
- identityPath: resolvedPath,
392
+ identityPath: getModuleIdentityPath(candidateIdentityPath, resolvedPath, options),
384
393
  resolvedPath,
385
394
  };
386
395
  }
396
+ function getModuleIdentityPath(candidateIdentityPath, resolvedPath, options) {
397
+ if (candidateIdentityPath === resolvedPath)
398
+ return resolvedPath;
399
+ if (!containsNodeModulesPathSegment(candidateIdentityPath))
400
+ return resolvedPath;
401
+ if (!options.routes.toUrlPathname(candidateIdentityPath))
402
+ return resolvedPath;
403
+ if (!options.isAllowed(candidateIdentityPath))
404
+ return resolvedPath;
405
+ if (options.isDenied(resolvedPath))
406
+ return resolvedPath;
407
+ return candidateIdentityPath;
408
+ }
409
+ function containsNodeModulesPathSegment(filePath) {
410
+ return filePath.split('/').includes('node_modules');
411
+ }
387
412
  function resolveActualPath(identityPath) {
388
413
  try {
389
414
  return normalizeFilePath(fs.realpathSync(identityPath));
@@ -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;AAYD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,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,CA0IxB"}
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;AAYD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,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,CA4IxB"}
@@ -18,7 +18,7 @@ export async function resolveModule(record, transformed, args) {
18
18
  try {
19
19
  resolvedImports =
20
20
  transformed.unresolvedImports.length > 0
21
- ? await batchResolveSpecifiers(getUniqueSpecifiers(transformed.unresolvedImports), transformed.resolvedPath, args.resolverFactory)
21
+ ? await batchResolveSpecifiers(getUniqueSpecifiers(transformed.unresolvedImports), transformed.identityPath, args.resolverFactory)
22
22
  : new Map();
23
23
  }
24
24
  catch (error) {
@@ -60,7 +60,7 @@ export async function resolveModule(record, transformed, args) {
60
60
  }
61
61
  deps.add(resolvedImport.identityPath);
62
62
  if (transformed.packageSpecifiers.includes(unresolved.specifier)) {
63
- let packageJsonPath = resolvedSpec.packageJsonPath ?? findNearestPackageJsonPath(resolvedImport.resolvedPath);
63
+ let packageJsonPath = resolvePackageJsonPath(resolvedSpec.packageJsonPath, resolvedImport.resolvedPath);
64
64
  if (packageJsonPath && !args.isWatchIgnored(packageJsonPath)) {
65
65
  trackedFiles.add(packageJsonPath);
66
66
  }
@@ -94,6 +94,20 @@ export async function resolveModule(record, transformed, args) {
94
94
  },
95
95
  };
96
96
  }
97
+ function resolvePackageJsonPath(packageJsonPath, resolvedPath) {
98
+ return ((packageJsonPath ? resolveExistingPath(packageJsonPath) : null) ??
99
+ findNearestPackageJsonPath(resolvedPath));
100
+ }
101
+ function resolveExistingPath(filePath) {
102
+ try {
103
+ return normalizeFilePath(fs.realpathSync(filePath));
104
+ }
105
+ catch (error) {
106
+ if (isNoEntityError(error))
107
+ return null;
108
+ throw error;
109
+ }
110
+ }
97
111
  function findNearestPackageJsonPath(filePath) {
98
112
  let directory = path.dirname(filePath);
99
113
  while (true) {
@@ -107,6 +121,12 @@ function findNearestPackageJsonPath(filePath) {
107
121
  directory = parentDirectory;
108
122
  }
109
123
  }
124
+ function isNoEntityError(error) {
125
+ return (error instanceof Error &&
126
+ 'code' in error &&
127
+ (error.code === 'ENOENT' ||
128
+ error.code === 'ENOTDIR'));
129
+ }
110
130
  function isRelativeImportSpecifier(specifier) {
111
131
  return specifier.startsWith('./') || specifier.startsWith('../');
112
132
  }
@@ -141,7 +141,7 @@ export async function transformModule(record, args) {
141
141
  content: sourceText,
142
142
  }),
143
143
  identityPath: record.identityPath,
144
- importerDir: path.dirname(resolvedPath),
144
+ importerDir: path.dirname(record.identityPath),
145
145
  packageSpecifiers: analysis.unresolvedImports
146
146
  .filter((unresolved) => isPackageImportSpecifier(unresolved.specifier))
147
147
  .map((unresolved) => unresolved.specifier),
@@ -21,7 +21,11 @@ type StyleGetOptions = {
21
21
  type StyleCompilerOptions = {
22
22
  buildId?: string;
23
23
  fingerprintAssets: boolean;
24
+ getServedFileUrl?(identityPath: string, options: {
25
+ transform: readonly string[] | null;
26
+ }): Promise<string>;
24
27
  isAllowed(absolutePath: string): boolean;
28
+ isServedFilePath(filePath: string): boolean;
25
29
  minify: boolean;
26
30
  onWatchDirectoriesChange?: (delta: {
27
31
  add: string[];