bare-module-traverse 1.2.5 → 1.3.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 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,18 +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
+ }
141
+
142
+ break
165
143
  }
166
144
  }
167
145
 
168
- yield * exports.imports(url, source, imports, artifacts, visited, opts)
146
+ yield* exports.imports(url, source, imports, artifacts, visited, opts)
169
147
 
170
148
  yield { dependency: { url, source, imports: compressImportsMap(imports) } }
171
149
 
172
150
  return true
173
151
  }
174
152
 
175
- exports.package = function * (url, source, artifacts, visited, opts = {}) {
153
+ exports.package = function* (url, source, artifacts, visited, opts = {}) {
176
154
  if (visited.has(url.href)) return false
177
155
 
178
156
  visited.add(url.href)
@@ -187,7 +165,9 @@ exports.package = function * (url, source, artifacts, visited, opts = {}) {
187
165
  }
188
166
 
189
167
  if (info.assets) {
190
- yield { children: exports.assets(info.assets, url, artifacts, visited, opts) }
168
+ yield {
169
+ children: exports.assets(info.assets, url, artifacts, visited, opts)
170
+ }
191
171
  }
192
172
 
193
173
  return true
@@ -196,7 +176,14 @@ exports.package = function * (url, source, artifacts, visited, opts = {}) {
196
176
  return false
197
177
  }
198
178
 
199
- 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
+ ) {
200
187
  const imports = resolutions[url.href]
201
188
 
202
189
  if (typeof imports !== 'object' || imports === null) return false
@@ -211,9 +198,13 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
211
198
  const url = new URL(entry)
212
199
 
213
200
  if (specifier === '#package') {
214
- yield { children: exports.package(url, null, artifacts, visited, opts) }
201
+ yield {
202
+ children: exports.package(url, null, artifacts, visited, opts)
203
+ }
215
204
  } else {
216
- yield { children: exports.module(url, null, artifacts, visited, opts) }
205
+ yield {
206
+ children: exports.module(url, null, artifacts, visited, opts)
207
+ }
217
208
  }
218
209
  } else {
219
210
  stack.unshift(...Object.values(entry))
@@ -226,103 +217,145 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
226
217
  return true
227
218
  }
228
219
 
229
- exports.imports = function * (parentURL, source, imports, artifacts, visited, opts = {}) {
230
- 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
231
234
 
232
235
  let yielded = false
233
236
 
234
237
  for (const entry of lex(source).imports) {
235
- const resolver = resolve(entry, parentURL, opts)
236
-
237
- let next = resolver.next()
238
- let resolved = false
239
238
  let specifier = entry.specifier
240
- let key = 'default'
239
+ let condition = 'default'
241
240
 
242
241
  if (entry.type & lex.constants.ADDON) {
243
242
  specifier = specifier || '.'
244
- key = 'addon'
243
+ condition = 'addon'
245
244
  } else if (entry.type & lex.constants.ASSET) {
246
- key = 'asset'
245
+ condition = 'asset'
247
246
  }
248
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
+
249
255
  while (next.done !== true) {
250
256
  const value = next.value
251
257
 
252
258
  if (value.package) {
253
259
  next = resolver.next(JSON.parse(yield { module: value.package }))
260
+ } else if (hasResolution(imports, specifier, matchedConditions)) {
261
+ next = resolver.next(false)
254
262
  } else {
255
263
  const url = value.resolution
256
264
 
257
- if (url.protocol === builtinProtocol || url.protocol === linkedProtocol) {
258
- if (key === 'addon') addURL(artifacts.addons, url)
259
- else if (key === 'asset') addURL(artifacts.assets, url)
265
+ let resolved = false
260
266
 
261
- 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 }
262
276
 
263
- 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
+ }
264
282
 
265
- break
283
+ resolved = yielded = true
284
+ }
285
+ }
266
286
  }
267
287
 
268
- const source = yield { module: url }
269
-
270
- if (source !== null) {
271
- if (key === 'addon') addURL(artifacts.addons, url)
272
- 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)
273
291
 
274
- imports[specifier] = { [key]: url.href, ...imports[specifier] }
275
-
276
- yield { children: exports.module(url, source, artifacts, visited, opts) }
277
-
278
- resolved = yielded = true
279
-
280
- break
292
+ resolutions++
281
293
  }
282
294
 
283
- next = resolver.next()
295
+ next = resolver.next(resolved)
284
296
  }
285
297
  }
286
298
 
