@remix-run/assets 0.4.3 → 0.5.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 (76) hide show
  1. package/README.md +322 -56
  2. package/dist/assets.d.ts +2 -1
  3. package/dist/assets.d.ts.map +1 -1
  4. package/dist/assets.js +2 -2
  5. package/dist/lib/access.d.ts +6 -2
  6. package/dist/lib/access.d.ts.map +1 -1
  7. package/dist/lib/access.js +300 -5
  8. package/dist/lib/asset-server.d.ts +118 -5
  9. package/dist/lib/asset-server.d.ts.map +1 -1
  10. package/dist/lib/asset-server.js +260 -24
  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 +7 -6
  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.map +1 -1
  21. package/dist/lib/injected-packages.js +36 -13
  22. package/dist/lib/loaders.d.ts +57 -0
  23. package/dist/lib/loaders.d.ts.map +1 -0
  24. package/dist/lib/loaders.js +1 -0
  25. package/dist/lib/module-store.d.ts +24 -0
  26. package/dist/lib/module-store.d.ts.map +1 -1
  27. package/dist/lib/module-store.js +136 -11
  28. package/dist/lib/routes.d.ts.map +1 -1
  29. package/dist/lib/routes.js +13 -13
  30. package/dist/lib/scripts/compiler.d.ts +24 -1
  31. package/dist/lib/scripts/compiler.d.ts.map +1 -1
  32. package/dist/lib/scripts/compiler.js +183 -29
  33. package/dist/lib/scripts/conditions.d.ts +2 -0
  34. package/dist/lib/scripts/conditions.d.ts.map +1 -0
  35. package/dist/lib/scripts/conditions.js +1 -0
  36. package/dist/lib/scripts/emit.d.ts +3 -0
  37. package/dist/lib/scripts/emit.d.ts.map +1 -1
  38. package/dist/lib/scripts/emit.js +24 -5
  39. package/dist/lib/scripts/resolve.d.ts +4 -0
  40. package/dist/lib/scripts/resolve.d.ts.map +1 -1
  41. package/dist/lib/scripts/resolve.js +70 -5
  42. package/dist/lib/scripts/transform.d.ts +9 -0
  43. package/dist/lib/scripts/transform.d.ts.map +1 -1
  44. package/dist/lib/scripts/transform.js +222 -18
  45. package/dist/lib/source-maps.js +1 -1
  46. package/dist/lib/styles/compiler.d.ts +14 -1
  47. package/dist/lib/styles/compiler.d.ts.map +1 -1
  48. package/dist/lib/styles/compiler.js +78 -14
  49. package/dist/lib/styles/emit.js +4 -4
  50. package/dist/lib/styles/resolve.d.ts.map +1 -1
  51. package/dist/lib/styles/resolve.js +8 -7
  52. package/dist/lib/styles/transform.js +3 -3
  53. package/dist/lib/target.d.ts +1 -1
  54. package/dist/lib/target.d.ts.map +1 -1
  55. package/dist/lib/watch.js +1 -1
  56. package/dist/types/hmr.d.ts +36 -0
  57. package/package.json +17 -11
  58. package/src/assets.ts +2 -1
  59. package/src/lib/access.ts +386 -5
  60. package/src/lib/asset-server.ts +429 -18
  61. package/src/lib/compilation-error.ts +1 -0
  62. package/src/lib/files/compiler.ts +7 -3
  63. package/src/lib/hmr.ts +397 -0
  64. package/src/lib/injected-packages.ts +41 -11
  65. package/src/lib/loaders.ts +80 -0
  66. package/src/lib/module-store.ts +190 -9
  67. package/src/lib/routes.ts +24 -14
  68. package/src/lib/scripts/compiler.ts +248 -24
  69. package/src/lib/scripts/conditions.ts +1 -0
  70. package/src/lib/scripts/emit.ts +50 -5
  71. package/src/lib/scripts/resolve.ts +124 -2
  72. package/src/lib/scripts/transform.ts +290 -19
  73. package/src/lib/styles/compiler.ts +108 -8
  74. package/src/lib/styles/emit.ts +1 -1
  75. package/src/lib/styles/resolve.ts +11 -7
  76. package/src/types/hmr.d.ts +36 -0
