UNPKG

7.74 kBJavaScriptView Raw
1/* eslint-disable import/max-dependencies */
2import {
3 operatingSystemPathToPathname,
4 pathnameToOperatingSystemPath,
5} from "@jsenv/operating-system-path"
6import { generateGroupMap } from "@jsenv/core"
7import {
8 catchAsyncFunctionCancellation,
9 createProcessInterruptionCancellationToken,
10} from "@dmail/cancellation"
11import { jsenvBundlingRelativePathInception } from "./jsenv-bundling-project.js"
12import { assertFile, assertFolder } from "./filesystem-assertions.js"
13import { bundleWithoutBalancing } from "./bundle-without-balancing.js"
14import { bundleWithBalancing } from "./bundle-with-balancing.js"
15import { bundleBalancer } from "./bundle-balancer.js"
16import { removeFolder } from "./removeFolder.js"
17import {
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
25export 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 // balancing
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
179const 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
229const 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
281const createFormatIncompatibleWithBalancingError = ({ format }) =>
282 new Error(`format not compatible with balancing.
283format: ${format}`)