@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.
- package/README.md +331 -72
- package/dist/assets.d.ts +4 -1
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +2 -2
- package/dist/lib/access.d.ts +35 -4
- package/dist/lib/access.d.ts.map +1 -1
- package/dist/lib/access.js +332 -11
- package/dist/lib/asset-server.d.ts +138 -11
- package/dist/lib/asset-server.d.ts.map +1 -1
- package/dist/lib/asset-server.js +281 -30
- package/dist/lib/compilation-error.d.ts +1 -1
- package/dist/lib/compilation-error.d.ts.map +1 -1
- package/dist/lib/file-matcher.js +1 -1
- package/dist/lib/files/compiler.d.ts.map +1 -1
- package/dist/lib/files/compiler.js +9 -8
- package/dist/lib/files/config.js +1 -1
- package/dist/lib/hmr.d.ts +37 -0
- package/dist/lib/hmr.d.ts.map +1 -0
- package/dist/lib/hmr.js +357 -0
- package/dist/lib/injected-packages.d.ts +3 -2
- package/dist/lib/injected-packages.d.ts.map +1 -1
- package/dist/lib/injected-packages.js +43 -17
- package/dist/lib/inspection.d.ts +39 -0
- package/dist/lib/inspection.d.ts.map +1 -0
- package/dist/lib/inspection.js +160 -0
- package/dist/lib/loaders.d.ts +57 -0
- package/dist/lib/loaders.d.ts.map +1 -0
- package/dist/lib/loaders.js +1 -0
- package/dist/lib/module-store.d.ts +24 -0
- package/dist/lib/module-store.d.ts.map +1 -1
- package/dist/lib/module-store.js +136 -11
- package/dist/lib/routes.d.ts +11 -3
- package/dist/lib/routes.d.ts.map +1 -1
- package/dist/lib/routes.js +124 -80
- package/dist/lib/scripts/compiler.d.ts +24 -1
- package/dist/lib/scripts/compiler.d.ts.map +1 -1
- package/dist/lib/scripts/compiler.js +183 -29
- package/dist/lib/scripts/conditions.d.ts +2 -0
- package/dist/lib/scripts/conditions.d.ts.map +1 -0
- package/dist/lib/scripts/conditions.js +1 -0
- package/dist/lib/scripts/emit.d.ts +3 -0
- package/dist/lib/scripts/emit.d.ts.map +1 -1
- package/dist/lib/scripts/emit.js +24 -5
- package/dist/lib/scripts/resolve.d.ts +4 -0
- package/dist/lib/scripts/resolve.d.ts.map +1 -1
- package/dist/lib/scripts/resolve.js +75 -10
- package/dist/lib/scripts/transform.d.ts +9 -0
- package/dist/lib/scripts/transform.d.ts.map +1 -1
- package/dist/lib/scripts/transform.js +222 -18
- package/dist/lib/source-maps.js +1 -1
- package/dist/lib/styles/compiler.d.ts +14 -1
- package/dist/lib/styles/compiler.d.ts.map +1 -1
- package/dist/lib/styles/compiler.js +78 -14
- package/dist/lib/styles/emit.js +4 -4
- package/dist/lib/styles/resolve.d.ts.map +1 -1
- package/dist/lib/styles/resolve.js +16 -15
- package/dist/lib/styles/transform.js +5 -5
- package/dist/lib/target.d.ts +1 -1
- package/dist/lib/target.d.ts.map +1 -1
- package/dist/lib/watch.js +1 -1
- package/dist/types/hmr.d.ts +36 -0
- package/package.json +16 -11
- package/src/assets.ts +4 -1
- package/src/lib/access.ts +445 -11
- package/src/lib/asset-server.ts +466 -27
- package/src/lib/compilation-error.ts +4 -3
- package/src/lib/files/compiler.ts +9 -5
- package/src/lib/hmr.ts +397 -0
- package/src/lib/injected-packages.ts +52 -16
- package/src/lib/inspection.ts +229 -0
- package/src/lib/loaders.ts +80 -0
- package/src/lib/module-store.ts +190 -9
- package/src/lib/routes.ts +158 -126
- package/src/lib/scripts/compiler.ts +248 -24
- package/src/lib/scripts/conditions.ts +1 -0
- package/src/lib/scripts/emit.ts +50 -5
- package/src/lib/scripts/resolve.ts +129 -7
- package/src/lib/scripts/transform.ts +290 -19
- package/src/lib/styles/compiler.ts +108 -8
- package/src/lib/styles/emit.ts +1 -1
- package/src/lib/styles/resolve.ts +19 -15
- package/src/lib/styles/transform.ts +2 -2
- package/src/types/hmr.d.ts +36 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
type ModuleFloat16Array = typeof globalThis extends {
|
|
2
|
+
Float16Array: {
|
|
3
|
+
prototype: infer array;
|
|
4
|
+
};
|
|
5
|
+
} ? array : never;
|
|
6
|
+
type ModuleTypedArray = Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | Int8Array | Int16Array | Int32Array | BigUint64Array | BigInt64Array | ModuleFloat16Array | Float32Array | Float64Array;
|
|
7
|
+
type ModuleLoadSource = string | ArrayBuffer | ModuleTypedArray;
|
|
8
|
+
/**
|
|
9
|
+
* Synchronously loads a module or delegates to the next configured loader.
|
|
10
|
+
*
|
|
11
|
+
* Loaders follow Node's synchronous `load` hook signature and chaining contract. The asset server
|
|
12
|
+
* passes them JavaScript after its TypeScript/JavaScript transform and before HMR analysis and
|
|
13
|
+
* minification. Each loader must delegate to `nextLoad` or return `shortCircuit: true`.
|
|
14
|
+
*
|
|
15
|
+
* @param url Resolved `file:` URL for the module being compiled.
|
|
16
|
+
* @param context Format, conditions, attributes, and public asset URL for this load.
|
|
17
|
+
* @param nextLoad Next loader in the chain, ending with the asset server's compiled JavaScript.
|
|
18
|
+
* @returns A Node-compatible load result containing ES module source.
|
|
19
|
+
*/
|
|
20
|
+
export type ModuleLoader = (url: string, context: ModuleLoadContext, nextLoad: NextModuleLoader) => ModuleLoadResult;
|
|
21
|
+
/**
|
|
22
|
+
* Continues loading through the remaining loader chain.
|
|
23
|
+
*
|
|
24
|
+
* Omitted context fields retain their current values.
|
|
25
|
+
*
|
|
26
|
+
* @param url Current module URL. Loaders cannot change this URL.
|
|
27
|
+
* @param context Context fields to override for the remainder of this load.
|
|
28
|
+
* @returns The source produced by the remaining loaders or the asset compiler.
|
|
29
|
+
*/
|
|
30
|
+
export type NextModuleLoader = (url: string, context?: Partial<ModuleLoadContext>) => ModuleLoadResult;
|
|
31
|
+
/** State passed through a module loader chain. */
|
|
32
|
+
export interface ModuleLoadContext {
|
|
33
|
+
/** Package export conditions used while compiling this module. */
|
|
34
|
+
conditions: string[];
|
|
35
|
+
/** Current module format. Asset-server loaders must ultimately return `'module'`. */
|
|
36
|
+
format: string | null | undefined;
|
|
37
|
+
/** Import attributes supplied by the previous loader. Authored import attributes are unsupported. */
|
|
38
|
+
importAttributes: Record<string, string | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Stable public URL path used to request this module from the asset server.
|
|
41
|
+
*
|
|
42
|
+
* Unlike Node's standard load context, this field is provided so loaders can use the browser
|
|
43
|
+
* module identity rather than its private filesystem URL.
|
|
44
|
+
*/
|
|
45
|
+
moduleUrl?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Source returned by a module loader. */
|
|
48
|
+
export interface ModuleLoadResult {
|
|
49
|
+
/** Loaded module format. Must be `'module'` for asset-server scripts. */
|
|
50
|
+
format: string | null | undefined;
|
|
51
|
+
/** Whether this result intentionally ends the loader chain without calling `nextLoad`. */
|
|
52
|
+
shortCircuit?: boolean;
|
|
53
|
+
/** Compiled JavaScript source, optionally rewritten by the loader. */
|
|
54
|
+
source?: ModuleLoadSource;
|
|
55
|
+
}
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=loaders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loaders.d.ts","sourceRoot":"","sources":["../../src/lib/loaders.ts"],"names":[],"mappings":"AAAA,KAAK,kBAAkB,GAAG,OAAO,UAAU,SAAS;IAClD,YAAY,EAAE;QAAE,SAAS,EAAE,MAAM,KAAK,CAAA;KAAE,CAAA;CACzC,GACG,KAAK,GACL,KAAK,CAAA;AAET,KAAK,gBAAgB,GACjB,UAAU,GACV,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,SAAS,GACT,UAAU,GACV,UAAU,GACV,cAAc,GACd,aAAa,GACb,kBAAkB,GAClB,YAAY,GACZ,YAAY,CAAA;AAEhB,KAAK,gBAAgB,GAAG,MAAM,GAAG,WAAW,GAAG,gBAAgB,CAAA;AAE/D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,gBAAgB,KACvB,gBAAgB,CAAA;AAErB;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,KACjC,gBAAgB,CAAA;AAErB,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,qFAAqF;IACrF,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACjC,qGAAqG;IACrG,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACpD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACjC,0FAA0F;IAC1F,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,sEAAsE;IACtE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,11 +8,21 @@ export type FileSnapshot = {
|
|
|
8
8
|
size: bigint;
|
|
9
9
|
};
|
|
10
10
|
export type ModuleSnapshot = ReadonlyMap<string, FileSnapshot>;
|
|
11
|
+
type ModuleLinksState = {
|
|
12
|
+
acceptedDependencies: ReadonlySet<string>;
|
|
13
|
+
dependencies: ReadonlySet<string>;
|
|
14
|
+
};
|
|
11
15
|
type ModuleRecordState<transformed, resolved, emitted> = {
|
|
16
|
+
emittedVersion?: number;
|
|
17
|
+
hmrUpdateTimestamp?: number;
|
|
12
18
|
identityPath: string;
|
|
13
19
|
invalidationVersion: number;
|
|
14
20
|
transformed?: transformed;
|
|
21
|
+
transformedVersion?: number;
|
|
15
22
|
resolved?: resolved;
|
|
23
|
+
resolvedVersion?: number;
|
|
24
|
+
lastResolved?: resolved;
|
|
25
|
+
links: ModuleLinksState;
|
|
16
26
|
emitted?: emitted;
|
|
17
27
|
emittedSnapshot?: ModuleSnapshot;
|
|
18
28
|
staleEmitted?: emitted;
|
|
@@ -23,6 +33,14 @@ type ModuleRecordState<transformed, resolved, emitted> = {
|
|
|
23
33
|
export type ModuleRecord<transformed, resolved, emitted> = Readonly<ModuleRecordState<transformed, resolved, emitted>>;
|
|
24
34
|
export type ModuleStore<transformed, resolved, emitted> = {
|
|
25
35
|
get(identityPath: string): ModuleRecord<transformed, resolved, emitted>;
|
|
36
|
+
getAcceptedImporters(identityPath: string): ReadonlySet<string>;
|
|
37
|
+
getHmrUpdateTimestamp(identityPath: string): number | undefined;
|
|
38
|
+
getImporters(identityPath: string): ReadonlySet<string>;
|
|
39
|
+
getLastResolved(identityPath: string): resolved | undefined;
|
|
40
|
+
isEmittedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean;
|
|
41
|
+
isResolvedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean;
|
|
42
|
+
isTransformedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean;
|
|
43
|
+
setHmrUpdateTimestamp(identityPath: string, timestamp: number): void;
|
|
26
44
|
clearTransformed(identityPath: string, tracking: readonly ModuleTracking[]): void;
|
|
27
45
|
setTransformed(identityPath: string, transformed: transformed, tracking: readonly ModuleTracking[]): void;
|
|
28
46
|
setResolved(identityPath: string, resolved: resolved, tracking: readonly ModuleTracking[]): void;
|
|
@@ -32,10 +50,16 @@ export type ModuleStore<transformed, resolved, emitted> = {
|
|
|
32
50
|
invalidateAll(): void;
|
|
33
51
|
};
|
|
34
52
|
export declare function createModuleStore<transformed, resolved, emitted>(options?: {
|
|
53
|
+
getAcceptedDependencies?: (resolved: resolved) => readonly string[];
|
|
54
|
+
getDependencies?: (resolved: resolved) => readonly string[];
|
|
35
55
|
onWatchDirectoriesChange?: (delta: {
|
|
36
56
|
add: string[];
|
|
37
57
|
remove: string[];
|
|
38
58
|
}) => void;
|
|
59
|
+
onWatchFilesChange?: (delta: {
|
|
60
|
+
add: string[];
|
|
61
|
+
remove: string[];
|
|
62
|
+
}) => void;
|
|
39
63
|
}): ModuleStore<transformed, resolved, emitted>;
|
|
40
64
|
export {};
|
|
41
65
|
//# sourceMappingURL=module-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-store.d.ts","sourceRoot":"","sources":["../../src/lib/module-store.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AAE9D,KAAK,iBAAiB,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,IAAI;IACvD,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,cAAc,CAAA;IAChC,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oBAAoB,CAAC,EAAE,cAAc,CAAA;IACrC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACjC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,IAAI,QAAQ,CACjE,iBAAiB,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAClD,CAAA;
|
|
1
|
+
{"version":3,"file":"module-store.d.ts","sourceRoot":"","sources":["../../src/lib/module-store.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/module-store.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { getFilePathDirectory } from
|
|
1
|
+
import { getFilePathDirectory } from './paths.js';
|
|
2
2
|
export function createModuleStore(options = {}) {
|
|
3
3
|
let recordsByIdentityPath = new Map();
|
|
4
|
+
let importersByDepPath = new Map();
|
|
5
|
+
let acceptedImportersByDepPath = new Map();
|
|
4
6
|
let recordsByTrackedFile = new Map();
|
|
5
7
|
let watchDirectoryRefCountByPath = new Map();
|
|
8
|
+
let watchFileRefCountByPath = new Map();
|
|
9
|
+
let emptyImporters = new Set();
|
|
6
10
|
return {
|
|
7
11
|
get(identityPath) {
|
|
8
12
|
let existing = recordsByIdentityPath.get(identityPath);
|
|
@@ -11,17 +15,46 @@ export function createModuleStore(options = {}) {
|
|
|
11
15
|
let record = {
|
|
12
16
|
identityPath,
|
|
13
17
|
invalidationVersion: 0,
|
|
18
|
+
links: createEmptyLinks(),
|
|
14
19
|
trackedFiles: new Set(),
|
|
15
20
|
trackedDirectories: new Set(),
|
|
16
21
|
};
|
|
17
22
|
recordsByIdentityPath.set(identityPath, record);
|
|
18
23
|
return record;
|
|
19
24
|
},
|
|
25
|
+
getAcceptedImporters(identityPath) {
|
|
26
|
+
return acceptedImportersByDepPath.get(identityPath) ?? emptyImporters;
|
|
27
|
+
},
|
|
28
|
+
getHmrUpdateTimestamp(identityPath) {
|
|
29
|
+
return recordsByIdentityPath.get(identityPath)?.hmrUpdateTimestamp;
|
|
30
|
+
},
|
|
31
|
+
getImporters(identityPath) {
|
|
32
|
+
return importersByDepPath.get(identityPath) ?? emptyImporters;
|
|
33
|
+
},
|
|
34
|
+
getLastResolved(identityPath) {
|
|
35
|
+
return recordsByIdentityPath.get(identityPath)?.lastResolved;
|
|
36
|
+
},
|
|
37
|
+
isEmittedFresh(record) {
|
|
38
|
+
return record.emittedVersion === record.invalidationVersion;
|
|
39
|
+
},
|
|
40
|
+
isResolvedFresh(record) {
|
|
41
|
+
return record.resolvedVersion === record.invalidationVersion;
|
|
42
|
+
},
|
|
43
|
+
isTransformedFresh(record) {
|
|
44
|
+
return record.transformedVersion === record.invalidationVersion;
|
|
45
|
+
},
|
|
46
|
+
setHmrUpdateTimestamp(identityPath, timestamp) {
|
|
47
|
+
let record = getOrCreateMutableRecord(identityPath);
|
|
48
|
+
record.hmrUpdateTimestamp = timestamp;
|
|
49
|
+
},
|
|
20
50
|
clearTransformed(identityPath, tracking) {
|
|
21
51
|
let record = getOrCreateMutableRecord(identityPath);
|
|
22
52
|
record.transformed = undefined;
|
|
53
|
+
record.transformedVersion = undefined;
|
|
23
54
|
record.resolved = undefined;
|
|
55
|
+
record.resolvedVersion = undefined;
|
|
24
56
|
record.emitted = undefined;
|
|
57
|
+
record.emittedVersion = undefined;
|
|
25
58
|
record.emittedSnapshot = undefined;
|
|
26
59
|
record.staleEmitted = undefined;
|
|
27
60
|
record.staleEmittedSnapshot = undefined;
|
|
@@ -30,8 +63,11 @@ export function createModuleStore(options = {}) {
|
|
|
30
63
|
setTransformed(identityPath, transformed, tracking) {
|
|
31
64
|
let record = getOrCreateMutableRecord(identityPath);
|
|
32
65
|
record.transformed = transformed;
|
|
66
|
+
record.transformedVersion = record.invalidationVersion;
|
|
33
67
|
record.resolved = undefined;
|
|
68
|
+
record.resolvedVersion = undefined;
|
|
34
69
|
record.emitted = undefined;
|
|
70
|
+
record.emittedVersion = undefined;
|
|
35
71
|
record.emittedSnapshot = undefined;
|
|
36
72
|
record.staleEmitted = undefined;
|
|
37
73
|
record.staleEmittedSnapshot = undefined;
|
|
@@ -39,17 +75,25 @@ export function createModuleStore(options = {}) {
|
|
|
39
75
|
},
|
|
40
76
|
setResolved(identityPath, resolved, tracking) {
|
|
41
77
|
let record = getOrCreateMutableRecord(identityPath);
|
|
78
|
+
removeResolvedIndexes(record);
|
|
42
79
|
record.resolved = resolved;
|
|
80
|
+
record.resolvedVersion = record.invalidationVersion;
|
|
81
|
+
record.lastResolved = resolved;
|
|
82
|
+
record.links = createLinks(resolved);
|
|
43
83
|
record.emitted = undefined;
|
|
84
|
+
record.emittedVersion = undefined;
|
|
44
85
|
record.emittedSnapshot = undefined;
|
|
45
86
|
record.staleEmitted = undefined;
|
|
46
87
|
record.staleEmittedSnapshot = undefined;
|
|
47
88
|
setTracking(record, tracking);
|
|
89
|
+
addResolvedIndexes(record);
|
|
48
90
|
},
|
|
49
91
|
clearResolved(identityPath, tracking) {
|
|
50
92
|
let record = getOrCreateMutableRecord(identityPath);
|
|
51
93
|
record.resolved = undefined;
|
|
94
|
+
record.resolvedVersion = undefined;
|
|
52
95
|
record.emitted = undefined;
|
|
96
|
+
record.emittedVersion = undefined;
|
|
53
97
|
record.emittedSnapshot = undefined;
|
|
54
98
|
record.staleEmitted = undefined;
|
|
55
99
|
record.staleEmittedSnapshot = undefined;
|
|
@@ -58,6 +102,7 @@ export function createModuleStore(options = {}) {
|
|
|
58
102
|
setEmitted(identityPath, emitted, snapshot) {
|
|
59
103
|
let record = getOrCreateMutableRecord(identityPath);
|
|
60
104
|
record.emitted = emitted;
|
|
105
|
+
record.emittedVersion = record.invalidationVersion;
|
|
61
106
|
record.emittedSnapshot = snapshot ?? undefined;
|
|
62
107
|
record.staleEmitted = undefined;
|
|
63
108
|
record.staleEmittedSnapshot = undefined;
|
|
@@ -73,19 +118,28 @@ export function createModuleStore(options = {}) {
|
|
|
73
118
|
}
|
|
74
119
|
for (let identityPath of affected) {
|
|
75
120
|
let record = recordsByIdentityPath.get(identityPath);
|
|
76
|
-
if (record)
|
|
77
|
-
|
|
121
|
+
if (record) {
|
|
122
|
+
if (event === 'change') {
|
|
123
|
+
invalidateContent(record, { retainStale: true });
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
invalidateGraph(record);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
78
129
|
}
|
|
79
130
|
if (event === 'unlink') {
|
|
80
131
|
let deletedRecord = recordsByIdentityPath.get(filePath);
|
|
81
132
|
if (deletedRecord) {
|
|
133
|
+
if (!affected.has(filePath)) {
|
|
134
|
+
invalidateGraph(deletedRecord);
|
|
135
|
+
}
|
|
82
136
|
clearTracking(deletedRecord);
|
|
83
137
|
}
|
|
84
138
|
}
|
|
85
139
|
},
|
|
86
140
|
invalidateAll() {
|
|
87
141
|
for (let record of recordsByIdentityPath.values()) {
|
|
88
|
-
|
|
142
|
+
invalidateGraph(record);
|
|
89
143
|
}
|
|
90
144
|
},
|
|
91
145
|
};
|
|
@@ -96,13 +150,14 @@ export function createModuleStore(options = {}) {
|
|
|
96
150
|
let record = {
|
|
97
151
|
identityPath,
|
|
98
152
|
invalidationVersion: 0,
|
|
153
|
+
links: createEmptyLinks(),
|
|
99
154
|
trackedFiles: new Set(),
|
|
100
155
|
trackedDirectories: new Set(),
|
|
101
156
|
};
|
|
102
157
|
recordsByIdentityPath.set(identityPath, record);
|
|
103
158
|
return record;
|
|
104
159
|
}
|
|
105
|
-
function
|
|
160
|
+
function invalidateContent(record, options) {
|
|
106
161
|
if (!options.retainStale) {
|
|
107
162
|
record.staleEmitted = undefined;
|
|
108
163
|
record.staleEmittedSnapshot = undefined;
|
|
@@ -115,14 +170,39 @@ export function createModuleStore(options = {}) {
|
|
|
115
170
|
record.staleEmitted = undefined;
|
|
116
171
|
record.staleEmittedSnapshot = undefined;
|
|
117
172
|
}
|
|
118
|
-
record.emitted = undefined;
|
|
119
|
-
record.emittedSnapshot = undefined;
|
|
120
|
-
record.resolved = undefined;
|
|
121
|
-
record.transformed = undefined;
|
|
122
173
|
record.invalidationVersion += 1;
|
|
123
174
|
}
|
|
175
|
+
function invalidateGraph(record) {
|
|
176
|
+
record.hmrUpdateTimestamp = undefined;
|
|
177
|
+
invalidateContent(record, { retainStale: false });
|
|
178
|
+
}
|
|
179
|
+
function createLinks(resolved) {
|
|
180
|
+
return {
|
|
181
|
+
acceptedDependencies: new Set(options.getAcceptedDependencies?.(resolved) ?? []),
|
|
182
|
+
dependencies: new Set(options.getDependencies?.(resolved) ?? []),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function createEmptyLinks() {
|
|
186
|
+
return {
|
|
187
|
+
acceptedDependencies: new Set(),
|
|
188
|
+
dependencies: new Set(),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function addResolvedIndexes(record) {
|
|
192
|
+
for (let depPath of record.links.dependencies) {
|
|
193
|
+
addToIndexedSet(importersByDepPath, depPath, record.identityPath);
|
|
194
|
+
}
|
|
195
|
+
for (let depPath of record.links.acceptedDependencies) {
|
|
196
|
+
addToIndexedSet(acceptedImportersByDepPath, depPath, record.identityPath);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function removeResolvedIndexes(record) {
|
|
200
|
+
removeFromIndexedSets(importersByDepPath, record.identityPath);
|
|
201
|
+
removeFromIndexedSets(acceptedImportersByDepPath, record.identityPath);
|
|
202
|
+
}
|
|
124
203
|
function setTracking(record, tracking) {
|
|
125
204
|
let previousWatchedDirectories = getWatchedDirectories(record);
|
|
205
|
+
let previousWatchedFiles = new Set(record.trackedFiles);
|
|
126
206
|
removeIndexes(record);
|
|
127
207
|
let normalizedTracking = mergeTracking(tracking);
|
|
128
208
|
record.trackedFiles = normalizedTracking.trackedFiles;
|
|
@@ -131,8 +211,10 @@ export function createModuleStore(options = {}) {
|
|
|
131
211
|
addToIndexedSet(recordsByTrackedFile, trackedFile, record.identityPath);
|
|
132
212
|
}
|
|
133
213
|
let nextWatchedDirectories = getWatchedDirectories(record);
|
|
134
|
-
let
|
|
135
|
-
|
|
214
|
+
let directoryDelta = updateWatchDirectoryRefCounts(previousWatchedDirectories, nextWatchedDirectories);
|
|
215
|
+
let fileDelta = updateWatchFileRefCounts(previousWatchedFiles, record.trackedFiles);
|
|
216
|
+
emitWatchDirectoryDelta(directoryDelta);
|
|
217
|
+
emitWatchFileDelta(fileDelta);
|
|
136
218
|
}
|
|
137
219
|
function clearTracking(record) {
|
|
138
220
|
setTracking(record, []);
|
|
@@ -170,6 +252,34 @@ export function createModuleStore(options = {}) {
|
|
|
170
252
|
}
|
|
171
253
|
return { add, remove };
|
|
172
254
|
}
|
|
255
|
+
function updateWatchFileRefCounts(previousWatchedFiles, nextWatchedFiles) {
|
|
256
|
+
let add = [];
|
|
257
|
+
let remove = [];
|
|
258
|
+
for (let file of previousWatchedFiles) {
|
|
259
|
+
if (nextWatchedFiles.has(file))
|
|
260
|
+
continue;
|
|
261
|
+
let previousCount = watchFileRefCountByPath.get(file);
|
|
262
|
+
if (!previousCount)
|
|
263
|
+
continue;
|
|
264
|
+
if (previousCount === 1) {
|
|
265
|
+
watchFileRefCountByPath.delete(file);
|
|
266
|
+
remove.push(file);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
watchFileRefCountByPath.set(file, previousCount - 1);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
for (let file of nextWatchedFiles) {
|
|
273
|
+
if (previousWatchedFiles.has(file))
|
|
274
|
+
continue;
|
|
275
|
+
let previousCount = watchFileRefCountByPath.get(file) ?? 0;
|
|
276
|
+
watchFileRefCountByPath.set(file, previousCount + 1);
|
|
277
|
+
if (previousCount === 0) {
|
|
278
|
+
add.push(file);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return { add, remove };
|
|
282
|
+
}
|
|
173
283
|
function emitWatchDirectoryDelta(delta) {
|
|
174
284
|
if (!options.onWatchDirectoriesChange)
|
|
175
285
|
return;
|
|
@@ -177,6 +287,13 @@ export function createModuleStore(options = {}) {
|
|
|
177
287
|
return;
|
|
178
288
|
options.onWatchDirectoriesChange(delta);
|
|
179
289
|
}
|
|
290
|
+
function emitWatchFileDelta(delta) {
|
|
291
|
+
if (!options.onWatchFilesChange)
|
|
292
|
+
return;
|
|
293
|
+
if (delta.add.length === 0 && delta.remove.length === 0)
|
|
294
|
+
return;
|
|
295
|
+
options.onWatchFilesChange(delta);
|
|
296
|
+
}
|
|
180
297
|
}
|
|
181
298
|
function addToIndexedSet(map, key, value) {
|
|
182
299
|
let existing = map.get(key) ?? new Set();
|
|
@@ -192,6 +309,14 @@ function removeFromIndexedSet(map, key, value) {
|
|
|
192
309
|
map.delete(key);
|
|
193
310
|
}
|
|
194
311
|
}
|
|
312
|
+
function removeFromIndexedSets(map, value) {
|
|
313
|
+
for (let [key, values] of map) {
|
|
314
|
+
values.delete(value);
|
|
315
|
+
if (values.size === 0) {
|
|
316
|
+
map.delete(key);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
195
320
|
function matchesTrackedDirectory(trackedDirectories, filePath) {
|
|
196
321
|
for (let trackedDirectory of trackedDirectories) {
|
|
197
322
|
if (filePath === trackedDirectory || filePath.startsWith(`${trackedDirectory}/`))
|
package/dist/lib/routes.d.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
interface
|
|
2
|
-
|
|
1
|
+
interface MountConfig {
|
|
2
|
+
mounts: Readonly<Record<string, string>>;
|
|
3
3
|
rootDir: string;
|
|
4
4
|
}
|
|
5
5
|
export interface CompiledRoutes {
|
|
6
6
|
resolveUrlPathname(pathname: string): string | null;
|
|
7
|
+
matchUrlPathname(pathname: string): AssetRouteMatch | null;
|
|
7
8
|
toUrlPathname(filePath: string): string | null;
|
|
9
|
+
matchFilePath(filePath: string): AssetRouteMatch | null;
|
|
8
10
|
}
|
|
9
|
-
export
|
|
11
|
+
export interface AssetRouteMatch {
|
|
12
|
+
filePath: string;
|
|
13
|
+
fileRoot: string;
|
|
14
|
+
urlPathname: string;
|
|
15
|
+
urlRoot: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function compileRoutes(basePath: string, mountConfigs: readonly MountConfig[]): CompiledRoutes;
|
|
10
18
|
export {};
|
|
11
19
|
//# sourceMappingURL=routes.d.ts.map
|
package/dist/lib/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/lib/routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/lib/routes.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxC,OAAO,EAAE,MAAM,CAAA;CAChB;AASD,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAA;IAC1D,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC9C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAA;CACxD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,SAAS,WAAW,EAAE,GACnC,cAAc,CA8DhB"}
|
package/dist/lib/routes.js
CHANGED
|
@@ -1,99 +1,143 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
throw new Error('createAssetServer() requires at least one configured fileMap entry.');
|
|
14
|
-
}
|
|
15
|
-
let compiledRoutes = routeConfigs.flatMap((routeConfig) => Object.entries(routeConfig.fileMap).map(([urlPattern, filePattern]) => compileRoute({
|
|
16
|
-
filePattern,
|
|
17
|
-
urlPattern,
|
|
18
|
-
}, {
|
|
19
|
-
basePath,
|
|
20
|
-
rootDir: routeConfig.rootDir,
|
|
21
|
-
})));
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { isAbsoluteFilePath, normalizeFilePath, normalizePathname, resolveFilePath, } from './paths.js';
|
|
3
|
+
export function compileRoutes(basePath, mountConfigs) {
|
|
4
|
+
let compiledMounts = mountConfigs.flatMap((mountConfig) => {
|
|
5
|
+
let configMounts = Object.entries(mountConfig.mounts).map(([urlRoot, fileRoot]) => compileMount(urlRoot, fileRoot, {
|
|
6
|
+
basePath,
|
|
7
|
+
rootDir: mountConfig.rootDir,
|
|
8
|
+
}));
|
|
9
|
+
validateNoOverlappingMounts(configMounts);
|
|
10
|
+
return configMounts;
|
|
11
|
+
});
|
|
12
|
+
validateNoOverlappingUrlRoots(compiledMounts);
|
|
22
13
|
return {
|
|
23
14
|
resolveUrlPathname(pathname) {
|
|
24
|
-
|
|
25
|
-
for (let route of compiledRoutes) {
|
|
26
|
-
let match = route.urlMatcher.match(`http://remix.run${normalizedPathname}`);
|
|
27
|
-
if (!match)
|
|
28
|
-
continue;
|
|
29
|
-
let relativeFilePath = decodeURIComponent(createHref(route.filePattern, match.params)).replace(/^\/+/, '');
|
|
30
|
-
return resolveFilePath(route.rootDir, relativeFilePath);
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
15
|
+
return matchUrlPathname(pathname)?.filePath ?? null;
|
|
33
16
|
},
|
|
17
|
+
matchUrlPathname,
|
|
34
18
|
toUrlPathname(filePath) {
|
|
35
|
-
|
|
36
|
-
for (let route of compiledRoutes) {
|
|
37
|
-
let relativeFilePath = getRelativeFilePath(route.rootDir, normalizedFilePath);
|
|
38
|
-
let match = route.fileMatcher.match(`http://remix.run/${relativeFilePath}`);
|
|
39
|
-
if (!match)
|
|
40
|
-
continue;
|
|
41
|
-
return normalizePathname(createHref(route.urlPattern, match.params));
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
19
|
+
return matchFilePath(filePath)?.urlPathname ?? null;
|
|
44
20
|
},
|
|
21
|
+
matchFilePath,
|
|
45
22
|
};
|
|
23
|
+
function matchUrlPathname(pathname) {
|
|
24
|
+
let normalizedPathname = normalizePathname(pathname);
|
|
25
|
+
for (let mount of compiledMounts) {
|
|
26
|
+
let relativePathname = getPathWithinRoot(mount.urlRoot, normalizedPathname);
|
|
27
|
+
if (relativePathname === null)
|
|
28
|
+
continue;
|
|
29
|
+
let filePath = resolveFilePath(mount.fileRoot, decodeURIComponent(relativePathname));
|
|
30
|
+
if (getPathWithinRoot(mount.fileRoot, filePath) === null)
|
|
31
|
+
return null;
|
|
32
|
+
return {
|
|
33
|
+
filePath,
|
|
34
|
+
fileRoot: mount.fileRootValue,
|
|
35
|
+
urlPathname: normalizedPathname,
|
|
36
|
+
urlRoot: mount.urlRoot,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function matchFilePath(filePath) {
|
|
42
|
+
let normalizedFilePath = normalizeFilePath(filePath);
|
|
43
|
+
for (let mount of compiledMounts) {
|
|
44
|
+
let relativeFilePath = getPathWithinRoot(mount.fileRoot, normalizedFilePath);
|
|
45
|
+
if (relativeFilePath === null)
|
|
46
|
+
continue;
|
|
47
|
+
let encodedFilePath = relativeFilePath.split('/').map(encodeURIComponent).join('/');
|
|
48
|
+
return {
|
|
49
|
+
filePath: normalizedFilePath,
|
|
50
|
+
fileRoot: mount.fileRootValue,
|
|
51
|
+
urlPathname: joinUrlPath(mount.urlRoot, encodedFilePath),
|
|
52
|
+
urlRoot: mount.urlRoot,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
46
57
|
}
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
let filePatternSource = normalizeFilePattern(route.filePattern);
|
|
52
|
-
let urlPattern = RoutePattern.parse(urlPatternSource);
|
|
53
|
-
let filePattern = RoutePattern.parse(filePatternSource);
|
|
54
|
-
validateNoUnnamedWildcards(urlPattern, 'URL');
|
|
55
|
-
validateNoUnnamedWildcards(filePattern, 'File');
|
|
56
|
-
validateRoutePatterns(urlPattern, filePattern);
|
|
58
|
+
function compileMount(urlRoot, fileRoot, options) {
|
|
59
|
+
if (isAbsoluteFilePath(fileRoot)) {
|
|
60
|
+
throw new TypeError(`mounts values must be relative to rootDir. Received "${fileRoot}".`);
|
|
61
|
+
}
|
|
57
62
|
return {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
fileMatcher: createMatcher(stripDotSegments(filePatternSource)),
|
|
63
|
+
fileRoot: resolveMountFileRoot(options.rootDir, fileRoot),
|
|
64
|
+
fileRootValue: fileRoot,
|
|
65
|
+
urlRoot: joinUrlPath(normalizeMountUrlRoot(options.basePath), normalizeMountUrlRoot(urlRoot)),
|
|
66
|
+
urlRootKey: urlRoot,
|
|
63
67
|
};
|
|
64
68
|
}
|
|
65
|
-
function
|
|
66
|
-
let
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
segments.push(segment);
|
|
69
|
+
function normalizeMountUrlRoot(urlRoot) {
|
|
70
|
+
let normalizedRoot = normalizePathname(urlRoot).replace(/\/+$/, '') || '/';
|
|
71
|
+
let url = new URL(normalizedRoot, 'http://remix.run');
|
|
72
|
+
if (url.search !== '' ||
|
|
73
|
+
url.hash !== '' ||
|
|
74
|
+
getUrlPathSegmentCount(url.pathname) !== getUrlPathSegmentCount(normalizedRoot)) {
|
|
75
|
+
throw new TypeError(`mounts keys must be URL pathnames without query strings, fragments, or encoded dot segments. Received "${urlRoot}".`);
|
|
75
76
|
}
|
|
76
|
-
return
|
|
77
|
+
return url.pathname.replace(/\/+$/, '') || '/';
|
|
77
78
|
}
|
|
78
|
-
function
|
|
79
|
-
let
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
function resolveMountFileRoot(rootDir, fileRoot) {
|
|
80
|
+
let resolvedRoot = resolveFilePath(rootDir, fileRoot);
|
|
81
|
+
try {
|
|
82
|
+
resolvedRoot = normalizeFilePath(fs.realpathSync(resolvedRoot));
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (!isUnresolvedPathError(error, resolvedRoot))
|
|
86
|
+
throw error;
|
|
83
87
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
return resolvedRoot.replace(/\/+$/, '') || '/';
|
|
89
|
+
}
|
|
90
|
+
function getUrlPathSegmentCount(pathname) {
|
|
91
|
+
return pathname.split('/').filter((segment) => segment !== '').length;
|
|
92
|
+
}
|
|
93
|
+
function joinUrlPath(root, path) {
|
|
94
|
+
if (path === '' || path === '/')
|
|
95
|
+
return normalizeMountUrlRoot(root);
|
|
96
|
+
return normalizePathname(`${root.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`);
|
|
97
|
+
}
|
|
98
|
+
function getPathWithinRoot(root, value) {
|
|
99
|
+
if (value === root)
|
|
100
|
+
return '';
|
|
101
|
+
if (root === '/')
|
|
102
|
+
return value.slice(1);
|
|
103
|
+
if (!value.startsWith(`${root}/`))
|
|
104
|
+
return null;
|
|
105
|
+
return value.slice(root.length + 1);
|
|
106
|
+
}
|
|
107
|
+
function validateNoOverlappingMounts(mounts) {
|
|
108
|
+
for (let index = 0; index < mounts.length; index++) {
|
|
109
|
+
let mount = mounts[index];
|
|
110
|
+
for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
|
|
111
|
+
let otherMount = mounts[otherIndex];
|
|
112
|
+
if (rootsOverlap(mount.fileRoot, otherMount.fileRoot)) {
|
|
113
|
+
throw new TypeError(`mounts values must not overlap. Received "${mount.fileRootValue}" and "${otherMount.fileRootValue}", resolving to "${mount.fileRoot}" and "${otherMount.fileRoot}".`);
|
|
114
|
+
}
|
|
89
115
|
}
|
|
90
116
|
}
|
|
91
117
|
}
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
|
|
118
|
+
function validateNoOverlappingUrlRoots(mounts) {
|
|
119
|
+
for (let index = 0; index < mounts.length; index++) {
|
|
120
|
+
let mount = mounts[index];
|
|
121
|
+
for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
|
|
122
|
+
let otherMount = mounts[otherIndex];
|
|
123
|
+
if (!rootsOverlap(mount.urlRoot, otherMount.urlRoot))
|
|
124
|
+
continue;
|
|
125
|
+
throw new TypeError(`mounts keys must not overlap. Received "${mount.urlRootKey}" and "${otherMount.urlRootKey}".`);
|
|
126
|
+
}
|
|
95
127
|
}
|
|
96
128
|
}
|
|
97
|
-
function
|
|
98
|
-
return
|
|
129
|
+
function rootsOverlap(root, otherRoot) {
|
|
130
|
+
return (root === otherRoot ||
|
|
131
|
+
root === '/' ||
|
|
132
|
+
otherRoot === '/' ||
|
|
133
|
+
root.startsWith(`${otherRoot}/`) ||
|
|
134
|
+
otherRoot.startsWith(`${root}/`));
|
|
135
|
+
}
|
|
136
|
+
function isUnresolvedPathError(error, filePath) {
|
|
137
|
+
// Windows reports UNKNOWN rather than ENOENT when a UNC share cannot be reached.
|
|
138
|
+
return (error instanceof Error &&
|
|
139
|
+
'code' in error &&
|
|
140
|
+
(error.code === 'ENOENT' ||
|
|
141
|
+
error.code === 'ENOTDIR' ||
|
|
142
|
+
(error.code === 'UNKNOWN' && filePath.startsWith('//'))));
|
|
99
143
|
}
|