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