@@ -14,11 +14,27 @@ export type FileSnapshot = {
14
14
 
15
15
  export type ModuleSnapshot = ReadonlyMap<string, FileSnapshot>
16
16
 
17
+ type ModuleLinksState = {
18
+ acceptedDependencies: ReadonlySet<string>
19
+ dependencies: ReadonlySet<string>
20
+ }
21
+
22
+ type MutableModuleLinks = {
23
+ acceptedDependencies: Set<string>
24
+ dependencies: Set<string>
25
+ }
26
+
17
27
  type ModuleRecordState<transformed, resolved, emitted> = {
28
+ emittedVersion?: number
29
+ hmrUpdateTimestamp?: number
18
30
  identityPath: string
19
31
  invalidationVersion: number
20
32
  transformed?: transformed
33
+ transformedVersion?: number
21
34
  resolved?: resolved
35
+ resolvedVersion?: number
36
+ lastResolved?: resolved
37
+ links: ModuleLinksState
22
38
  emitted?: emitted
23
39
  emittedSnapshot?: ModuleSnapshot
24
40
  staleEmitted?: emitted
@@ -32,10 +48,16 @@ export type ModuleRecord<transformed, resolved, emitted> = Readonly<
32
48
  >
33
49
 
34
50
  type MutableModuleRecord<transformed, resolved, emitted> = {
51
+ emittedVersion?: number
52
+ hmrUpdateTimestamp?: number
35
53
  identityPath: string
36
54
  invalidationVersion: number
37
55
  transformed?: transformed
56
+ transformedVersion?: number
38
57
  resolved?: resolved
58
+ resolvedVersion?: number
59
+ lastResolved?: resolved
60
+ links: MutableModuleLinks
39
61
  emitted?: emitted
40
62
  emittedSnapshot?: ModuleSnapshot
41
63
  staleEmitted?: emitted
@@ -46,6 +68,14 @@ type MutableModuleRecord<transformed, resolved, emitted> = {
46
68
 
47
69
  export type ModuleStore<transformed, resolved, emitted> = {
48
70
  get(identityPath: string): ModuleRecord<transformed, resolved, emitted>
71
+ getAcceptedImporters(identityPath: string): ReadonlySet<string>
72
+ getHmrUpdateTimestamp(identityPath: string): number | undefined
73
+ getImporters(identityPath: string): ReadonlySet<string>
74
+ getLastResolved(identityPath: string): resolved | undefined
75
+ isEmittedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean
76
+ isResolvedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean
77
+ isTransformedFresh(record: ModuleRecord<transformed, resolved, emitted>): boolean
78
+ setHmrUpdateTimestamp(identityPath: string, timestamp: number): void
49
79
  clearTransformed(identityPath: string, tracking: readonly ModuleTracking[]): void
50
80
  setTransformed(
51
81
  identityPath: string,
@@ -61,12 +91,19 @@ export type ModuleStore<transformed, resolved, emitted> = {
61
91
 
62
92
  export function createModuleStore<transformed, resolved, emitted>(
63
93
  options: {
94
+ getAcceptedDependencies?: (resolved: resolved) => readonly string[]
95
+ getDependencies?: (resolved: resolved) => readonly string[]
64
96
  onWatchDirectoriesChange?: (delta: { add: string[]; remove: string[] }) => void
97
+ onWatchFilesChange?: (delta: { add: string[]; remove: string[] }) => void
65
98
  } = {},
66
99
  ): ModuleStore<transformed, resolved, emitted> {
67
100
  let recordsByIdentityPath = new Map<string, MutableModuleRecord<transformed, resolved, emitted>>()
101
+ let importersByDepPath = new Map<string, Set<string>>()
102
+ let acceptedImportersByDepPath = new Map<string, Set<string>>()
68
103
  let recordsByTrackedFile = new Map<string, Set<string>>()
69
104
  let watchDirectoryRefCountByPath = new Map<string, number>()
105
+ let watchFileRefCountByPath = new Map<string, number>()
106
+ let emptyImporters = new Set<string>()
70
107
 
71
108
  return {
72
109
  get(identityPath) {
@@ -76,17 +113,55 @@ export function createModuleStore<transformed, resolved, emitted>(
76
113
  let record: MutableModuleRecord<transformed, resolved, emitted> = {
77
114
  identityPath,
78
115
  invalidationVersion: 0,
116
+ links: createEmptyLinks(),
79
117
  trackedFiles: new Set(),
80
118
  trackedDirectories: new Set(),
81
119
  }
82
120
  recordsByIdentityPath.set(identityPath, record)
83
121
  return record
84
122
  },
123
+
124
+ getAcceptedImporters(identityPath) {
125
+ return acceptedImportersByDepPath.get(identityPath) ?? emptyImporters
126
+ },
127
+
128
+ getHmrUpdateTimestamp(identityPath) {
129
+ return recordsByIdentityPath.get(identityPath)?.hmrUpdateTimestamp
130
+ },
131
+
132
+ getImporters(identityPath) {
133
+ return importersByDepPath.get(identityPath) ?? emptyImporters
134
+ },
135
+
136
+ getLastResolved(identityPath) {
137
+ return recordsByIdentityPath.get(identityPath)?.lastResolved
138
+ },
139
+
140
+ isEmittedFresh(record) {
141
+ return record.emittedVersion === record.invalidationVersion
142
+ },
143
+
144
+ isResolvedFresh(record) {
145
+ return record.resolvedVersion === record.invalidationVersion
146
+ },
147
+
148
+ isTransformedFresh(record) {
149
+ return record.transformedVersion === record.invalidationVersion
150
+ },
151
+
152
+ setHmrUpdateTimestamp(identityPath, timestamp) {
153
+ let record = getOrCreateMutableRecord(identityPath)
154
+ record.hmrUpdateTimestamp = timestamp
155
+ },
156
+
85
157
  clearTransformed(identityPath, tracking) {
86
158
  let record = getOrCreateMutableRecord(identityPath)
87
159
  record.transformed = undefined
160
+ record.transformedVersion = undefined
88
161
  record.resolved = undefined
162
+ record.resolvedVersion = undefined
89
163
  record.emitted = undefined
164
+ record.emittedVersion = undefined
90
165
  record.emittedSnapshot = undefined
91
166
  record.staleEmitted = undefined
92
167
  record.staleEmittedSnapshot = undefined
@@ -96,8 +171,11 @@ export function createModuleStore<transformed, resolved, emitted>(
96
171
  setTransformed(identityPath, transformed, tracking) {
97
172
  let record = getOrCreateMutableRecord(identityPath)
98
173
  record.transformed = transformed
174
+ record.transformedVersion = record.invalidationVersion
99
175
  record.resolved = undefined
176
+ record.resolvedVersion = undefined
100
177
  record.emitted = undefined
178
+ record.emittedVersion = undefined
101
179
  record.emittedSnapshot = undefined
102
180
  record.staleEmitted = undefined
103
181
  record.staleEmittedSnapshot = undefined
@@ -106,18 +184,26 @@ export function createModuleStore<transformed, resolved, emitted>(
106
184
 
107
185
  setResolved(identityPath, resolved, tracking) {
108
186
  let record = getOrCreateMutableRecord(identityPath)
187
+ removeResolvedIndexes(record)
109
188
  record.resolved = resolved
189
+ record.resolvedVersion = record.invalidationVersion
190
+ record.lastResolved = resolved
191
+ record.links = createLinks(resolved)
110
192
  record.emitted = undefined
193
+ record.emittedVersion = undefined
111
194
  record.emittedSnapshot = undefined
112
195
  record.staleEmitted = undefined
113
196
  record.staleEmittedSnapshot = undefined
114
197
  setTracking(record, tracking)
198
+ addResolvedIndexes(record)
115
199
  },
116
200
 
117
201
  clearResolved(identityPath, tracking) {
118
202
  let record = getOrCreateMutableRecord(identityPath)
119
203
  record.resolved = undefined
204
+ record.resolvedVersion = undefined
120
205
  record.emitted = undefined
206
+ record.emittedVersion = undefined
121
207
  record.emittedSnapshot = undefined
122
208
  record.staleEmitted = undefined
123
209
  record.staleEmittedSnapshot = undefined
@@ -127,6 +213,7 @@ export function createModuleStore<transformed, resolved, emitted>(
127
213
  setEmitted(identityPath, emitted, snapshot) {
128
214
  let record = getOrCreateMutableRecord(identityPath)
129
215
  record.emitted = emitted
216
+ record.emittedVersion = record.invalidationVersion
130
217
  record.emittedSnapshot = snapshot ?? undefined
131
218
  record.staleEmitted = undefined
132
219
  record.staleEmittedSnapshot = undefined
@@ -145,12 +232,21 @@ export function createModuleStore<transformed, resolved, emitted>(
145
232
 
146
233
  for (let identityPath of affected) {
147
234
  let record = recordsByIdentityPath.get(identityPath)
148
- if (record) invalidateRecord(record, { retainStale: event === 'change' })
235
+ if (record) {
236
+ if (event === 'change') {
237
+ invalidateContent(record, { retainStale: true })
238
+ } else {
239
+ invalidateGraph(record)
240
+ }
241
+ }
149
242
  }
150
243
 
151
244
  if (event === 'unlink') {
152
245
  let deletedRecord = recordsByIdentityPath.get(filePath)
153
246
  if (deletedRecord) {
247
+ if (!affected.has(filePath)) {
248
+ invalidateGraph(deletedRecord)
249
+ }
154
250
  clearTracking(deletedRecord)
155
251
  }
156
252
  }
@@ -158,7 +254,7 @@ export function createModuleStore<transformed, resolved, emitted>(
158
254
 
159
255
  invalidateAll() {
160
256
  for (let record of recordsByIdentityPath.values()) {
161
- invalidateRecord(record, { retainStale: false })
257
+ invalidateGraph(record)
162
258
  }
163
259
  },
164
260
  }
@@ -172,6 +268,7 @@ export function createModuleStore<transformed, resolved, emitted>(
172
268
  let record: MutableModuleRecord<transformed, resolved, emitted> = {
173
269
  identityPath,
174
270
  invalidationVersion: 0,
271
+ links: createEmptyLinks(),
175
272
  trackedFiles: new Set(),
176
273
  trackedDirectories: new Set(),
177
274
  }
@@ -179,7 +276,7 @@ export function createModuleStore<transformed, resolved, emitted>(
179
276
  return record
180
277
  }
181
278
 
182
- function invalidateRecord(
279
+ function invalidateContent(
183
280
  record: MutableModuleRecord<transformed, resolved, emitted>,
184
281
  options: { retainStale: boolean },
185
282
  ) {
@@ -194,18 +291,51 @@ export function createModuleStore<transformed, resolved, emitted>(
194
291
  record.staleEmittedSnapshot = undefined
195
292
  }
196
293
 
197
- record.emitted = undefined
198
- record.emittedSnapshot = undefined
199
- record.resolved = undefined
200
- record.transformed = undefined
201
294
  record.invalidationVersion += 1
202
295
  }
203
296
 
297
+ function invalidateGraph(record: MutableModuleRecord<transformed, resolved, emitted>) {
298
+ record.hmrUpdateTimestamp = undefined
299
+ invalidateContent(record, { retainStale: false })
300
+ }
301
+
302
+ function createLinks(resolved: resolved): MutableModuleLinks {
303
+ return {
304
+ acceptedDependencies: new Set(options.getAcceptedDependencies?.(resolved) ?? []),
305
+ dependencies: new Set(options.getDependencies?.(resolved) ?? []),
306
+ }
307
+ }
308
+
309
+ function createEmptyLinks(): MutableModuleLinks {
310
+ return {
311
+ acceptedDependencies: new Set(),
312
+ dependencies: new Set(),
313
+ }
314
+ }
315
+
316
+ function addResolvedIndexes(record: MutableModuleRecord<transformed, resolved, emitted>): void {
317
+ for (let depPath of record.links.dependencies) {
318
+ addToIndexedSet(importersByDepPath, depPath, record.identityPath)
319
+ }
320
+
321
+ for (let depPath of record.links.acceptedDependencies) {
322
+ addToIndexedSet(acceptedImportersByDepPath, depPath, record.identityPath)
323
+ }
324
+ }
325
+
326
+ function removeResolvedIndexes(
327
+ record: MutableModuleRecord<transformed, resolved, emitted>,
328
+ ): void {
329
+ removeFromIndexedSets(importersByDepPath, record.identityPath)
330
+ removeFromIndexedSets(acceptedImportersByDepPath, record.identityPath)
331
+ }
332
+
204
333
  function setTracking(
205
334
  record: MutableModuleRecord<transformed, resolved, emitted>,
206
335
  tracking: readonly ModuleTracking[],
207
336
  ) {
208
337
  let previousWatchedDirectories = getWatchedDirectories(record)
338
+ let previousWatchedFiles = new Set(record.trackedFiles)
209
339
  removeIndexes(record)
210
340
 
211
341
  let normalizedTracking = mergeTracking(tracking)
@@ -217,8 +347,13 @@ export function createModuleStore<transformed, resolved, emitted>(
217
347
  }
218
348
 
219
349
  let nextWatchedDirectories = getWatchedDirectories(record)
220
- let delta = updateWatchDirectoryRefCounts(previousWatchedDirectories, nextWatchedDirectories)
221
- emitWatchDirectoryDelta(delta)
350
+ let directoryDelta = updateWatchDirectoryRefCounts(
351
+ previousWatchedDirectories,
352
+ nextWatchedDirectories,
353
+ )
354
+ let fileDelta = updateWatchFileRefCounts(previousWatchedFiles, record.trackedFiles)
355
+ emitWatchDirectoryDelta(directoryDelta)
356
+ emitWatchFileDelta(fileDelta)
222
357
  }
223
358
 
224
359
  function clearTracking(record: MutableModuleRecord<transformed, resolved, emitted>) {
@@ -262,11 +397,48 @@ export function createModuleStore<transformed, resolved, emitted>(
262
397
  return { add, remove }
263
398
  }
264
399
 
400
+ function updateWatchFileRefCounts(
401
+ previousWatchedFiles: ReadonlySet<string>,
402
+ nextWatchedFiles: ReadonlySet<string>,
403
+ ): { add: string[]; remove: string[] } {
404
+ let add: string[] = []
405
+ let remove: string[] = []
406
+
407
+ for (let file of previousWatchedFiles) {
408
+ if (nextWatchedFiles.has(file)) continue
409
+ let previousCount = watchFileRefCountByPath.get(file)
410
+ if (!previousCount) continue
411
+ if (previousCount === 1) {
412
+ watchFileRefCountByPath.delete(file)
413
+ remove.push(file)
414
+ } else {
415
+ watchFileRefCountByPath.set(file, previousCount - 1)
416
+ }
417
+ }
418
+
419
+ for (let file of nextWatchedFiles) {
420
+ if (previousWatchedFiles.has(file)) continue
421
+ let previousCount = watchFileRefCountByPath.get(file) ?? 0
422
+ watchFileRefCountByPath.set(file, previousCount + 1)
423
+ if (previousCount === 0) {
424
+ add.push(file)
425
+ }
426
+ }
427
+
428
+ return { add, remove }
429
+ }
430
+
265
431
  function emitWatchDirectoryDelta(delta: { add: string[]; remove: string[] }): void {
266
432
  if (!options.onWatchDirectoriesChange) return
267
433
  if (delta.add.length === 0 && delta.remove.length === 0) return
268
434
  options.onWatchDirectoriesChange(delta)
269
435
  }
436
+
437
+ function emitWatchFileDelta(delta: { add: string[]; remove: string[] }): void {
438
+ if (!options.onWatchFilesChange) return
439
+ if (delta.add.length === 0 && delta.remove.length === 0) return
440
+ options.onWatchFilesChange(delta)
441
+ }
270
442
  }
271
443
 
272
444
  function addToIndexedSet(map: Map<string, Set<string>>, key: string, value: string) {
@@ -284,6 +456,15 @@ function removeFromIndexedSet(map: Map<string, Set<string>>, key: string, value:
284
456
  }
285
457
  }
286
458
 
459
+ function removeFromIndexedSets(map: Map<string, Set<string>>, value: string): void {
460
+ for (let [key, values] of map) {
461
+ values.delete(value)
462
+ if (values.size === 0) {
463
+ map.delete(key)
464
+ }
465
+ }
466
+ }
467
+
287
468
  function matchesTrackedDirectory(
288
469
  trackedDirectories: ReadonlySet<string>,
289
470
  filePath: string,
package/src/lib/routes.ts CHANGED
@@ -1,4 +1,8 @@
1
- import { RoutePattern } from '@remix-run/route-pattern'
1
+ import {
2
+ getRoutePatternCaptures,
3
+ RoutePattern,
4
+ type RoutePatternCapture,
5
+ } from '@remix-run/route-pattern'
2
6
  import { createHref } from '@remix-run/route-pattern/href'
3
7
  import { createMatcher, type Matcher } from '@remix-run/route-pattern/match'
4
8
 
@@ -73,7 +77,9 @@ export function compileRoutes(
73
77
  for (let route of compiledRoutes) {
74
78
  let match = route.urlMatcher.match(`http://remix.run${normalizedPathname}`)
75
79
  if (!match) continue
76
- let relativeFilePath = createHref(route.filePattern, match.params).replace(/^\/+/, '')
80
+ let relativeFilePath = decodeURIComponent(
81
+ createHref(route.filePattern, match.params),
82
+ ).replace(/^\/+/, '')
77
83
  return resolveFilePath(route.rootDir, relativeFilePath)
78
84
  }
79
85
 
@@ -140,18 +146,18 @@ function stripDotSegments(pattern: string): string {
140
146
  }
141
147
 
142
148
  function validateRoutePatterns(urlPattern: RoutePattern, filePattern: RoutePattern): void {
143
- let urlParams = getPathnameParams(urlPattern)
144
- let fileParams = getPathnameParams(filePattern)
145
- if (urlParams.length !== fileParams.length) {
149
+ let urlCaptures = getPathnameCaptures(urlPattern)
150
+ let fileCaptures = getPathnameCaptures(filePattern)
151
+ if (urlCaptures.length !== fileCaptures.length) {
146
152
  throw new Error(
147
153
  `Route patterns must have matching capture structure.\nURL: ${urlPattern}\nFile: ${filePattern}`,
148
154
  )
149
155
  }
150
156
 
151
- for (let i = 0; i < urlParams.length; i++) {
152
- let urlParam = urlParams[i]
153
- let fileParam = fileParams[i]
154
- if (urlParam.type !== fileParam.type || urlParam.name !== fileParam.name) {
157
+ for (let i = 0; i < urlCaptures.length; i++) {
158
+ let urlCapture = urlCaptures[i]
159
+ let fileCapture = fileCaptures[i]
160
+ if (urlCapture.type !== fileCapture.type || urlCapture.name !== fileCapture.name) {
155
161
  throw new Error(
156
162
  `Route patterns must have matching capture structure.\nURL: ${urlPattern}\nFile: ${filePattern}`,
157
163
  )
@@ -160,17 +166,21 @@ function validateRoutePatterns(urlPattern: RoutePattern, filePattern: RoutePatte
160
166
  }
161
167
 
162
168
  function validateNoUnnamedWildcards(pattern: RoutePattern, label: string): void {
163
- if (pattern.pathname.tokens.some((token) => token.type === '*' && token.name === '*')) {
169
+ if (
170
+ getRoutePatternCaptures(pattern).some(
171
+ (capture) => capture.part === 'pathname' && capture.type === '*' && capture.name === '*',
172
+ )
173
+ ) {
164
174
  throw new Error(
165
175
  `${label} route patterns must use named wildcards for reversible mapping.\nPattern: ${pattern}`,
166
176
  )
167
177
  }
168
178
  }
169
179
 
170
- type PathnameParam = Extract<RoutePattern['pathname']['tokens'][number], { type: ':' | '*' }>
180
+ type PathnameCapture = RoutePatternCapture & { readonly part: 'pathname' }
171
181
 
172
- function getPathnameParams(pattern: RoutePattern): Array<PathnameParam> {
173
- return pattern.pathname.tokens.filter(
174
- (token): token is PathnameParam => token.type === ':' || token.type === '*',
182
+ function getPathnameCaptures(pattern: RoutePattern): Array<PathnameCapture> {
183
+ return getRoutePatternCaptures(pattern).filter(
184
+ (capture): capture is PathnameCapture => capture.part === 'pathname',
175
185
  )
176
186
  }