@@ -163,6 +163,9 @@ func writeForm(form *multipart.Writer, meta api.FunctionDeployMetadata, fsys fs.
163
163
if err := importMap .Parse (data ); err != nil {
164
164
return err
165
165
}
166
+ if err := importMap .Resolve (imPath , fsys ); err != nil {
167
+ return err
168
+ }
166
169
// TODO: replace with addFile once edge runtime supports jsonc
167
170
fmt .Fprintf (os .Stderr , "Uploading asset (%s): %s\n " , * meta .Name , imPath )
168
171
f , err := form .CreateFormFile ("file" , imPath )
@@ -201,6 +204,41 @@ func (m *ImportMap) Parse(data []byte) error {
201
204
return nil
202
205
}
203
206
207
+ func (m * ImportMap ) Resolve (imPath string , fsys fs.FS ) error {
208
+ // Resolve all paths relative to current file
209
+ for k , v := range m .Imports {
210
+ m .Imports [k ] = resolveHostPath (imPath , v , fsys )
211
+ }
212
+ for module , mapping := range m .Scopes {
213
+ for k , v := range mapping {
214
+ m.Scopes [module ][k ] = resolveHostPath (imPath , v , fsys )
215
+ }
216
+ }
217
+ return nil
218
+ }
219
+
220
+ func resolveHostPath (jsonPath , hostPath string , fsys fs.FS ) string {
221
+ // Leave absolute paths unchanged
222
+ if path .IsAbs (hostPath ) {
223
+ return hostPath
224
+ }
225
+ resolved := path .Join (path .Dir (jsonPath ), hostPath )
226
+ if _ , err := fs .Stat (fsys , filepath .FromSlash (resolved )); err != nil {
227
+ // Leave URLs unchanged
228
+ return hostPath
229
+ }
230
+ // Directory imports need to be suffixed with /
231
+ // Ref: https://deno.com/[email protected] /basics/import_maps
232
+ if strings .HasSuffix (hostPath , "/" ) {
233
+ resolved += "/"
234
+ }
235
+ // Relative imports must be prefixed with ./ or ../
236
+ if ! path .IsAbs (resolved ) {
237
+ resolved = "./" + resolved
238
+ }
239
+ return resolved
240
+ }
241
+
204
242
// Ref: https://regex101.com/r/DfBdJA/1
205
243
var importPathPattern = regexp .MustCompile (`(?i)(?:import|export)\s+(?:{[^{}]+}|.*?)\s*(?:from)?\s*['"](.*?)['"]|import\(\s*['"](.*?)['"]\)` )
206
244
@@ -237,22 +275,35 @@ func walkImportPaths(srcPath string, importMap ImportMap, readFile func(curr str
237
275
}
238
276
mod = strings .TrimSpace (mod )
239
277
// Substitute kv from import map
278
+ substituted := false
240
279
for k , v := range importMap .Imports {
241
280
if strings .HasPrefix (mod , k ) {
242
281
mod = v + mod [len (k ):]
282
+ substituted = true
243
283
}
244
284
}
245
- // Deno import path must begin with these prefixes
246
- if strings .HasPrefix (mod , "./" ) || strings .HasPrefix (mod , "../" ) {
247
- mod = path .Join (path .Dir (curr ), mod )
248
- } else if ! strings .HasPrefix (mod , "/" ) {
285
+ // Ignore URLs and directories
286
+ if len (path .Ext (mod )) == 0 {
249
287
continue
250
288
}
251
- if len ( path . Ext ( mod )) > 0 {
252
- // Cleans import path to help detect duplicates
253
- q = append ( q , path . Clean ( mod ))
289
+ // Deno import path must begin with one of these prefixes
290
+ if ! isRelPath ( mod ) && ! isAbsPath ( mod ) {
291
+ continue
254
292
}
293
+ if isRelPath (mod ) && ! substituted {
294
+ mod = path .Join (path .Dir (curr ), mod )
295
+ }
296
+ // Cleans import path to help detect duplicates
297
+ q = append (q , path .Clean (mod ))
255
298
}
256
299
}
257
300
return nil
258
301
}
302
+
303
+ func isRelPath (mod string ) bool {
304
+ return strings .HasPrefix (mod , "./" ) || strings .HasPrefix (mod , "../" )
305
+ }
306
+
307
+ func isAbsPath (mod string ) bool {
308
+ return strings .HasPrefix (mod , "/" )
309
+ }
0 commit comments