1 |
|
2 | import {
|
3 | operatingSystemPathToPathname,
|
4 | pathnameToOperatingSystemPath,
|
5 | } from "@jsenv/operating-system-path"
|
6 | import { generateGroupMap } from "@jsenv/core"
|
7 | import {
|
8 | catchAsyncFunctionCancellation,
|
9 | createProcessInterruptionCancellationToken,
|
10 | } from "@dmail/cancellation"
|
11 | import { jsenvBundlingRelativePathInception } from "./jsenv-bundling-project.js"
|
12 | import { assertFile, assertFolder } from "./filesystem-assertions.js"
|
13 | import { bundleWithoutBalancing } from "./bundle-without-balancing.js"
|
14 | import { bundleWithBalancing } from "./bundle-with-balancing.js"
|
15 | import { bundleBalancer } from "./bundle-balancer.js"
|
16 | import { removeFolder } from "./removeFolder.js"
|
17 | import {
|
18 | DEFAULT_IMPORT_MAP_RELATIVE_PATH,
|
19 | DEFAULT_ENTRY_POINT_MAP,
|
20 | DEFAULT_NATIVE_MODULE_PREDICATE,
|
21 | DEFAULT_BABEL_PLUGIN_MAP,
|
22 | DEFAULT_PLATFORM_SCORE_MAP,
|
23 | } from "./generate-bundle-constant.js"
|
24 |
|
25 | export const generateBundle = ({
|
26 | projectPath,
|
27 | bundleIntoRelativePath,
|
28 | cleanBundleInto = false,
|
29 | cache = false,
|
30 | cacheRelativePath = "/.cache",
|
31 | importDefaultExtension,
|
32 | importMapRelativePath = DEFAULT_IMPORT_MAP_RELATIVE_PATH,
|
33 | importMapForBundle = {},
|
34 | importAbstractMap = {},
|
35 | importFallbackMap = {},
|
36 | nativeModulePredicate = DEFAULT_NATIVE_MODULE_PREDICATE,
|
37 | entryPointMap = DEFAULT_ENTRY_POINT_MAP,
|
38 | babelPluginMap = DEFAULT_BABEL_PLUGIN_MAP,
|
39 | convertMap,
|
40 | logLevel,
|
41 | minify = false,
|
42 | writeOnFileSystem = true,
|
43 | throwUnhandled = true,
|
44 | format,
|
45 | formatOutputOptions = {},
|
46 |
|
47 | compileGroupCount = 1,
|
48 | platformAlwaysInsidePlatformScoreMap,
|
49 | balancerTemplateRelativePath,
|
50 | defaultBalancerTemplateHref,
|
51 | balancerDataAbstractPath,
|
52 | platformScoreMap = DEFAULT_PLATFORM_SCORE_MAP,
|
53 | }) => {
|
54 | const promise = catchAsyncFunctionCancellation(async () => {
|
55 | if (typeof projectPath !== "string")
|
56 | throw new TypeError(`projectPath must be a string, got ${projectPath}`)
|
57 | if (typeof bundleIntoRelativePath !== "string")
|
58 | throw new TypeError(`bundleIntoRelativePath must be a string, got ${bundleIntoRelativePath}`)
|
59 | if (typeof entryPointMap !== "object")
|
60 | throw new TypeError(`entryPointMap must be an object, got ${entryPointMap}`)
|
61 | if (typeof compileGroupCount !== "number")
|
62 | throw new TypeError(`compileGroupCount must be a number, got ${compileGroupCount}`)
|
63 | if (compileGroupCount < 1)
|
64 | throw new Error(`compileGroupCount must be >= 1, got ${compileGroupCount}`)
|
65 |
|
66 | const cancellationToken = createProcessInterruptionCancellationToken()
|
67 | const projectPathname = operatingSystemPathToPathname(projectPath)
|
68 |
|
69 | await assertFolder(projectPath)
|
70 |
|
71 | if (cleanBundleInto) {
|
72 | await removeFolder(
|
73 | pathnameToOperatingSystemPath(`${projectPathname}${bundleIntoRelativePath}`),
|
74 | )
|
75 | }
|
76 |
|
77 | if (compileGroupCount === 1) {
|
78 | return bundleWithoutBalancing({
|
79 | cancellationToken,
|
80 | projectPathname,
|
81 | bundleIntoRelativePath,
|
82 | cache,
|
83 | cacheRelativePath,
|
84 | importDefaultExtension,
|
85 | importMapRelativePath,
|
86 | importMapForBundle,
|
87 | importAbstractMap,
|
88 | importFallbackMap,
|
89 | nativeModulePredicate,
|
90 | entryPointMap,
|
91 | babelPluginMap,
|
92 | convertMap,
|
93 | minify,
|
94 | logLevel,
|
95 | format,
|
96 | formatOutputOptions,
|
97 | writeOnFileSystem,
|
98 | })
|
99 | }
|
100 |
|
101 | if (typeof balancerTemplateRelativePath === "undefined") {
|
102 | if (!defaultBalancerTemplateHref) {
|
103 | throw createFormatIncompatibleWithBalancingError({ format })
|
104 | }
|
105 | balancerTemplateRelativePath = jsenvBundlingRelativePathInception({
|
106 | jsenvBundlingRelativePath: defaultBalancerTemplateHref,
|
107 | projectPathname,
|
108 | })
|
109 | }
|
110 | const balancerTemplatePathname = `${projectPathname}${balancerTemplateRelativePath}`
|
111 | const balancerTemplateHref = `file://${balancerTemplatePathname}`
|
112 |
|
113 | await assertFile(pathnameToOperatingSystemPath(balancerTemplatePathname))
|
114 |
|
115 | const groupMap = generateGroupMap({
|
116 | babelPluginMap,
|
117 | platformScoreMap,
|
118 | groupCount: compileGroupCount,
|
119 | platformAlwaysInsidePlatformScoreMap,
|
120 | })
|
121 |
|
122 | return await Promise.all([
|
123 | generateEntryPointsFolders({
|
124 | cancellationToken,
|
125 | projectPathname,
|
126 | bundleIntoRelativePath,
|
127 | cache,
|
128 | cacheRelativePath,
|
129 | importDefaultExtension,
|
130 | importMapRelativePath,
|
131 | importMapForBundle,
|
132 | importAbstractMap,
|
133 | importFallbackMap,
|
134 | nativeModulePredicate,
|
135 | entryPointMap,
|
136 | babelPluginMap,
|
137 | convertMap,
|
138 | minify,
|
139 | logLevel,
|
140 | writeOnFileSystem,
|
141 | format,
|
142 | formatOutputOptions,
|
143 | groupMap,
|
144 | }),
|
145 | generateEntryPointsBalancerFiles({
|
146 | cancellationToken,
|
147 | projectPathname,
|
148 | bundleIntoRelativePath,
|
149 | cache,
|
150 | cacheRelativePath,
|
151 | importDefaultExtension,
|
152 | importMapRelativePath,
|
153 | importMapForBundle,
|
154 | importAbstractMap,
|
155 | importFallbackMap,
|
156 | nativeModulePredicate,
|
157 | entryPointMap,
|
158 | babelPluginMap,
|
159 | convertMap,
|
160 | minify,
|
161 | logLevel,
|
162 | writeOnFileSystem,
|
163 | format,
|
164 | balancerTemplateHref,
|
165 | balancerDataAbstractPath,
|
166 | groupMap,
|
167 | }),
|
168 | ])
|
169 | })
|
170 |
|
171 | if (!throwUnhandled) return promise
|
172 | return promise.catch((e) => {
|
173 | setTimeout(() => {
|
174 | throw e
|
175 | })
|
176 | })
|
177 | }
|
178 |
|
179 | const generateEntryPointsFolders = async ({
|
180 | cancellationToken,
|
181 | projectPathname,
|
182 | bundleIntoRelativePath,
|
183 | cache,
|
184 | cacheRelativePath,
|
185 | importDefaultExtension,
|
186 | importMapRelativePath,
|
187 | importMapForBundle,
|
188 | importAbstractMap,
|
189 | importFallbackMap,
|
190 | nativeModulePredicate,
|
191 | entryPointMap,
|
192 | babelPluginMap,
|
193 | convertMap,
|
194 | minify,
|
195 | logLevel,
|
196 | writeOnFileSystem,
|
197 | format,
|
198 | formatOutputOptions,
|
199 | groupMap,
|
200 | }) =>
|
201 | Promise.all(
|
202 | Object.keys(groupMap).map(async (compileId) =>
|
203 | bundleWithBalancing({
|
204 | cancellationToken,
|
205 | projectPathname,
|
206 | bundleIntoRelativePath,
|
207 | cache,
|
208 | cacheRelativePath,
|
209 | importDefaultExtension,
|
210 | importMapRelativePath,
|
211 | importMapForBundle,
|
212 | importAbstractMap,
|
213 | importFallbackMap,
|
214 | nativeModulePredicate,
|
215 | entryPointMap,
|
216 | babelPluginMap,
|
217 | convertMap,
|
218 | minify,
|
219 | logLevel,
|
220 | format,
|
221 | formatOutputOptions,
|
222 | groupMap,
|
223 | compileId,
|
224 | writeOnFileSystem,
|
225 | }),
|
226 | ),
|
227 | )
|
228 |
|
229 | const generateEntryPointsBalancerFiles = ({
|
230 | cancellationToken,
|
231 | projectPathname,
|
232 | bundleIntoRelativePath,
|
233 | cache,
|
234 | cacheRelativePath,
|
235 | importDefaultExtension,
|
236 | importMapRelativePath,
|
237 | importMapForBundle,
|
238 | importAbstractMap,
|
239 | importFallbackMap,
|
240 | nativeModulePredicate,
|
241 | entryPointMap,
|
242 | babelPluginMap,
|
243 | convertMap,
|
244 | minify,
|
245 | logLevel,
|
246 | writeOnFileSystem,
|
247 | format,
|
248 | balancerTemplateHref,
|
249 | balancerDataAbstractPath,
|
250 | groupMap,
|
251 | }) =>
|
252 | Promise.all(
|
253 | Object.keys(entryPointMap).map(async (entryPointName) =>
|
254 | bundleBalancer({
|
255 | cancellationToken,
|
256 | projectPathname,
|
257 | bundleIntoRelativePath,
|
258 | cache,
|
259 | cacheRelativePath,
|
260 | importDefaultExtension,
|
261 | importMapRelativePath,
|
262 | importMapForBundle,
|
263 | importAbstractMap,
|
264 | importFallbackMap,
|
265 | nativeModulePredicate,
|
266 | entryPointMap: {
|
267 | [entryPointName]: balancerTemplateHref,
|
268 | },
|
269 | babelPluginMap,
|
270 | convertMap,
|
271 | minify,
|
272 | logLevel,
|
273 | format,
|
274 | balancerDataAbstractPath,
|
275 | groupMap,
|
276 | writeOnFileSystem,
|
277 | }),
|
278 | ),
|
279 | )
|
280 |
|
281 | const createFormatIncompatibleWithBalancingError = ({ format }) =>
|
282 | new Error(`format not compatible with balancing.
|
283 | format: ${format}`)
|