-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
composeTwoImportMaps.js
113 lines (98 loc) · 3.31 KB
/
composeTwoImportMaps.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// https://github.com/systemjs/systemjs/blob/89391f92dfeac33919b0223bbf834a1f4eea5750/src/common.js#L136
import { assertImportMap } from "./internal/assertImportMap.js"
import { resolveUrl } from "./resolveUrl.js"
export const composeTwoImportMaps = (leftImportMap, rightImportMap) => {
assertImportMap(leftImportMap)
assertImportMap(rightImportMap)
const importMap = {}
const leftImports = leftImportMap.imports
const rightImports = rightImportMap.imports
const leftHasImports = Boolean(leftImports)
const rightHasImports = Boolean(rightImports)
if (leftHasImports && rightHasImports) {
importMap.imports = composeTwoMappings(leftImports, rightImports)
} else if (leftHasImports) {
importMap.imports = { ...leftImports }
} else if (rightHasImports) {
importMap.imports = { ...rightImports }
}
const leftScopes = leftImportMap.scopes
const rightScopes = rightImportMap.scopes
const leftHasScopes = Boolean(leftScopes)
const rightHasScopes = Boolean(rightScopes)
if (leftHasScopes && rightHasScopes) {
importMap.scopes = composeTwoScopes(
leftScopes,
rightScopes,
importMap.imports || {},
)
} else if (leftHasScopes) {
importMap.scopes = { ...leftScopes }
} else if (rightHasScopes) {
importMap.scopes = { ...rightScopes }
}
return importMap
}
const composeTwoMappings = (leftMappings, rightMappings) => {
const mappings = {}
Object.keys(leftMappings).forEach((leftSpecifier) => {
if (objectHasKey(rightMappings, leftSpecifier)) {
// will be overidden
return
}
const leftAddress = leftMappings[leftSpecifier]
const rightSpecifier = Object.keys(rightMappings).find((rightSpecifier) => {
return compareAddressAndSpecifier(leftAddress, rightSpecifier)
})
mappings[leftSpecifier] = rightSpecifier
? rightMappings[rightSpecifier]
: leftAddress
})
Object.keys(rightMappings).forEach((rightSpecifier) => {
mappings[rightSpecifier] = rightMappings[rightSpecifier]
})
return mappings
}
const objectHasKey = (object, key) =>
Object.prototype.hasOwnProperty.call(object, key)
const compareAddressAndSpecifier = (address, specifier) => {
const addressUrl = resolveUrl(address, "file:///")
const specifierUrl = resolveUrl(specifier, "file:///")
return addressUrl === specifierUrl
}
const composeTwoScopes = (leftScopes, rightScopes, imports) => {
const scopes = {}
Object.keys(leftScopes).forEach((leftScopeKey) => {
if (objectHasKey(rightScopes, leftScopeKey)) {
// will be merged
scopes[leftScopeKey] = leftScopes[leftScopeKey]
return
}
const topLevelSpecifier = Object.keys(imports).find(
(topLevelSpecifierCandidate) => {
return compareAddressAndSpecifier(
leftScopeKey,
topLevelSpecifierCandidate,
)
},
)
if (topLevelSpecifier) {
scopes[imports[topLevelSpecifier]] = leftScopes[leftScopeKey]
} else {
scopes[leftScopeKey] = leftScopes[leftScopeKey]
}
})
Object.keys(rightScopes).forEach((rightScopeKey) => {
if (objectHasKey(scopes, rightScopeKey)) {
scopes[rightScopeKey] = composeTwoMappings(
scopes[rightScopeKey],
rightScopes[rightScopeKey],
)
} else {
scopes[rightScopeKey] = {
...rightScopes[rightScopeKey],
}
}
})
return scopes
}