287
- if (!resolved) {
288
- switch (key) {
289
- case 'addon':
290
- throw errors.ADDON_NOT_FOUND(`Cannot find addon '${specifier}' imported from '${parentURL.href}'`)
291
- case 'asset':
292
- throw errors.ASSET_NOT_FOUND(`Cannot find asset '${specifier}' imported from '${parentURL.href}'`)
293
- default:
294
- throw errors.MODULE_NOT_FOUND(`Cannot find module '${specifier}' imported from '${parentURL.href}'`)
295
- }
299
+ matchedConditions.pop()
300
+
301
+ if (resolutions === 0) {
302
+ throw errors.ADDON_NOT_FOUND(
303
+ `Cannot find ${condition === 'default' ? 'module' : condition} '${specifier}' imported from '${parentURL.href}'`
304
+ )
296
305
  }
297
306
  }
298
307
 
299
308
  return yielded
300
309
  }
301
310
 
302
- exports.prebuilds = function * (packageURL, artifacts, visited, opts = {}) {
303
- const [prefix = null] = lookupPrebuildsScope(packageURL, opts)
311
+ exports.prebuilds = function* (packageURL, artifacts, visited, opts = {}) {
312
+ const {
313
+ host = null, // Shorthand for single host resolution
314
+ hosts = host !== null ? [host] : [],
315
+ matchedConditions = []
316
+ } = opts
304
317
 
305
- if (prefix === null) return false
318
+ const [prebuildsURL = null] = lookupPrebuildsScope(packageURL, opts)
319
+
320
+ if (prebuildsURL === null) return false
306
321
 
307
322
  let yielded = false
308
323
 
309
- for (const url of yield { prefix }) {
310
- const source = yield { module: url }
324
+ for (const host of hosts) {
325
+ const prefix = new URL(host + '/', prebuildsURL)
311
326
 
312
- if (source !== null) {
313
- addURL(artifacts.addons, url)
327
+ const conditions = host.split('-')
314
328
 
315
- yield { children: exports.module(url, source, artifacts, visited, opts) }
329
+ matchedConditions.push(...conditions)
316
330
 
317
- yielded = true
331
+ for (const url of yield { prefix }) {
332
+ const source = yield { module: url }
333
+
334
+ if (source !== null) {
335
+ addURL(artifacts.addons, url)
336
+
337
+ yield {
338
+ children: exports.module(url, source, artifacts, visited, opts)
339
+ }
340
+
341
+ yielded = true
342
+ }
318
343
  }
344
+
345
+ for (const _ of conditions) matchedConditions.pop()
319
346
  }
320
347
 
321
348
  return yielded
322
349
  }
323
350
 
324
- exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {}) {
325
- const matches = yield * exports.patternMatches(patterns, parentURL, [], opts)
351
+ exports.assets = function* (
352
+ patterns,
353
+ parentURL,
354
+ artifacts,
355
+ visited,
356
+ opts = {}
357
+ ) {
358
+ const matches = yield* exports.patternMatches(patterns, parentURL, [], opts)
326
359
 
327
360
  let yielded = false
328
361
 
@@ -341,8 +374,13 @@ exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {})
341
374
  return yielded
342
375
  }
343
376
 
344
- exports.patternMatches = function * (pattern, parentURL, matches, opts = {}) {
345
- const { conditions = [] } = opts
377
+ exports.patternMatches = function* patternMatches(
378
+ pattern,
379
+ parentURL,
380
+ matches,
381
+ opts = {}
382
+ ) {
383
+ const { conditions = [], matchedConditions = [] } = opts
346
384
 
347
385
  if (typeof pattern === 'string') {
348
386
  let patternNegate = false
@@ -378,24 +416,127 @@ exports.patternMatches = function * (pattern, parentURL, matches, opts = {}) {
378
416
  }
379
417
  } else if (Array.isArray(pattern)) {
380
418
  for (const patternValue of pattern) {
381
- yield * exports.patternMatches(patternValue, parentURL, matches, opts)
419
+ yield* patternMatches(patternValue, parentURL, matches, opts)
382
420
  }
383
421
  } else if (typeof pattern === 'object' && pattern !== null) {
384
- const keys = Object.keys(pattern)
385
-
386
- for (const p of keys) {
387
- if (p === 'default' || conditions.includes(p)) {
388
- const patternValue = pattern[p]
389
-
390
- return yield * exports.patternMatches(patternValue, parentURL, matches, opts)
422
+ let yielded = false
423
+
424
+ for (const [condition, patternValue, subset] of conditionMatches(
425
+ pattern,
426
+ conditions,
427
+ opts
428
+ )) {
429
+ matchedConditions.push(condition)
430
+
431
+ if (
432
+ yield* patternMatches(patternValue, parentURL, matches, {
433
+ ...opts,
434
+ conditions: subset
435
+ })
436
+ ) {
437
+ yielded = true
391
438
  }
439
+
440
+ matchedConditions.pop()
392
441
  }
442
+
443
+ if (yielded) return true
393
444
  }
394
445
 
395
446
  return matches
396
447
  }
397
448
 
398
- function compressImportsMap (imports) {
449
+ function addURL(array, url) {
450
+ let lo = 0
451
+ let hi = array.length - 1
452
+
453
+ while (lo <= hi) {
454
+ const mid = lo + ((hi - lo) >> 1)
455
+ const found = array[mid]
456
+
457
+ if (found.href === url.href) return
458
+
459
+ if (found.href < url.href) {
460
+ lo = mid + 1
461
+ } else {
462
+ hi = mid - 1
463
+ }
464
+ }
465
+
466
+ array.splice(lo, 0, url)
467
+ }
468
+
469
+ function removeURL(array, url) {
470
+ let lo = 0
471
+ let hi = array.length - 1
472
+
473
+ while (lo <= hi) {
474
+ const mid = lo + ((hi - lo) >> 1)
475
+ const found = array[mid]
476
+
477
+ if (found.href === url.href) break
478
+
479
+ if (found.href < url.href) {
480
+ lo = mid + 1
481
+ } else {
482
+ hi = mid - 1
483
+ }
484
+ }
485
+
486
+ if (array[lo].href === url.href) array.splice(lo, 1)
487
+ }
488
+
489
+ function hasResolution(imports, specifier, conditions) {
490
+ if (specifier in imports === false) return false
491
+
492
+ let current = imports[specifier]
493
+
494
+ for (const key of conditions) {
495
+ if (key in current === false || typeof current[key] !== 'object') {
496
+ return false
497
+ }
498
+
499
+ current = current[key]
500
+ }
501
+
502
+ return true
503
+ }
504
+
505
+ function addResolution(imports, specifier, conditions, url) {
506
+ imports[specifier] = imports[specifier] || {}
507
+
508
+ let current = imports[specifier]
509
+
510
+ for (let i = 0, n = conditions.length - 1; i < n; i++) {
511
+ const key = conditions[i]
512
+
513
+ if (key in current === false) {
514
+ current[key] = {}
515
+ } else if (typeof current[key] !== 'object') {
516
+ current[key] = { default: current[key] }
517
+ }
518
+
519
+ current = current[key]
520
+ }
521
+
522
+ const last = conditions[conditions.length - 1]
523
+
524
+ if (last in current) return false
525
+
526
+ current[last] = url.href
527
+
528
+ if ('default' in current) {
529
+ const value = current.default
530
+
531
+ delete current.default
532
+
533
+ current.default = value
534
+ }
535
+
536
+ return true
537
+ }
538
+
539
+ function compressImportsMap(imports) {
399
540
  const entries = []
400
541
 
401
542
  for (const entry of Object.entries(imports)) {
@@ -407,7 +548,7 @@ function compressImportsMap (imports) {
407
548
  return Object.fromEntries(entries)
408
549
  }
409
550
 
410
- function compressImportsMapEntry (resolved) {
551
+ function compressImportsMapEntry(resolved) {
411
552
  if (typeof resolved === 'string') return resolved
412
553
 
413
554
  let entries = []
@@ -421,13 +562,11 @@ function compressImportsMapEntry (resolved) {
421
562
  if (entry[0] === 'default') primary = entry[1]
422
563
  }
423
564
 
424
- entries = entries.filter(([condition, resolved]) => condition === 'default' || resolved !== primary)
565
+ entries = entries.filter(
566
+ ([condition, resolved]) => condition === 'default' || resolved !== primary
567
+ )
425
568
 
426
- if (entries.length === 1) {
427
- const [condition, resolved] = entries[0]
428
-
429
- if (condition === 'default') return resolved
430
- }
569
+ if (entries.length === 1) return entries[0][1]
431
570
 
432
571
  return Object.fromEntries(entries)
433
572
  }
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.5",
3
+ "version": "1.3.0",
4
4
  "description": "Low-level module graph traversal for Bare",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -21,7 +21,10 @@
21
21
  }
22
22
  },
23
23
  "scripts": {
24
- "test": "standard && bare test.js"
24
+ "test": "npm run lint && npm run test:bare && npm run test:node",
25
+ "test:bare": "bare test.js",
26
+ "test:node": "node test.js",
27
+ "lint": "prettier . --check"
25
28
  },
26
29
  "repository": {
27
30
  "type": "git",
@@ -40,6 +43,7 @@
40
43
  },
41
44
  "devDependencies": {
42
45
  "brittle": "^3.2.1",
43
- "standard": "^17.0.0"
46
+ "prettier": "^3.4.2",
47
+ "prettier-config-standard": "^7.0.0"
44
48
  }
45
49
  }