bare-module-traverse 1.2.6 → 1.3.1

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 CHANGED
@@ -10,36 +10,44 @@ npm i bare-module-traverse
10
10
 
11
11
  For synchronous traversal:
12
12
 
13
- ``` js
13
+ ```js
14
14
  const traverse = require('bare-module-traverse')
15
15
 
16
- function readModule (url) {
16
+ function readModule(url) {
17
17
  // Read `url` if it exists, otherwise `null`
18
18
  }
19
19
 
20
- function * listPrefix (url) {
20
+ function* listPrefix(url) {
21
21
  // Yield URLs that have `url` as a prefix. The list may be empty.
22
22
  }
23
23
 
24
- for (const dependency of traverse(new URL('file:///directory/file.js'), readModule, listPrefix)) {
24
+ for (const dependency of traverse(
25
+ new URL('file:///directory/file.js'),
26
+ readModule,
27
+ listPrefix
28
+ )) {
25
29
  console.log(dependency)
26
30
  }
27
31
  ```
28
32
 
29
33
  For asynchronous traversal:
30
34
 
31
- ``` js
35
+ ```js
32
36
  const traverse = require('bare-module-traverse')
33
37
 
34
- async function readModule (url) {
38
+ async function readModule(url) {
35
39
  // Read `url` if it exists, otherwise `null`
36
40
  }
37
41
 
38
- async function * listPrefix (url) {
42
+ async function* listPrefix(url) {
39
43
  // Yield URLs that have `url` as a prefix. The list may be empty.
40
44
  }
41
45
 
42
- for await (const dependency of traverse(new URL('file:///directory/file.js'), readModule, listPrefix)) {
46
+ for await (const dependency of traverse(
47
+ new URL('file:///directory/file.js'),
48
+ readModule,
49
+ listPrefix
50
+ )) {
43
51
  console.log(dependency)
44
52
  }
45
53
  ```
@@ -53,7 +61,7 @@ Traverse the module graph rooted at `url`, which must be a WHATWG `URL` instance
53
61
  Options include:
54
62
 
55
63
  ```js
56
- {
64
+ options = {
57
65
  resolve: resolve.default
58
66
  }
59
67
  ```
@@ -65,7 +73,7 @@ Options supported by <https://github.com/holepunchto/bare-module-resolve> and <h
65
73
  Synchronously iterate the module graph. Each yielded dependency has the following shape:
66
74
 
67
75
  ```js
68
- {
76
+ dependency = {
69
77
  url: URL,
70
78
  source: 'string' | Buffer, // Source as returned by `readModule()`
71
79
  imports: {
@@ -80,6 +88,8 @@ Asynchronously iterate the module graph. If `readModule` returns a promise or `l
80
88
 
81
89
  ### Resolution
82
90
 
91
+ Module and addon resolution is configurable by providing a resolver function. A resolver function is a generator function that yields values matching the shapes defined by <https://github.com/holepunchto/bare-module-resolve#algorithm>. Several resolvers are provided out of the box to support the most common use cases.
92
+
83
93
  #### `resolve.module`
84
94
 
85
95
  Convenience export from <https://github.com/holepunchto/bare-module-resolve>.
@@ -94,15 +104,73 @@ The default resolver, which simply forwards to <https://github.com/holepunchto/b
94
104
 
95
105
  #### `resolve.bare`
96
106
 
97
- The Bare resolver, which matches the options used by the Bare module system.
107
+ The Bare resolver, which matches the options used by the Bare module system. The resolver accepts the following additional options:
108
+
109
+ ```js
110
+ options = {
111
+ platform: Bare.platform,
112
+ arch: Bare.arch,
113
+ simulator: false,
114
+ host: `${platform}-${arch}${simulator ? '-simulator' : ''}`,
115
+ target: [host]
116
+ }
117
+ ```
118
+
119
+ For single target traversal it is sufficient to pass `platform`, `arch`, `simulator`, and/or `host`. For multi target target traversal pass a list of `target` identifiers instead.
98
120
 
99
121
  #### `resolve.node`
100
122
 
101
- The Node.js resolver, which matches the options used by the Node.js module system.
123
+ The Node.js resolver, which matches the options used by the Node.js module system. The resolver accepts the following additional options:
124
+
125
+ ```js
126
+ options = {
127
+ platform: process.platform,
128
+ arch: process.arch,
129
+ simulator: false,
130
+ host: `${platform}-${arch}${simulator ? '-simulator' : ''}`,
131
+ target: [host]
132
+ }
133
+ ```
134
+
135
+ For single target traversal it is sufficient to pass `platform`, `arch`, `simulator`, and/or `host`. For multi target target traversal pass a list of `target` identifiers instead.
102
136
 
103
137
  ### Algorithm
104
138
 
105
- The following generator functions implement the traversal algorithm. To drive the generator functions, a loop like the following can be used:
139
+ The following generator functions implement the traversal algorithm. The yielded values have the following shape:
140
+
141
+ **Source module**
142
+
143
+ ```js
144
+ next.value = {
145
+ module: URL
146
+ }
147
+ ```
148
+
149
+ **File prefix**
150
+
151
+ ```js
152
+ next.value = {
153
+ prefix: URL
154
+ }
155
+ ```
156
+
157
+ **Dependency subgraph**
158
+
159
+ ```js
160
+ next.value = {
161
+ children: URL
162
+ }
163
+ ```
164
+
165
+ **Dependency node**
166
+
167
+ ```js
168
+ next.value = {
169
+ dependency: URL
170
+ }
171
+ ```
172
+
173
+ To drive the generator functions, a loop like the following can be used:
106
174
 
107
175
  ```js
108
176
  const queue = [traverse.module(url, source, artifacts, visited)]
@@ -116,11 +184,13 @@ while (queue.length > 0) {
116
184
  const value = next.value
117
185
 
118
186
  if (value.module) {
119
- const source = /* Read `value.module` if it exists, otherwise `null` */;
187
+ // Read `value.module` if it exists, otherwise `null`
188
+ let source
120
189
 
121
190
  next = generator.next(source)
122
191
  } else if (value.prefix) {
123
- const modules = /* List the modules that have `value.prefix` as a prefix */;
192
+ // List the modules that have `value.prefix` as a prefix
193
+ let modules
124
194
 
125
195
  next = generator.next(modules)
126
196
  } else {
package/index.js CHANGED
@@ -1,10 +1,15 @@
1
- const { lookupPackageScope } = require('bare-module-resolve')
1
+ const { lookupPackageScope, conditionMatches } = require('bare-module-resolve')
2
2
  const { lookupPrebuildsScope } = require('bare-addon-resolve')
3
3
  const lex = require('bare-module-lexer')
4
4
  const resolve = require('./lib/resolve')
5
5
  const errors = require('./lib/errors')
6
6
 
7
- module.exports = exports = function traverse (entry, opts, readModule, listPrefix) {
7
+ module.exports = exports = function traverse(
8
+ entry,
9
+ opts,
10
+ readModule,
11
+ listPrefix
12
+ ) {
8
13
  if (typeof opts === 'function') {
9
14
  listPrefix = readModule
10
15
  readModule = opts
@@ -16,7 +21,7 @@ module.exports = exports = function traverse (entry, opts, readModule, listPrefi
16
21
  }
17
22
 
18
23
  return {
19
- * [Symbol.iterator] () {
24
+ *[Symbol.iterator]() {
20
25
  const artifacts = { addons: [], assets: [] }
21
26
 
22
27
  const queue = [exports.module(entry, null, artifacts, new Set(), opts)]
@@ -51,7 +56,7 @@ module.exports = exports = function traverse (entry, opts, readModule, listPrefi
51
56
  return artifacts
52
57
  },
53
58
 
54
- async * [Symbol.asyncIterator] () {
59
+ async *[Symbol.asyncIterator]() {
55
60
  const artifacts = { addons: [], assets: [] }
56
61
 
57
62
  const queue = [exports.module(entry, null, artifacts, new Set(), opts)]
@@ -88,51 +93,11 @@ module.exports = exports = function traverse (entry, opts, readModule, listPrefi
88
93
  }
89
94
  }
90
95
 
91
- function * defaultListPrefix () {}
92
-
93
- function addURL (array, url) {
94
- let lo = 0
95
- let hi = array.length - 1
96
-
97
- while (lo <= hi) {
98
- const mid = lo + ((hi - lo) >> 1)
99
- const found = array[mid]
100
-
101
- if (found.href === url.href) return
102
-
103
- if (found.href < url.href) {
104
- lo = mid + 1
105
- } else {
106
- hi = mid - 1
107
- }
108
- }
109
-
110
- array.splice(lo, 0, url)
111
- }
112
-
113
- function removeURL (array, url) {
114
- let lo = 0
115
- let hi = array.length - 1
116
-
117
- while (lo <= hi) {
118
- const mid = lo + ((hi - lo) >> 1)
119
- const found = array[mid]
120
-
121
- if (found.href === url.href) break
122
-
123
- if (found.href < url.href) {
124
- lo = mid + 1
125
- } else {
126
- hi = mid - 1
127
- }
128
- }
129
-
130
- if (array[lo].href === url.href) array.splice(lo, 1)
131
- }
96
+ function* defaultListPrefix() {}
132
97
 
133
98
  exports.resolve = resolve
134
99
 
135
- exports.module = function * (url, source, artifacts, visited, opts = {}) {
100
+ exports.module = function* (url, source, artifacts, visited, opts = {}) {
136
101
  const { resolutions = null } = opts
137
102
 
138
103
  if (visited.has(url.href)) return false
@@ -148,7 +113,16 @@ exports.module = function * (url, source, artifacts, visited, opts = {}) {
148
113
  visited.add(url.href)
149
114
 
150
115
  if (resolutions) {
151
- if (yield * exports.preresolved(url, source, resolutions, artifacts, visited, opts)) {
116
+ if (
117
+ yield* exports.preresolved(
118
+ url,
119
+ source,
120
+ resolutions,
121
+ artifacts,
122
+ visited,
123
+ opts
124
+ )
125
+ ) {
152
126
  return true
153
127
  }
154
128
  }
@@ -161,20 +135,22 @@ exports.module = function * (url, source, artifacts, visited, opts = {}) {
161
135
  if (source !== null) {
162
136
  imports['#package'] = packageURL.href
163
137
 
164
- yield { children: exports.package(packageURL, source, artifacts, visited, opts) }
138
+ yield {
139
+ children: exports.package(packageURL, source, artifacts, visited, opts)
140
+ }
165
141
 
166
142
  break
167
143
  }
168
144
  }
169
145
 
170
- yield * exports.imports(url, source, imports, artifacts, visited, opts)
146
+ yield* exports.imports(url, source, imports, artifacts, visited, opts)
171
147
 
172
148
  yield { dependency: { url, source, imports: compressImportsMap(imports) } }
173
149
 
174
150
  return true
175
151
  }
176
152
 
177
- exports.package = function * (url, source, artifacts, visited, opts = {}) {
153
+ exports.package = function* (url, source, artifacts, visited, opts = {}) {
178
154
  if (visited.has(url.href)) return false
179
155
 
180
156
  visited.add(url.href)
@@ -189,7 +165,9 @@ exports.package = function * (url, source, artifacts, visited, opts = {}) {
189
165
  }
190
166
 
191
167
  if (info.assets) {
192
- yield { children: exports.assets(info.assets, url, artifacts, visited, opts) }
168
+ yield {
169
+ children: exports.assets(info.assets, url, artifacts, visited, opts)
170
+ }
193
171
  }
194
172
 
195
173
  return true
@@ -198,7 +176,14 @@ exports.package = function * (url, source, artifacts, visited, opts = {}) {
198
176
  return false
199
177
  }
200
178
 
201
- exports.preresolved = function * (url, source, resolutions, artifacts, visited, opts = {}) {
179
+ exports.preresolved = function* (
180
+ url,
181
+ source,
182
+ resolutions,
183
+ artifacts,
184
+ visited,
185
+ opts = {}
186
+ ) {
202
187
  const imports = resolutions[url.href]
203
188
 
204
189
  if (typeof imports !== 'object' || imports === null) return false
@@ -213,9 +198,13 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
213
198
  const url = new URL(entry)
214
199
 
215
200
  if (specifier === '#package') {
216
- yield { children: exports.package(url, null, artifacts, visited, opts) }
201
+ yield {
202
+ children: exports.package(url, null, artifacts, visited, opts)
203
+ }
217
204
  } else {
218
- yield { children: exports.module(url, null, artifacts, visited, opts) }
205
+ yield {
206
+ children: exports.module(url, null, artifacts, visited, opts)
207
+ }
219
208
  }
220
209
  } else {
221
210
  stack.unshift(...Object.values(entry))
@@ -228,72 +217,101 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
228
217
  return true
229
218
  }
230
219
 
231
- exports.imports = function * (parentURL, source, imports, artifacts, visited, opts = {}) {
232
- const { resolve = exports.resolve.default, builtinProtocol = 'builtin:', linkedProtocol = 'linked:' } = opts
220
+ exports.imports = function* (
221
+ parentURL,
222
+ source,
223
+ imports,
224
+ artifacts,
225
+ visited,
226
+ opts = {}
227
+ ) {
228
+ const {
229
+ resolve = exports.resolve.default,
230
+ builtinProtocol = 'builtin:',
231
+ linkedProtocol = 'linked:',
232
+ matchedConditions = []
233
+ } = opts
233
234
 
234
235
  let yielded = false
235
236
 
236
237
  for (const entry of lex(source).imports) {
237
- const resolver = resolve(entry, parentURL, opts)
238
-
239
- let next = resolver.next()
240
- let resolved = false
241
238
  let specifier = entry.specifier
242
- let key = 'default'
239
+ let condition = 'default'
243
240
 
244
241
  if (entry.type & lex.constants.ADDON) {
245
242
  specifier = specifier || '.'
246
- key = 'addon'
243
+ condition = 'addon'
247
244
  } else if (entry.type & lex.constants.ASSET) {
248
- key = 'asset'
245
+ condition = 'asset'
249
246
  }
250
247
 
248
+ matchedConditions.push(condition)
249
+
250
+ const resolver = resolve(entry, parentURL, { ...opts, matchedConditions })
251
+
252
+ let next = resolver.next()
253
+ let resolutions = 0
254
+
251
255
  while (next.done !== true) {
252
256
  const value = next.value
253
257
 
254
258
  if (value.package) {
255
259
  next = resolver.next(JSON.parse(yield { module: value.package }))
260
+ } else if (hasResolution(imports, specifier, matchedConditions)) {
261
+ next = resolver.next(false)
256
262
  } else {
257
263
  const url = value.resolution
258
264
 
259
- if (url.protocol === builtinProtocol || url.protocol === linkedProtocol) {
260
- if (key === 'addon') addURL(artifacts.addons, url)
261
- else if (key === 'asset') addURL(artifacts.assets, url)
265
+ let resolved = false
262
266
 
263
- imports[specifier] = { [key]: url.href, ...imports[specifier] }
267
+ if (
268
+ url.protocol === builtinProtocol ||
269
+ url.protocol === linkedProtocol
270
+ ) {
271
+ if (addResolution(imports, specifier, matchedConditions, url)) {
272
+ resolved = yielded = true
273
+ }
274
+ } else {
275
+ const source = yield { module: url }
264
276
 
265
- resolved = yielded = true
277
+ if (source !== null) {
278
+ if (addResolution(imports, specifier, matchedConditions, url)) {
279
+ yield {
280
+ children: exports.module(url, source, artifacts, visited, opts)
281
+ }
266
282
 
267
- break
283
+ resolved = yielded = true
284
+ }
285
+ }
268
286
  }
269
287
 
270
- const source = yield { module: url }
271
-
272
- if (source !== null) {
273
- if (key === 'addon') addURL(artifacts.addons, url)
274
- else if (key === 'asset') addURL(artifacts.assets, url)
288
+ if (resolved) {
289
+ if (condition === 'addon') addURL(artifacts.addons, url)
290
+ else if (condition === 'asset') addURL(artifacts.assets, url)
275
291
 
276
- imports[specifier] = { [key]: url.href, ...imports[specifier] }
277
-
278
- yield { children: exports.module(url, source, artifacts, visited, opts) }
279
-
280
- resolved = yielded = true
281
-
282
- break
292
+ resolutions++
283
293
  }
284
294
 
285
- next = resolver.next()
295
+ next = resolver.next(resolved)
286
296
  }
287
297
  }
288
298
 
289
- if (!resolved) {
290
- switch (key) {
299
+ matchedConditions.pop()
300
+
301
+ if (resolutions === 0) {
302
+ switch (condition) {
291
303
  case 'addon':
292
- throw errors.ADDON_NOT_FOUND(`Cannot find addon '${specifier}' imported from '${parentURL.href}'`)
304
+ throw errors.ADDON_NOT_FOUND(
305
+ `Cannot find addon '${specifier}' imported from '${parentURL.href}'`
306
+ )
293
307
  case 'asset':
294
- throw errors.ASSET_NOT_FOUND(`Cannot find asset '${specifier}' imported from '${parentURL.href}'`)
308
+ throw errors.ASSET_NOT_FOUND(
309
+ `Cannot find asset '${specifier}' imported from '${parentURL.href}'`
310
+ )
295
311
  default:
296
- throw errors.MODULE_NOT_FOUND(`Cannot find module '${specifier}' imported from '${parentURL.href}'`)
312
+ throw errors.MODULE_NOT_FOUND(
313
+ `Cannot find module '${specifier}' imported from '${parentURL.href}'`
314
+ )
297
315
  }
298
316
  }
299
317
  }
@@ -301,30 +319,54 @@ exports.imports = function * (parentURL, source, imports, artifacts, visited, op
301
319
  return yielded
302
320
  }
303
321
 
304
- exports.prebuilds = function * (packageURL, artifacts, visited, opts = {}) {
305
- const [prefix = null] = lookupPrebuildsScope(packageURL, opts)
322
+ exports.prebuilds = function* (packageURL, artifacts, visited, opts = {}) {
323
+ const {
324
+ host = null, // Shorthand for single host resolution
325
+ hosts = host !== null ? [host] : [],
326
+ matchedConditions = []
327
+ } = opts
328
+
329
+ const [prebuildsURL = null] = lookupPrebuildsScope(packageURL, opts)
306
330
 
307
- if (prefix === null) return false
331
+ if (prebuildsURL === null) return false
308
332
 
309
333
  let yielded = false
310
334
 
311
- for (const url of yield { prefix }) {
312
- const source = yield { module: url }
335
+ for (const host of hosts) {
336
+ const prefix = new URL(host + '/', prebuildsURL)
313
337
 
314
- if (source !== null) {
315
- addURL(artifacts.addons, url)
338
+ const conditions = host.split('-')
316
339
 
317
- yield { children: exports.module(url, source, artifacts, visited, opts) }
340
+ matchedConditions.push(...conditions)
318
341
 
319
- yielded = true
342
+ for (const url of yield { prefix }) {
343
+ const source = yield { module: url }
344
+
345
+ if (source !== null) {
346
+ addURL(artifacts.addons, url)
347
+
348
+ yield {
349
+ children: exports.module(url, source, artifacts, visited, opts)
350
+ }
351
+
352
+ yielded = true
353
+ }
320
354
  }
355
+
356
+ for (const _ of conditions) matchedConditions.pop()
321
357
  }
322
358
 
323
359
  return yielded
324
360
  }
325
361
 
326
- exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {}) {
327
- const matches = yield * exports.patternMatches(patterns, parentURL, [], opts)
362
+ exports.assets = function* (
363
+ patterns,
364
+ parentURL,
365
+ artifacts,
366
+ visited,
367
+ opts = {}
368
+ ) {
369
+ const matches = yield* exports.patternMatches(patterns, parentURL, [], opts)
328
370
 
329
371
  let yielded = false
330
372
 
@@ -343,8 +385,13 @@ exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {})
343
385
  return yielded
344
386
  }
345
387
 
346
- exports.patternMatches = function * (pattern, parentURL, matches, opts = {}) {
347
- const { conditions = [] } = opts
388
+ exports.patternMatches = function* patternMatches(
389
+ pattern,
390
+ parentURL,
391
+ matches,
392
+ opts = {}
393
+ ) {
394
+ const { conditions = [], matchedConditions = [] } = opts
348
395
 
349
396
  if (typeof pattern === 'string') {
350
397
  let patternNegate = false
@@ -380,24 +427,127 @@ exports.patternMatches = function * (pattern, parentURL, matches, opts = {}) {
380
427
  }
381
428
  } else if (Array.isArray(pattern)) {
382
429
  for (const patternValue of pattern) {
383
- yield * exports.patternMatches(patternValue, parentURL, matches, opts)
430
+ yield* patternMatches(patternValue, parentURL, matches, opts)
384
431
  }
385
432
  } else if (typeof pattern === 'object' && pattern !== null) {
386
- const keys = Object.keys(pattern)
387
-
388
- for (const p of keys) {
389
- if (p === 'default' || conditions.includes(p)) {
390
- const patternValue = pattern[p]
391
-
392
- return yield * exports.patternMatches(patternValue, parentURL, matches, opts)
433
+ let yielded = false
434
+
435
+ for (const [condition, patternValue, subset] of conditionMatches(
436
+ pattern,
437
+ conditions,
438
+ opts
439
+ )) {
440
+ matchedConditions.push(condition)
441
+
442
+ if (
443
+ yield* patternMatches(patternValue, parentURL, matches, {
444
+ ...opts,
445
+ conditions: subset
446
+ })
447
+ ) {
448
+ yielded = true
393
449
  }
450
+
451
+ matchedConditions.pop()
394
452
  }
453
+
454
+ if (yielded) return true
395
455
  }
396
456
 
397
457
  return matches
398
458
  }
399
459
 
400
- function compressImportsMap (imports) {
460
+ function addURL(array, url) {
461
+ let lo = 0
462
+ let hi = array.length - 1
463
+
464
+ while (lo <= hi) {
465
+ const mid = lo + ((hi - lo) >> 1)
466
+ const found = array[mid]
467
+
468
+ if (found.href === url.href) return
469
+
470
+ if (found.href < url.href) {
471
+ lo = mid + 1
472
+ } else {
473
+ hi = mid - 1
474
+ }
475
+ }
476
+
477
+ array.splice(lo, 0, url)
478
+ }
479
+
480
+ function removeURL(array, url) {
481
+ let lo = 0
482
+ let hi = array.length - 1
483
+
484
+ while (lo <= hi) {
485
+ const mid = lo + ((hi - lo) >> 1)
486
+ const found = array[mid]
487
+
488
+ if (found.href === url.href) break
489
+
490
+ if (found.href < url.href) {
491
+ lo = mid + 1
492
+ } else {
493
+ hi = mid - 1
494
+ }
495
+ }
496
+
497
+ if (array[lo].href === url.href) array.splice(lo, 1)
498
+ }
499
+
500
+ function hasResolution(imports, specifier, conditions) {
501
+ if (specifier in imports === false) return false
502
+
503
+ let current = imports[specifier]
504
+
505
+ for (const key of conditions) {
506
+ if (key in current === false || typeof current[key] !== 'object') {
507
+ return false
508
+ }
509
+
510
+ current = current[key]
511
+ }
512
+
513
+ return true
514
+ }
515
+
516
+ function addResolution(imports, specifier, conditions, url) {
517
+ imports[specifier] = imports[specifier] || {}
518
+
519
+ let current = imports[specifier]
520
+
521
+ for (let i = 0, n = conditions.length - 1; i < n; i++) {
522
+ const key = conditions[i]
523
+
524
+ if (key in current === false) {
525
+ current[key] = {}
526
+ } else if (typeof current[key] !== 'object') {
527
+ current[key] = { default: current[key] }
528
+ }
529
+
530
+ current = current[key]
531
+ }
532
+
533
+ const last = conditions[conditions.length - 1]
534
+
535
+ if (last in current) return false
536
+
537
+ current[last] = url.href
538
+
539
+ if ('default' in current) {
540
+ const value = current.default
541
+
542
+ delete current.default
543
+
544
+ current.default = value
545
+ }
546
+
547
+ return true
548
+ }
549
+
550
+ function compressImportsMap(imports) {
401
551
  const entries = []
402
552
 
403
553
  for (const entry of Object.entries(imports)) {
@@ -409,7 +559,7 @@ function compressImportsMap (imports) {
409
559
  return Object.fromEntries(entries)
410
560
  }
411
561
 
412
- function compressImportsMapEntry (resolved) {
562
+ function compressImportsMapEntry(resolved) {
413
563
  if (typeof resolved === 'string') return resolved
414
564
 
415
565
  let entries = []
@@ -423,13 +573,11 @@ function compressImportsMapEntry (resolved) {
423
573
  if (entry[0] === 'default') primary = entry[1]
424
574
  }
425
575
 
426
- entries = entries.filter(([condition, resolved]) => condition === 'default' || resolved !== primary)
576
+ entries = entries.filter(
577
+ ([condition, resolved]) => condition === 'default' || resolved !== primary
578
+ )
427
579
 
428
- if (entries.length === 1) {
429
- const [condition, resolved] = entries[0]
430
-
431
- if (condition === 'default') return resolved
432
- }
580
+ if (entries.length === 1) return entries[0][1]
433
581
 
434
582
  return Object.fromEntries(entries)
435
583
  }
package/lib/errors.js CHANGED
@@ -1,5 +1,5 @@
1
1
  module.exports = class ModuleTraverseError extends Error {
2
- constructor (msg, code, fn = ModuleTraverseError) {
2
+ constructor(msg, code, fn = ModuleTraverseError) {
3
3
  super(`${code}: ${msg}`)
4
4
  this.code = code
5
5
 
@@ -8,19 +8,31 @@ module.exports = class ModuleTraverseError extends Error {
8
8
  }
9
9
  }
10
10
 
11
- get name () {
11
+ get name() {
12
12
  return 'ModuleTraverseError'
13
13
  }
14
14
 
15
- static MODULE_NOT_FOUND (msg) {
16
- return new ModuleTraverseError(msg, 'MODULE_NOT_FOUND', ModuleTraverseError.MODULE_NOT_FOUND)
15
+ static MODULE_NOT_FOUND(msg) {
16
+ return new ModuleTraverseError(
17
+ msg,
18
+ 'MODULE_NOT_FOUND',
19
+ ModuleTraverseError.MODULE_NOT_FOUND
20
+ )
17
21
  }
18
22
 
19
- static ADDON_NOT_FOUND (msg) {
20
- return new ModuleTraverseError(msg, 'ADDON_NOT_FOUND', ModuleTraverseError.ADDON_NOT_FOUND)
23
+ static ADDON_NOT_FOUND(msg) {
24
+ return new ModuleTraverseError(
25
+ msg,
26
+ 'ADDON_NOT_FOUND',
27
+ ModuleTraverseError.ADDON_NOT_FOUND
28
+ )
21
29
  }
22
30
 
23
- static ASSET_NOT_FOUND (msg) {
24
- return new ModuleTraverseError(msg, 'ASSET_NOT_FOUND', ModuleTraverseError.ASSET_NOT_FOUND)
31
+ static ASSET_NOT_FOUND(msg) {
32
+ return new ModuleTraverseError(
33
+ msg,
34
+ 'ASSET_NOT_FOUND',
35
+ ModuleTraverseError.ASSET_NOT_FOUND
36
+ )
25
37
  }
26
38
  }
@@ -9,32 +9,41 @@ module.exports = function (entry, parentURL, opts = {}) {
9
9
  platform = runtime.platform,
10
10
  arch = runtime.arch,
11
11
  simulator = false,
12
- host = `${platform}-${arch}${simulator ? '-simulator' : ''}`
12
+ host = `${platform}-${arch}${simulator ? '-simulator' : ''}`,
13
+ target = [host]
13
14
  } = opts
14
15
 
15
16
  let extensions
16
- let conditions = ['bare', 'node', platform, arch]
17
-
18
- if (simulator) conditions = [...conditions, 'simulator']
17
+ let conditions = target.map((host) => ['bare', 'node', ...host.split('-')])
19
18
 
20
19
  if (entry.type & lex.constants.ADDON) {
21
20
  extensions = linked ? [] : ['.bare', '.node']
22
- conditions = ['addon', ...conditions]
23
-
24
- return resolve.addon(entry.specifier || '.', parentURL, { extensions, conditions, host, linked, ...opts })
21
+ conditions = conditions.map((conditions) => ['addon', ...conditions])
22
+
23
+ return resolve.addon(entry.specifier || '.', parentURL, {
24
+ extensions,
25
+ conditions,
26
+ hosts: target,
27
+ linked,
28
+ ...opts
29
+ })
25
30
  }
26
31
 
27
32
  if (entry.type & lex.constants.ASSET) {
28
- conditions = ['asset', ...conditions]
33
+ conditions = conditions.map((conditions) => ['asset', ...conditions])
29
34
  } else {
30
35
  extensions = ['.js', '.cjs', '.mjs', '.json', '.bare', '.node']
31
36
 
32
37
  if (entry.type & lex.constants.REQUIRE) {
33
- conditions = ['require', ...conditions]
38
+ conditions = conditions.map((conditions) => ['require', ...conditions])
34
39
  } else if (entry.type & lex.constants.IMPORT) {
35
- conditions = ['import', ...conditions]
40
+ conditions = conditions.map((conditions) => ['import', ...conditions])
36
41
  }
37
42
  }
38
43
 
39
- return resolve.module(entry.specifier, parentURL, { extensions, conditions, ...opts })
44
+ return resolve.module(entry.specifier, parentURL, {
45
+ extensions,
46
+ conditions,
47
+ ...opts
48
+ })
40
49
  }
@@ -8,27 +8,39 @@ module.exports = function (entry, parentURL, opts = {}) {
8
8
  platform = runtime.platform,
9
9
  arch = runtime.arch,
10
10
  simulator = false,
11
- host = `${platform}-${arch}${simulator ? '-simulator' : ''}`
11
+ host = `${platform}-${arch}${simulator ? '-simulator' : ''}`,
12
+ target = [host]
12
13
  } = opts
13
14
 
14
15
  let extensions
15
- let conditions = ['node', platform, arch]
16
-
17
- if (simulator) conditions = [...conditions, 'simulator']
16
+ let conditions
18
17
 
19
18
  if (entry.type & lex.constants.ADDON) {
20
19
  extensions = ['.node']
21
- conditions = ['addon', ...conditions]
22
-
23
- return resolve.addon(entry.specifier || '.', parentURL, { extensions, conditions, host, ...opts })
20
+ conditions = target.map((host) => ['node', 'addon', ...host.split('-')])
21
+
22
+ return resolve.addon(entry.specifier || '.', parentURL, {
23
+ extensions,
24
+ conditions,
25
+ host,
26
+ ...opts
27
+ })
24
28
  }
25
29
 
26
- if (entry.type & lex.constants.REQUIRE) {
30
+ if (entry.type & lex.constants.ASSET) {
31
+ conditions = ['node', 'asset']
32
+ } else if (entry.type & lex.constants.REQUIRE) {
27
33
  extensions = ['.js', '.json', '.node']
28
34
  conditions = ['node', 'require']
29
35
  } else if (entry.type & lex.constants.IMPORT) {
30
36
  conditions = ['node', 'import']
37
+ } else {
38
+ conditions = ['node']
31
39
  }
32
40
 
33
- return resolve.module(entry.specifier, parentURL, { extensions, conditions, ...opts })
41
+ return resolve.module(entry.specifier, parentURL, {
42
+ extensions,
43
+ conditions,
44
+ ...opts
45
+ })
34
46
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-module-traverse",
3
- "version": "1.2.6",
3
+ "version": "1.3.1",
4
4
  "description": "Low-level module graph traversal for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -24,7 +24,7 @@
24
24
  "test": "npm run lint && npm run test:bare && npm run test:node",
25
25
  "test:bare": "bare test.js",
26
26
  "test:node": "node test.js",
27
- "lint": "standard"
27
+ "lint": "prettier . --check"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -43,6 +43,7 @@
43
43
  },
44
44
  "devDependencies": {
45
45
  "brittle": "^3.2.1",
46
- "standard": "^17.0.0"
46
+ "prettier": "^3.4.2",
47
+ "prettier-config-standard": "^7.0.0"
47
48
  }
48
49
  }