@remix-run/assets 0.5.0 → 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 +85 -92
- package/dist/assets.d.ts +2 -0
- package/dist/assets.d.ts.map +1 -1
- package/dist/lib/access.d.ts +29 -2
- package/dist/lib/access.d.ts.map +1 -1
- package/dist/lib/access.js +52 -26
- package/dist/lib/asset-server.d.ts +21 -7
- package/dist/lib/asset-server.d.ts.map +1 -1
- package/dist/lib/asset-server.js +30 -15
- package/dist/lib/compilation-error.d.ts +1 -1
- package/dist/lib/compilation-error.d.ts.map +1 -1
- package/dist/lib/files/compiler.js +2 -2
- 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 +11 -8
- 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/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.js +2 -2
- package/dist/lib/scripts/resolve.js +9 -9
- package/dist/lib/scripts/transform.js +2 -2
- package/dist/lib/styles/resolve.js +8 -8
- package/dist/lib/styles/transform.js +2 -2
- package/package.json +5 -6
- package/src/assets.ts +2 -0
- package/src/lib/access.ts +83 -30
- package/src/lib/asset-server.ts +50 -22
- package/src/lib/compilation-error.ts +3 -3
- package/src/lib/files/compiler.ts +2 -2
- package/src/lib/injected-packages.ts +16 -10
- package/src/lib/inspection.ts +229 -0
- package/src/lib/routes.ts +158 -126
- package/src/lib/scripts/compiler.ts +2 -2
- package/src/lib/scripts/resolve.ts +9 -9
- package/src/lib/scripts/transform.ts +2 -2
- package/src/lib/styles/resolve.ts +8 -8
- package/src/lib/styles/transform.ts +2 -2
package/src/lib/routes.ts
CHANGED
|
@@ -1,186 +1,218 @@
|
|
|
1
|
-
import
|
|
2
|
-
getRoutePatternCaptures,
|
|
3
|
-
RoutePattern,
|
|
4
|
-
type RoutePatternCapture,
|
|
5
|
-
} from '@remix-run/route-pattern'
|
|
6
|
-
import { createHref } from '@remix-run/route-pattern/href'
|
|
7
|
-
import { createMatcher, type Matcher } from '@remix-run/route-pattern/match'
|
|
1
|
+
import * as fs from 'node:fs'
|
|
8
2
|
|
|
9
3
|
import {
|
|
10
|
-
getRelativeFilePath,
|
|
11
4
|
isAbsoluteFilePath,
|
|
12
5
|
normalizeFilePath,
|
|
13
6
|
normalizePathname,
|
|
14
7
|
resolveFilePath,
|
|
15
8
|
} from './paths.ts'
|
|
16
9
|
|
|
17
|
-
interface
|
|
18
|
-
|
|
19
|
-
filePattern: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface RouteConfig {
|
|
23
|
-
fileMap: Readonly<Record<string, string>>
|
|
10
|
+
interface MountConfig {
|
|
11
|
+
mounts: Readonly<Record<string, string>>
|
|
24
12
|
rootDir: string
|
|
25
13
|
}
|
|
26
14
|
|
|
27
|
-
interface
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
fileMatcher: Matcher
|
|
15
|
+
interface CompiledMount {
|
|
16
|
+
fileRoot: string
|
|
17
|
+
fileRootValue: string
|
|
18
|
+
urlRoot: string
|
|
19
|
+
urlRootKey: string
|
|
33
20
|
}
|
|
34
21
|
|
|
35
22
|
export interface CompiledRoutes {
|
|
36
23
|
resolveUrlPathname(pathname: string): string | null
|
|
24
|
+
matchUrlPathname(pathname: string): AssetRouteMatch | null
|
|
37
25
|
toUrlPathname(filePath: string): string | null
|
|
26
|
+
matchFilePath(filePath: string): AssetRouteMatch | null
|
|
38
27
|
}
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return normalizePathname(pattern)
|
|
29
|
+
export interface AssetRouteMatch {
|
|
30
|
+
filePath: string
|
|
31
|
+
fileRoot: string
|
|
32
|
+
urlPathname: string
|
|
33
|
+
urlRoot: string
|
|
48
34
|
}
|
|
49
35
|
|
|
50
36
|
export function compileRoutes(
|
|
51
37
|
basePath: string,
|
|
52
|
-
|
|
38
|
+
mountConfigs: readonly MountConfig[],
|
|
53
39
|
): CompiledRoutes {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
basePath,
|
|
67
|
-
rootDir: routeConfig.rootDir,
|
|
68
|
-
},
|
|
69
|
-
),
|
|
70
|
-
),
|
|
71
|
-
)
|
|
40
|
+
let compiledMounts = mountConfigs.flatMap((mountConfig) => {
|
|
41
|
+
let configMounts = Object.entries(mountConfig.mounts).map(([urlRoot, fileRoot]) =>
|
|
42
|
+
compileMount(urlRoot, fileRoot, {
|
|
43
|
+
basePath,
|
|
44
|
+
rootDir: mountConfig.rootDir,
|
|
45
|
+
}),
|
|
46
|
+
)
|
|
47
|
+
validateNoOverlappingMounts(configMounts)
|
|
48
|
+
return configMounts
|
|
49
|
+
})
|
|
50
|
+
validateNoOverlappingUrlRoots(compiledMounts)
|
|
72
51
|
|
|
73
52
|
return {
|
|
74
53
|
resolveUrlPathname(pathname) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
for (let route of compiledRoutes) {
|
|
78
|
-
let match = route.urlMatcher.match(`http://remix.run${normalizedPathname}`)
|
|
79
|
-
if (!match) continue
|
|
80
|
-
let relativeFilePath = decodeURIComponent(
|
|
81
|
-
createHref(route.filePattern, match.params),
|
|
82
|
-
).replace(/^\/+/, '')
|
|
83
|
-
return resolveFilePath(route.rootDir, relativeFilePath)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return null
|
|
54
|
+
return matchUrlPathname(pathname)?.filePath ?? null
|
|
87
55
|
},
|
|
56
|
+
matchUrlPathname,
|
|
88
57
|
toUrlPathname(filePath) {
|
|
89
|
-
|
|
58
|
+
return matchFilePath(filePath)?.urlPathname ?? null
|
|
59
|
+
},
|
|
60
|
+
matchFilePath,
|
|
61
|
+
}
|
|
90
62
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
function matchUrlPathname(pathname: string): AssetRouteMatch | null {
|
|
64
|
+
let normalizedPathname = normalizePathname(pathname)
|
|
65
|
+
|
|
66
|
+
for (let mount of compiledMounts) {
|
|
67
|
+
let relativePathname = getPathWithinRoot(mount.urlRoot, normalizedPathname)
|
|
68
|
+
if (relativePathname === null) continue
|
|
69
|
+
let filePath = resolveFilePath(mount.fileRoot, decodeURIComponent(relativePathname))
|
|
70
|
+
if (getPathWithinRoot(mount.fileRoot, filePath) === null) return null
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
filePath,
|
|
74
|
+
fileRoot: mount.fileRootValue,
|
|
75
|
+
urlPathname: normalizedPathname,
|
|
76
|
+
urlRoot: mount.urlRoot,
|
|
96
77
|
}
|
|
78
|
+
}
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function matchFilePath(filePath: string): AssetRouteMatch | null {
|
|
84
|
+
let normalizedFilePath = normalizeFilePath(filePath)
|
|
85
|
+
|
|
86
|
+
for (let mount of compiledMounts) {
|
|
87
|
+
let relativeFilePath = getPathWithinRoot(mount.fileRoot, normalizedFilePath)
|
|
88
|
+
if (relativeFilePath === null) continue
|
|
89
|
+
let encodedFilePath = relativeFilePath.split('/').map(encodeURIComponent).join('/')
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
filePath: normalizedFilePath,
|
|
93
|
+
fileRoot: mount.fileRootValue,
|
|
94
|
+
urlPathname: joinUrlPath(mount.urlRoot, encodedFilePath),
|
|
95
|
+
urlRoot: mount.urlRoot,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return null
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
function
|
|
104
|
-
|
|
103
|
+
function compileMount(
|
|
104
|
+
urlRoot: string,
|
|
105
|
+
fileRoot: string,
|
|
105
106
|
options: {
|
|
106
107
|
basePath: string
|
|
107
108
|
rootDir: string
|
|
108
109
|
},
|
|
109
|
-
):
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
`${basePath.replace(/\/+$/, '')}/${relativeUrlPattern.replace(/^\/+/, '')}`,
|
|
114
|
-
)
|
|
115
|
-
let filePatternSource = normalizeFilePattern(route.filePattern)
|
|
116
|
-
|
|
117
|
-
let urlPattern = RoutePattern.parse(urlPatternSource)
|
|
118
|
-
let filePattern = RoutePattern.parse(filePatternSource)
|
|
119
|
-
|
|
120
|
-
validateNoUnnamedWildcards(urlPattern, 'URL')
|
|
121
|
-
validateNoUnnamedWildcards(filePattern, 'File')
|
|
122
|
-
validateRoutePatterns(urlPattern, filePattern)
|
|
110
|
+
): CompiledMount {
|
|
111
|
+
if (isAbsoluteFilePath(fileRoot)) {
|
|
112
|
+
throw new TypeError(`mounts values must be relative to rootDir. Received "${fileRoot}".`)
|
|
113
|
+
}
|
|
123
114
|
|
|
124
115
|
return {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
fileMatcher: createMatcher(stripDotSegments(filePatternSource)),
|
|
116
|
+
fileRoot: resolveMountFileRoot(options.rootDir, fileRoot),
|
|
117
|
+
fileRootValue: fileRoot,
|
|
118
|
+
urlRoot: joinUrlPath(normalizeMountUrlRoot(options.basePath), normalizeMountUrlRoot(urlRoot)),
|
|
119
|
+
urlRootKey: urlRoot,
|
|
130
120
|
}
|
|
131
121
|
}
|
|
132
122
|
|
|
133
|
-
function
|
|
134
|
-
let
|
|
123
|
+
function normalizeMountUrlRoot(urlRoot: string): string {
|
|
124
|
+
let normalizedRoot = normalizePathname(urlRoot).replace(/\/+$/, '') || '/'
|
|
125
|
+
let url = new URL(normalizedRoot, 'http://remix.run')
|
|
135
126
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
127
|
+
if (
|
|
128
|
+
url.search !== '' ||
|
|
129
|
+
url.hash !== '' ||
|
|
130
|
+
getUrlPathSegmentCount(url.pathname) !== getUrlPathSegmentCount(normalizedRoot)
|
|
131
|
+
) {
|
|
132
|
+
throw new TypeError(
|
|
133
|
+
`mounts keys must be URL pathnames without query strings, fragments, or encoded dot segments. Received "${urlRoot}".`,
|
|
134
|
+
)
|
|
143
135
|
}
|
|
144
136
|
|
|
145
|
-
return
|
|
137
|
+
return url.pathname.replace(/\/+$/, '') || '/'
|
|
146
138
|
}
|
|
147
139
|
|
|
148
|
-
function
|
|
149
|
-
let
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
140
|
+
function resolveMountFileRoot(rootDir: string, fileRoot: string): string {
|
|
141
|
+
let resolvedRoot = resolveFilePath(rootDir, fileRoot)
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
resolvedRoot = normalizeFilePath(fs.realpathSync(resolvedRoot))
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (!isUnresolvedPathError(error, resolvedRoot)) throw error
|
|
155
147
|
}
|
|
156
148
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
149
|
+
return resolvedRoot.replace(/\/+$/, '') || '/'
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function getUrlPathSegmentCount(pathname: string): number {
|
|
153
|
+
return pathname.split('/').filter((segment) => segment !== '').length
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function joinUrlPath(root: string, path: string): string {
|
|
157
|
+
if (path === '' || path === '/') return normalizeMountUrlRoot(root)
|
|
158
|
+
return normalizePathname(`${root.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getPathWithinRoot(root: string, value: string): string | null {
|
|
162
|
+
if (value === root) return ''
|
|
163
|
+
if (root === '/') return value.slice(1)
|
|
164
|
+
if (!value.startsWith(`${root}/`)) return null
|
|
165
|
+
return value.slice(root.length + 1)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function validateNoOverlappingMounts(mounts: readonly CompiledMount[]): void {
|
|
169
|
+
for (let index = 0; index < mounts.length; index++) {
|
|
170
|
+
let mount = mounts[index]
|
|
171
|
+
|
|
172
|
+
for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
|
|
173
|
+
let otherMount = mounts[otherIndex]
|
|
174
|
+
|
|
175
|
+
if (rootsOverlap(mount.fileRoot, otherMount.fileRoot)) {
|
|
176
|
+
throw new TypeError(
|
|
177
|
+
`mounts values must not overlap. Received "${mount.fileRootValue}" and "${otherMount.fileRootValue}", resolving to "${mount.fileRoot}" and "${otherMount.fileRoot}".`,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
164
180
|
}
|
|
165
181
|
}
|
|
166
182
|
}
|
|
167
183
|
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
function validateNoOverlappingUrlRoots(mounts: readonly CompiledMount[]): void {
|
|
185
|
+
for (let index = 0; index < mounts.length; index++) {
|
|
186
|
+
let mount = mounts[index]
|
|
187
|
+
|
|
188
|
+
for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
|
|
189
|
+
let otherMount = mounts[otherIndex]
|
|
190
|
+
if (!rootsOverlap(mount.urlRoot, otherMount.urlRoot)) continue
|
|
191
|
+
|
|
192
|
+
throw new TypeError(
|
|
193
|
+
`mounts keys must not overlap. Received "${mount.urlRootKey}" and "${otherMount.urlRootKey}".`,
|
|
194
|
+
)
|
|
195
|
+
}
|
|
177
196
|
}
|
|
178
197
|
}
|
|
179
198
|
|
|
180
|
-
|
|
199
|
+
function rootsOverlap(root: string, otherRoot: string): boolean {
|
|
200
|
+
return (
|
|
201
|
+
root === otherRoot ||
|
|
202
|
+
root === '/' ||
|
|
203
|
+
otherRoot === '/' ||
|
|
204
|
+
root.startsWith(`${otherRoot}/`) ||
|
|
205
|
+
otherRoot.startsWith(`${root}/`)
|
|
206
|
+
)
|
|
207
|
+
}
|
|
181
208
|
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
|
|
209
|
+
function isUnresolvedPathError(error: unknown, filePath: string): boolean {
|
|
210
|
+
// Windows reports UNKNOWN rather than ENOENT when a UNC share cannot be reached.
|
|
211
|
+
return (
|
|
212
|
+
error instanceof Error &&
|
|
213
|
+
'code' in error &&
|
|
214
|
+
(error.code === 'ENOENT' ||
|
|
215
|
+
error.code === 'ENOTDIR' ||
|
|
216
|
+
(error.code === 'UNKNOWN' && filePath.startsWith('//')))
|
|
185
217
|
)
|
|
186
218
|
}
|
|
@@ -514,9 +514,9 @@ export function createScriptCompiler(options: ScriptCompilerOptions): ScriptComp
|
|
|
514
514
|
let stableUrlPathname = resolvedOptions.routes.toUrlPathname(identityPath)
|
|
515
515
|
if (!stableUrlPathname) {
|
|
516
516
|
throw createAssetServerCompilationError(
|
|
517
|
-
`File ${identityPath} is outside all configured
|
|
517
|
+
`File ${identityPath} is outside all configured mounts.`,
|
|
518
518
|
{
|
|
519
|
-
code: '
|
|
519
|
+
code: 'FILE_OUTSIDE_MOUNTS',
|
|
520
520
|
},
|
|
521
521
|
)
|
|
522
522
|
}
|
|
@@ -137,7 +137,7 @@ export async function resolveModule(
|
|
|
137
137
|
return failResolve(
|
|
138
138
|
createAssetServerCompilationError(
|
|
139
139
|
`Failed to resolve import "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
|
|
140
|
-
`Ensure it resolves to a file within
|
|
140
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`,
|
|
141
141
|
{
|
|
142
142
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
143
143
|
},
|
|
@@ -186,10 +186,10 @@ export async function resolveModule(
|
|
|
186
186
|
if (!stableUrlPathname) {
|
|
187
187
|
return failResolve(
|
|
188
188
|
createAssetServerCompilationError(
|
|
189
|
-
`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured
|
|
190
|
-
`Add a matching
|
|
189
|
+
`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
|
|
190
|
+
`Add a matching mount for this file path, or mark this import as external.`,
|
|
191
191
|
{
|
|
192
|
-
code: '
|
|
192
|
+
code: 'IMPORT_OUTSIDE_MOUNTS',
|
|
193
193
|
},
|
|
194
194
|
),
|
|
195
195
|
trackedFiles,
|
|
@@ -254,7 +254,7 @@ export async function resolveModule(
|
|
|
254
254
|
return failResolve(
|
|
255
255
|
createAssetServerCompilationError(
|
|
256
256
|
`Failed to resolve accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
|
|
257
|
-
`Ensure it resolves to a file within
|
|
257
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`,
|
|
258
258
|
{
|
|
259
259
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
260
260
|
},
|
|
@@ -303,10 +303,10 @@ export async function resolveModule(
|
|
|
303
303
|
if (!stableUrlPathname) {
|
|
304
304
|
return failResolve(
|
|
305
305
|
createAssetServerCompilationError(
|
|
306
|
-
`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured
|
|
307
|
-
`Add a matching
|
|
306
|
+
`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
|
|
307
|
+
`Add a matching mount for this file path, or mark this import as external.`,
|
|
308
308
|
{
|
|
309
|
-
code: '
|
|
309
|
+
code: 'IMPORT_OUTSIDE_MOUNTS',
|
|
310
310
|
},
|
|
311
311
|
),
|
|
312
312
|
trackedFiles,
|
|
@@ -462,7 +462,7 @@ async function batchResolveSpecifiers(
|
|
|
462
462
|
normalizedResolution.importerPath === getInjectedPackageImporterPath()
|
|
463
463
|
? `Failed to resolve injected import "${specifier}" from asset server.`
|
|
464
464
|
: `Failed to resolve import "${normalizedResolution.specifier}" in ${normalizedResolution.importerPath}. ` +
|
|
465
|
-
`Ensure it resolves to a file within
|
|
465
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`,
|
|
466
466
|
{
|
|
467
467
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
468
468
|
},
|
|
@@ -225,9 +225,9 @@ export async function transformModule(
|
|
|
225
225
|
let stableUrlPathname = args.routes.toUrlPathname(record.identityPath)
|
|
226
226
|
if (!stableUrlPathname) {
|
|
227
227
|
throw createAssetServerCompilationError(
|
|
228
|
-
`File ${record.identityPath} is outside all configured
|
|
228
|
+
`File ${record.identityPath} is outside all configured mounts.`,
|
|
229
229
|
{
|
|
230
|
-
code: '
|
|
230
|
+
code: 'FILE_OUTSIDE_MOUNTS',
|
|
231
231
|
},
|
|
232
232
|
)
|
|
233
233
|
}
|
|
@@ -175,9 +175,9 @@ export function resolveServedStyleOrThrow(
|
|
|
175
175
|
let stableUrlPathname = args.routes.toUrlPathname(identityPath)
|
|
176
176
|
if (!stableUrlPathname) {
|
|
177
177
|
throw createAssetServerCompilationError(
|
|
178
|
-
`File ${identityPath} is outside all configured
|
|
178
|
+
`File ${identityPath} is outside all configured mounts.`,
|
|
179
179
|
{
|
|
180
|
-
code: '
|
|
180
|
+
code: 'FILE_OUTSIDE_MOUNTS',
|
|
181
181
|
},
|
|
182
182
|
)
|
|
183
183
|
}
|
|
@@ -232,10 +232,10 @@ function resolveImportDependency(
|
|
|
232
232
|
|
|
233
233
|
if (!args.routes.toUrlPathname(identityPath)) {
|
|
234
234
|
throw createAssetServerCompilationError(
|
|
235
|
-
`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured
|
|
236
|
-
`Add a matching
|
|
235
|
+
`Import "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured mounts. ` +
|
|
236
|
+
`Add a matching mount for this file path, or mark this import as external.`,
|
|
237
237
|
{
|
|
238
|
-
code: '
|
|
238
|
+
code: 'IMPORT_OUTSIDE_MOUNTS',
|
|
239
239
|
},
|
|
240
240
|
)
|
|
241
241
|
}
|
|
@@ -302,10 +302,10 @@ function resolveUrlDependency(
|
|
|
302
302
|
|
|
303
303
|
if (!args.routes.toUrlPathname(identityPath)) {
|
|
304
304
|
throw createAssetServerCompilationError(
|
|
305
|
-
`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured
|
|
306
|
-
`Add a matching
|
|
305
|
+
`URL "${url}" in ${importerPath}, resolved to "${identityPath}", is outside all configured mounts. ` +
|
|
306
|
+
`Add a matching mount for this file path.`,
|
|
307
307
|
{
|
|
308
|
-
code: '
|
|
308
|
+
code: 'URL_OUTSIDE_MOUNTS',
|
|
309
309
|
},
|
|
310
310
|
)
|
|
311
311
|
}
|
|
@@ -99,9 +99,9 @@ export async function transformStyle(
|
|
|
99
99
|
let stableUrlPathname = args.routes.toUrlPathname(record.identityPath)
|
|
100
100
|
if (!stableUrlPathname) {
|
|
101
101
|
throw createAssetServerCompilationError(
|
|
102
|
-
`File ${record.identityPath} is outside all configured
|
|
102
|
+
`File ${record.identityPath} is outside all configured mounts.`,
|
|
103
103
|
{
|
|
104
|
-
code: '
|
|
104
|
+
code: 'FILE_OUTSIDE_MOUNTS',
|
|
105
105
|
},
|
|
106
106
|
)
|
|
107
107
|
}
|