balm-core 5.2.0 → 6.0.0-alpha.1

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.
Files changed (301) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.cjs +2625 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +569 -0
  5. package/dist/index.d.ts +569 -0
  6. package/dist/index.js +2527 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +49 -123
  9. package/src/balm.ts +108 -0
  10. package/src/bundler/esbuild.ts +47 -0
  11. package/src/bundler/index.ts +3 -0
  12. package/src/bundler/rollup.ts +45 -0
  13. package/src/bundler/webpack.ts +124 -0
  14. package/src/config/constants.ts +12 -0
  15. package/src/config/defaults.ts +209 -0
  16. package/src/config/index.ts +112 -0
  17. package/src/hooks/index.ts +224 -0
  18. package/src/index.ts +16 -0
  19. package/src/pipeline/file.ts +69 -0
  20. package/src/pipeline/index.ts +10 -0
  21. package/src/pipeline/pipeline.ts +135 -0
  22. package/src/pipeline/transforms/cache.ts +146 -0
  23. package/src/pipeline/transforms/htmlmin.ts +18 -0
  24. package/src/pipeline/transforms/less.ts +75 -0
  25. package/src/pipeline/transforms/postcss.ts +43 -0
  26. package/src/pipeline/transforms/rename.ts +37 -0
  27. package/src/pipeline/transforms/replace.ts +30 -0
  28. package/src/pipeline/transforms/sass.ts +106 -0
  29. package/src/pipeline/transforms/terser.ts +20 -0
  30. package/src/runner/dag.ts +77 -0
  31. package/src/runner/task.ts +38 -0
  32. package/src/shims.d.ts +5 -0
  33. package/src/tasks/cache.ts +72 -0
  34. package/src/tasks/clean.ts +21 -0
  35. package/src/tasks/copy.ts +36 -0
  36. package/src/tasks/ftp.ts +90 -0
  37. package/src/tasks/html.ts +232 -0
  38. package/src/tasks/index.ts +14 -0
  39. package/src/tasks/publish.ts +71 -0
  40. package/src/tasks/pwa.ts +99 -0
  41. package/src/tasks/remove.ts +24 -0
  42. package/src/tasks/replace.ts +34 -0
  43. package/src/tasks/script.ts +28 -0
  44. package/src/tasks/server.ts +183 -0
  45. package/src/tasks/static.ts +104 -0
  46. package/src/tasks/style.ts +57 -0
  47. package/src/tasks/zip.ts +65 -0
  48. package/src/types/index.ts +202 -0
  49. package/src/utilities/file.ts +120 -0
  50. package/src/utilities/logger.ts +63 -0
  51. package/src/utilities/utils.ts +46 -0
  52. package/src/utilities/workspace.ts +38 -0
  53. package/src/watcher/index.ts +100 -0
  54. package/tsconfig.json +8 -0
  55. package/tsup.config.ts +12 -0
  56. package/README.md +0 -196
  57. package/index.d.ts +0 -360
  58. package/lib/balm.js +0 -49
  59. package/lib/bootstrap/check_config.js +0 -43
  60. package/lib/bootstrap/index.js +0 -87
  61. package/lib/bundler/esbuild/build.js +0 -26
  62. package/lib/bundler/esbuild/index.js +0 -7
  63. package/lib/bundler/esbuild/options.js +0 -7
  64. package/lib/bundler/esbuild/transform.js +0 -36
  65. package/lib/bundler/rollup/build.js +0 -52
  66. package/lib/bundler/rollup/entry.js +0 -28
  67. package/lib/bundler/rollup/index.js +0 -20
  68. package/lib/bundler/rollup/output.js +0 -20
  69. package/lib/bundler/rollup/plugins.js +0 -31
  70. package/lib/bundler/webpack/config/common.js +0 -135
  71. package/lib/bundler/webpack/config/dev.js +0 -12
  72. package/lib/bundler/webpack/config/env.js +0 -67
  73. package/lib/bundler/webpack/config/index.js +0 -6
  74. package/lib/bundler/webpack/config/prod.js +0 -39
  75. package/lib/bundler/webpack/config/regex.js +0 -10
  76. package/lib/bundler/webpack/entry.js +0 -65
  77. package/lib/bundler/webpack/index.js +0 -32
  78. package/lib/bundler/webpack/loaders.js +0 -50
  79. package/lib/bundler/webpack/output.js +0 -41
  80. package/lib/bundler/webpack/rules/asset.js +0 -33
  81. package/lib/bundler/webpack/rules/babel.js +0 -19
  82. package/lib/bundler/webpack/rules/css.js +0 -109
  83. package/lib/bundler/webpack/rules/html.js +0 -15
  84. package/lib/bundler/webpack/rules/index.js +0 -10
  85. package/lib/config/assets.js +0 -30
  86. package/lib/config/constants.js +0 -14
  87. package/lib/config/env.js +0 -35
  88. package/lib/config/extras.js +0 -6
  89. package/lib/config/ftp.js +0 -6
  90. package/lib/config/globals.js +0 -43
  91. package/lib/config/html.js +0 -22
  92. package/lib/config/images.js +0 -4
  93. package/lib/config/index.js +0 -63
  94. package/lib/config/logs.js +0 -11
  95. package/lib/config/paths.js +0 -46
  96. package/lib/config/pwa.js +0 -24
  97. package/lib/config/roots.js +0 -9
  98. package/lib/config/scripts.js +0 -162
  99. package/lib/config/server.js +0 -84
  100. package/lib/config/spinner.js +0 -9
  101. package/lib/config/styles.js +0 -67
  102. package/lib/hello.js +0 -19
  103. package/lib/hooks/index.js +0 -94
  104. package/lib/hooks/maker.js +0 -59
  105. package/lib/index.js +0 -5
  106. package/lib/middlewares/history.js +0 -6
  107. package/lib/middlewares/index.js +0 -11
  108. package/lib/middlewares/proxy.js +0 -28
  109. package/lib/middlewares/webpack.js +0 -26
  110. package/lib/plugins/htmlmin.js +0 -39
  111. package/lib/plugins/imagemin.js +0 -95
  112. package/lib/plugins/index.js +0 -27
  113. package/lib/plugins/jsmin.js +0 -37
  114. package/lib/plugins/less.js +0 -97
  115. package/lib/plugins/plumber.js +0 -87
  116. package/lib/plugins/postcss-plugins.js +0 -13
  117. package/lib/plugins/postcss.js +0 -117
  118. package/lib/plugins/rename.js +0 -51
  119. package/lib/plugins/replace.js +0 -91
  120. package/lib/plugins/sass-legacy.js +0 -131
  121. package/lib/plugins/sass.js +0 -134
  122. package/lib/plugins/sftp.js +0 -288
  123. package/lib/tasks/default.js +0 -46
  124. package/lib/tasks/foundation/balm.js +0 -72
  125. package/lib/tasks/foundation/balm_style.js +0 -65
  126. package/lib/tasks/foundation/index.js +0 -10
  127. package/lib/tasks/index.js +0 -48
  128. package/lib/tasks/private/build.js +0 -18
  129. package/lib/tasks/private/cache.js +0 -31
  130. package/lib/tasks/private/clean.js +0 -69
  131. package/lib/tasks/private/end.js +0 -24
  132. package/lib/tasks/private/extra.js +0 -35
  133. package/lib/tasks/private/font.js +0 -15
  134. package/lib/tasks/private/image.js +0 -37
  135. package/lib/tasks/private/index.js +0 -34
  136. package/lib/tasks/private/lint.js +0 -20
  137. package/lib/tasks/private/media.js +0 -15
  138. package/lib/tasks/private/modernizr.js +0 -59
  139. package/lib/tasks/private/pwa-cache.js +0 -32
  140. package/lib/tasks/private/script.js +0 -9
  141. package/lib/tasks/private/sprite.js +0 -105
  142. package/lib/tasks/private/start.js +0 -16
  143. package/lib/tasks/private/style.js +0 -9
  144. package/lib/tasks/private/workbox-sw.js +0 -15
  145. package/lib/tasks/public/copy.js +0 -16
  146. package/lib/tasks/public/esbuild.js +0 -18
  147. package/lib/tasks/public/ftp.js +0 -39
  148. package/lib/tasks/public/html.js +0 -65
  149. package/lib/tasks/public/index.js +0 -38
  150. package/lib/tasks/public/jsmin.js +0 -23
  151. package/lib/tasks/public/less.js +0 -21
  152. package/lib/tasks/public/postcss.js +0 -16
  153. package/lib/tasks/public/publish.js +0 -51
  154. package/lib/tasks/public/pwa.js +0 -84
  155. package/lib/tasks/public/remove.js +0 -46
  156. package/lib/tasks/public/replace.js +0 -26
  157. package/lib/tasks/public/rollup.js +0 -17
  158. package/lib/tasks/public/sass.js +0 -27
  159. package/lib/tasks/public/server.js +0 -130
  160. package/lib/tasks/public/url.js +0 -35
  161. package/lib/tasks/public/version.js +0 -23
  162. package/lib/tasks/public/webpack.js +0 -39
  163. package/lib/tasks/public/zip.js +0 -19
  164. package/lib/utilities/address.js +0 -55
  165. package/lib/utilities/cache-core.js +0 -66
  166. package/lib/utilities/color.js +0 -27
  167. package/lib/utilities/compiling.js +0 -24
  168. package/lib/utilities/detect-port.js +0 -100
  169. package/lib/utilities/escape-string-regexp.js +0 -10
  170. package/lib/utilities/file.js +0 -70
  171. package/lib/utilities/index.js +0 -8
  172. package/lib/utilities/loading.js +0 -37
  173. package/lib/utilities/logger.js +0 -99
  174. package/lib/utilities/merge-stream.js +0 -38
  175. package/lib/utilities/namespace.js +0 -11
  176. package/lib/utilities/public-url.js +0 -37
  177. package/lib/utilities/replacestream.js +0 -106
  178. package/lib/utilities/typeof.js +0 -5
  179. package/lib/utilities/utils.js +0 -43
  180. package/tslib/balm.js +0 -44
  181. package/tslib/bootstrap/check_config.js +0 -36
  182. package/tslib/bootstrap/index.js +0 -82
  183. package/tslib/bundler/esbuild/build.js +0 -30
  184. package/tslib/bundler/esbuild/index.js +0 -11
  185. package/tslib/bundler/esbuild/options.js +0 -7
  186. package/tslib/bundler/esbuild/transform.js +0 -38
  187. package/tslib/bundler/rollup/build.js +0 -17
  188. package/tslib/bundler/rollup/entry.js +0 -24
  189. package/tslib/bundler/rollup/index.js +0 -21
  190. package/tslib/bundler/rollup/output.js +0 -23
  191. package/tslib/bundler/rollup/plugins.js +0 -27
  192. package/tslib/bundler/webpack/config/common.js +0 -130
  193. package/tslib/bundler/webpack/config/dev.js +0 -14
  194. package/tslib/bundler/webpack/config/env.js +0 -44
  195. package/tslib/bundler/webpack/config/index.js +0 -8
  196. package/tslib/bundler/webpack/config/prod.js +0 -43
  197. package/tslib/bundler/webpack/config/regex.js +0 -10
  198. package/tslib/bundler/webpack/entry.js +0 -68
  199. package/tslib/bundler/webpack/index.js +0 -30
  200. package/tslib/bundler/webpack/loaders.js +0 -51
  201. package/tslib/bundler/webpack/output.js +0 -41
  202. package/tslib/bundler/webpack/rules/asset.js +0 -33
  203. package/tslib/bundler/webpack/rules/babel.js +0 -16
  204. package/tslib/bundler/webpack/rules/css.js +0 -95
  205. package/tslib/bundler/webpack/rules/html.js +0 -15
  206. package/tslib/bundler/webpack/rules/index.js +0 -10
  207. package/tslib/config/assets.js +0 -24
  208. package/tslib/config/constants.js +0 -14
  209. package/tslib/config/env.js +0 -43
  210. package/tslib/config/extras.js +0 -6
  211. package/tslib/config/ftp.js +0 -6
  212. package/tslib/config/globals.js +0 -47
  213. package/tslib/config/html.js +0 -17
  214. package/tslib/config/images.js +0 -4
  215. package/tslib/config/index.js +0 -56
  216. package/tslib/config/logs.js +0 -6
  217. package/tslib/config/paths.js +0 -30
  218. package/tslib/config/pwa.js +0 -18
  219. package/tslib/config/roots.js +0 -8
  220. package/tslib/config/scripts.js +0 -93
  221. package/tslib/config/server.js +0 -33
  222. package/tslib/config/spinner.js +0 -10
  223. package/tslib/config/styles.js +0 -37
  224. package/tslib/hello.js +0 -19
  225. package/tslib/hooks/index.js +0 -75
  226. package/tslib/hooks/maker.js +0 -66
  227. package/tslib/index.js +0 -5
  228. package/tslib/middlewares/history.js +0 -12
  229. package/tslib/middlewares/index.js +0 -18
  230. package/tslib/middlewares/proxy.js +0 -27
  231. package/tslib/middlewares/webpack.js +0 -29
  232. package/tslib/plugins/htmlmin.js +0 -38
  233. package/tslib/plugins/imagemin.js +0 -97
  234. package/tslib/plugins/index.js +0 -27
  235. package/tslib/plugins/jsmin.js +0 -39
  236. package/tslib/plugins/less.js +0 -90
  237. package/tslib/plugins/plumber.js +0 -81
  238. package/tslib/plugins/postcss-plugins.js +0 -24
  239. package/tslib/plugins/postcss.js +0 -111
  240. package/tslib/plugins/rename.js +0 -51
  241. package/tslib/plugins/replace.js +0 -72
  242. package/tslib/plugins/sass-legacy.js +0 -95
  243. package/tslib/plugins/sass.js +0 -109
  244. package/tslib/plugins/sftp.js +0 -258
  245. package/tslib/tasks/default.js +0 -59
  246. package/tslib/tasks/foundation/balm.js +0 -75
  247. package/tslib/tasks/foundation/balm_style.js +0 -68
  248. package/tslib/tasks/foundation/index.js +0 -10
  249. package/tslib/tasks/index.js +0 -43
  250. package/tslib/tasks/private/build.js +0 -15
  251. package/tslib/tasks/private/cache.js +0 -48
  252. package/tslib/tasks/private/clean.js +0 -82
  253. package/tslib/tasks/private/end.js +0 -21
  254. package/tslib/tasks/private/extra.js +0 -34
  255. package/tslib/tasks/private/font.js +0 -12
  256. package/tslib/tasks/private/image.js +0 -42
  257. package/tslib/tasks/private/index.js +0 -34
  258. package/tslib/tasks/private/lint.js +0 -17
  259. package/tslib/tasks/private/media.js +0 -12
  260. package/tslib/tasks/private/modernizr.js +0 -54
  261. package/tslib/tasks/private/pwa-cache.js +0 -32
  262. package/tslib/tasks/private/script.js +0 -9
  263. package/tslib/tasks/private/sprite.js +0 -93
  264. package/tslib/tasks/private/start.js +0 -13
  265. package/tslib/tasks/private/style.js +0 -12
  266. package/tslib/tasks/private/workbox-sw.js +0 -15
  267. package/tslib/tasks/public/copy.js +0 -18
  268. package/tslib/tasks/public/esbuild.js +0 -18
  269. package/tslib/tasks/public/ftp.js +0 -39
  270. package/tslib/tasks/public/html.js +0 -75
  271. package/tslib/tasks/public/index.js +0 -38
  272. package/tslib/tasks/public/jsmin.js +0 -24
  273. package/tslib/tasks/public/less.js +0 -21
  274. package/tslib/tasks/public/postcss.js +0 -16
  275. package/tslib/tasks/public/publish.js +0 -50
  276. package/tslib/tasks/public/pwa.js +0 -87
  277. package/tslib/tasks/public/remove.js +0 -44
  278. package/tslib/tasks/public/replace.js +0 -27
  279. package/tslib/tasks/public/rollup.js +0 -17
  280. package/tslib/tasks/public/sass.js +0 -27
  281. package/tslib/tasks/public/server.js +0 -129
  282. package/tslib/tasks/public/url.js +0 -35
  283. package/tslib/tasks/public/version.js +0 -27
  284. package/tslib/tasks/public/webpack.js +0 -41
  285. package/tslib/tasks/public/zip.js +0 -19
  286. package/tslib/utilities/address.js +0 -48
  287. package/tslib/utilities/cache-core.js +0 -57
  288. package/tslib/utilities/color.js +0 -33
  289. package/tslib/utilities/compiling.js +0 -16
  290. package/tslib/utilities/detect-port.js +0 -91
  291. package/tslib/utilities/escape-string-regexp.js +0 -7
  292. package/tslib/utilities/file.js +0 -78
  293. package/tslib/utilities/index.js +0 -8
  294. package/tslib/utilities/loading.js +0 -25
  295. package/tslib/utilities/logger.js +0 -92
  296. package/tslib/utilities/merge-stream.js +0 -34
  297. package/tslib/utilities/namespace.js +0 -12
  298. package/tslib/utilities/public-url.js +0 -31
  299. package/tslib/utilities/replacestream.js +0 -112
  300. package/tslib/utilities/typeof.js +0 -8
  301. package/tslib/utilities/utils.js +0 -38
package/src/balm.ts ADDED
@@ -0,0 +1,108 @@
1
+ import { BalmConfig, BalmCustomConfig, BundlerType } from './types/index.js';
2
+ import { resolveConfig } from './config/index.js';
3
+ import { TaskDAG } from './runner/dag.js';
4
+ import { BalmHooks } from './hooks/index.js';
5
+ import { CleanTask } from './tasks/clean.js';
6
+ import { StyleTask } from './tasks/style.js';
7
+ import { ScriptTask } from './tasks/script.js';
8
+ import { HtmlTask } from './tasks/html.js';
9
+ import { CacheTask } from './tasks/cache.js';
10
+ import { PwaTask } from './tasks/pwa.js';
11
+ import { ServerTask } from './tasks/server.js';
12
+ import { StaticTask } from './tasks/static.js';
13
+ import { logger } from './utilities/logger.js';
14
+
15
+ export class Balm {
16
+ private _config: BalmConfig;
17
+ private dag = new TaskDAG();
18
+ beforeTask?: () => Promise<void> | void;
19
+ afterTask?: () => Promise<void> | void;
20
+ readonly Bundler = BundlerType;
21
+
22
+ constructor() {
23
+ this._config = resolveConfig();
24
+ }
25
+
26
+ get config(): BalmConfig {
27
+ return this._config;
28
+ }
29
+ set config(customConfig: BalmCustomConfig) {
30
+ this._config = resolveConfig(customConfig);
31
+ if (this._config.logs?.level !== undefined) {
32
+ logger.level = this._config.logs.level;
33
+ }
34
+ }
35
+
36
+ async go(recipe?: (mix: BalmHooks) => void): Promise<void> {
37
+ const endTimer = logger.time('Build');
38
+ const taskSequence: string[] = [];
39
+
40
+ // Register built-in tasks
41
+ this.dag.registerTask(new CleanTask());
42
+ this.dag.registerTask(new StyleTask());
43
+ this.dag.registerTask(new ScriptTask());
44
+ this.dag.registerTask(new StaticTask());
45
+ this.dag.registerTask(new HtmlTask());
46
+ this.dag.registerTask(new CacheTask());
47
+ this.dag.registerTask(new PwaTask());
48
+ this.dag.registerTask(new ServerTask());
49
+
50
+ // Run recipe hooks
51
+ if (typeof recipe === 'function') {
52
+ const hooks = new BalmHooks(this.dag, this._config);
53
+ recipe(hooks);
54
+ }
55
+
56
+ try {
57
+ if (this.beforeTask) {
58
+ await this.beforeTask();
59
+ }
60
+
61
+ if (this._config.useDefaults) {
62
+ await this.dag.runSeries(
63
+ ['clean', 'style', 'script', 'static', 'html'],
64
+ this._config
65
+ );
66
+ }
67
+
68
+ // Execute recipe tasks
69
+ for (let i = 1; ; i++) {
70
+ const recipeName = `recipe:${i}`;
71
+ if (!this.dag.hasTask(recipeName)) break;
72
+ await this.dag.executeTask(recipeName, this._config);
73
+ }
74
+
75
+ // Post-recipe tasks: cache, pwa, serve
76
+ if (this._config.useDefaults) {
77
+ if (this._config.env.isProd) {
78
+ if (this._config.assets.cache) {
79
+ await this.dag.executeTask('cache', this._config);
80
+ }
81
+ if (this._config.pwa.enabled) {
82
+ await this.dag.executeTask('pwa', this._config);
83
+ }
84
+ } else {
85
+ await this.dag.executeTask('serve', this._config);
86
+ }
87
+ }
88
+
89
+ if (this.afterTask) {
90
+ await this.afterTask();
91
+ }
92
+
93
+ endTimer();
94
+ } catch (err: any) {
95
+ logger.error('build', `Build failed: ${err?.message || err}`);
96
+ throw err;
97
+ }
98
+ }
99
+
100
+ reset(): void {
101
+ this.dag.clear();
102
+ this.beforeTask = undefined;
103
+ this.afterTask = undefined;
104
+ this._config = resolveConfig();
105
+ }
106
+ }
107
+
108
+ export const balm = new Balm();
@@ -0,0 +1,47 @@
1
+ import * as esbuild from 'esbuild';
2
+ import path from 'node:path';
3
+ import { BalmConfig } from '../types/index.js';
4
+ import { logger } from '../utilities/logger.js';
5
+
6
+ export async function runEsbuild(
7
+ config: BalmConfig,
8
+ customOptions: esbuild.BuildOptions = {}
9
+ ): Promise<esbuild.BuildResult> {
10
+ const isProd = config.env.isProd;
11
+
12
+ let entryPoints = customOptions.entryPoints || config.scripts.entry;
13
+ if (!entryPoints) {
14
+ entryPoints = [path.join(config.src.js, 'main.js')];
15
+ }
16
+
17
+ const defaultOptions: esbuild.BuildOptions = {
18
+ entryPoints: (Array.isArray(entryPoints)
19
+ ? entryPoints
20
+ : typeof entryPoints === 'string'
21
+ ? [entryPoints]
22
+ : entryPoints) as any,
23
+ absWorkingDir: config.workspace,
24
+ bundle: true,
25
+ outdir: config.dest.js,
26
+ alias: {
27
+ ...config.alias,
28
+ ...config.scripts.alias
29
+ },
30
+ minify: isProd || config.scripts.minify,
31
+ sourcemap: !isProd,
32
+ target:
33
+ config.scripts.target && config.scripts.target !== 'web'
34
+ ? (config.scripts.target as string)
35
+ : 'es2020',
36
+ format: 'esm',
37
+ ...config.scripts.esbuildOptions,
38
+ ...customOptions
39
+ };
40
+
41
+ try {
42
+ return await esbuild.build(defaultOptions);
43
+ } catch (err: any) {
44
+ logger.error('esbuild', err.message || err);
45
+ throw err;
46
+ }
47
+ }
@@ -0,0 +1,3 @@
1
+ export * from './webpack.js';
2
+ export * from './rollup.js';
3
+ export * from './esbuild.js';
@@ -0,0 +1,45 @@
1
+ import { rollup, RollupOptions, OutputOptions } from 'rollup';
2
+ import path from 'node:path';
3
+ import { BalmConfig } from '../types/index.js';
4
+ import { logger } from '../utilities/logger.js';
5
+
6
+ export async function runRollup(
7
+ config: BalmConfig,
8
+ customInputOptions: RollupOptions = {},
9
+ customOutputOptions: OutputOptions = {}
10
+ ): Promise<void> {
11
+ const isProd = config.env.isProd;
12
+
13
+ let input = customInputOptions.input || config.scripts.entry;
14
+ if (!input) {
15
+ input = path.join(config.src.js, 'main.js');
16
+ }
17
+
18
+ const inputOptions: RollupOptions = {
19
+ ...config.scripts.rollupOptions,
20
+ ...customInputOptions,
21
+ input: (customInputOptions.input || input) as any
22
+ };
23
+
24
+ const outputOptions: OutputOptions = customOutputOptions.file
25
+ ? {
26
+ format: 'es',
27
+ sourcemap: !isProd,
28
+ ...customOutputOptions
29
+ }
30
+ : {
31
+ dir: config.dest.js,
32
+ format: 'es',
33
+ sourcemap: !isProd,
34
+ ...customOutputOptions
35
+ };
36
+
37
+ try {
38
+ const bundle = await rollup(inputOptions);
39
+ await bundle.write(outputOptions);
40
+ await bundle.close();
41
+ } catch (err: any) {
42
+ logger.error('rollup', err.message || err);
43
+ throw err;
44
+ }
45
+ }
@@ -0,0 +1,124 @@
1
+ import webpack, { Configuration } from 'webpack';
2
+ import path from 'node:path';
3
+ import { BalmConfig } from '../types/index.js';
4
+ import { logger } from '../utilities/logger.js';
5
+
6
+ export async function runWebpack(
7
+ config: BalmConfig,
8
+ customOptions: Configuration = {}
9
+ ): Promise<webpack.Stats | undefined> {
10
+ const isProd = config.env.isProd;
11
+
12
+ let entry = customOptions.entry || config.scripts.entry;
13
+ if (!entry) {
14
+ entry = path.join(config.src.js, 'main.js');
15
+ }
16
+
17
+ const rawOutputPath = customOptions.output?.path;
18
+ const isCustomOutput = Boolean(rawOutputPath);
19
+ const outputPath = isCustomOutput
20
+ ? path.isAbsolute(rawOutputPath as string)
21
+ ? (rawOutputPath as string)
22
+ : path.resolve(config.workspace, rawOutputPath as string)
23
+ : config.dest.base;
24
+
25
+ const jsDir = isCustomOutput ? '' : isProd ? config.paths.target.js : config.paths.tmp.js;
26
+ const imgDir = isProd ? config.paths.target.img : config.paths.tmp.img;
27
+ const fontDir = isProd ? config.paths.target.font : config.paths.tmp.font;
28
+
29
+ const defaultWebpackConfig: Configuration = {
30
+ mode: isProd ? 'production' : 'development',
31
+ context: config.workspace,
32
+ entry,
33
+ output: {
34
+ path: outputPath,
35
+ filename: isCustomOutput
36
+ ? '[name].js'
37
+ : isProd && config.assets.cache
38
+ ? `${jsDir}/[name].[contenthash:8].js`
39
+ : `${jsDir}/[name].js`,
40
+ chunkFilename: isCustomOutput
41
+ ? 'chunk/[name].js'
42
+ : isProd && config.assets.cache
43
+ ? `${jsDir}/chunk/[name].[chunkhash:8].js`
44
+ : `${jsDir}/chunk/[name].js`,
45
+ publicPath: config.assets.virtualDir ? `/${config.assets.virtualDir}/` : '/',
46
+ ...(config.scripts.library ? { library: config.scripts.library as any } : {})
47
+ },
48
+ target: config.scripts.target || 'web',
49
+ externals: config.scripts.externals as any,
50
+ plugins: [
51
+ ...(config.scripts.plugins || [])
52
+ ],
53
+ resolve: {
54
+ extensions: [
55
+ '.wasm',
56
+ '.mjs',
57
+ '.js',
58
+ '.jsx',
59
+ '.ts',
60
+ '.tsx',
61
+ '.vue',
62
+ '.json',
63
+ ...(config.scripts.extensions || [])
64
+ ],
65
+ alias: {
66
+ ...config.alias,
67
+ ...config.scripts.alias
68
+ }
69
+ },
70
+ module: {
71
+ rules: [
72
+ ...(config.scripts.loaders || []),
73
+ {
74
+ test: /\.(png|jpe?g|gif|svg|webp)$/i,
75
+ type: 'asset/resource',
76
+ generator: {
77
+ filename: `${imgDir}/[name].[hash:8][ext]`
78
+ }
79
+ },
80
+ {
81
+ test: /\.(woff2?|eot|ttf|otf)$/i,
82
+ type: 'asset/resource',
83
+ generator: {
84
+ filename: `${fontDir}/[name].[hash:8][ext]`
85
+ }
86
+ }
87
+ ]
88
+ },
89
+ optimization: {
90
+ minimize: isProd || config.scripts.minify
91
+ },
92
+ devtool: isProd ? false : 'eval-cheap-module-source-map'
93
+ };
94
+
95
+ const webpackConfig: Configuration = {
96
+ ...defaultWebpackConfig,
97
+ ...config.scripts.webpackOptions,
98
+ ...customOptions,
99
+ output: {
100
+ ...defaultWebpackConfig.output,
101
+ ...config.scripts.webpackOptions?.output,
102
+ ...customOptions?.output,
103
+ path: outputPath
104
+ }
105
+ };
106
+
107
+ return new Promise((resolve, reject) => {
108
+ const compiler = webpack(webpackConfig);
109
+ compiler.run((err, stats) => {
110
+ if (err) {
111
+ logger.error('webpack', err.stack || err);
112
+ return reject(err);
113
+ }
114
+
115
+ if (stats?.hasErrors()) {
116
+ const info = stats.toJson();
117
+ logger.error('webpack', info.errors?.map((e) => e.message).join('\n'));
118
+ return reject(new Error('Webpack compilation errors'));
119
+ }
120
+
121
+ resolve(stats);
122
+ });
123
+ });
124
+ }
@@ -0,0 +1,12 @@
1
+ export const ASSETS_TYPES = ['css', 'js', 'img', 'font', 'media'];
2
+ export const PUBLIC_URL = '%PUBLIC_URL%';
3
+ export const CHUNK = { dir: 'chunk' };
4
+ export const ASSET = { dir: 'asset' };
5
+
6
+ export const ASSET_EXT = {
7
+ styles: ['css', 'scss', 'sass', 'less'],
8
+ scripts: ['js', 'mjs', 'cjs', 'ts', 'mts', 'cts', 'jsx', 'tsx'],
9
+ images: ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'ico'],
10
+ fonts: ['woff', 'woff2', 'ttf', 'eot', 'otf'],
11
+ media: ['mp4', 'webm', 'ogg', 'mp3', 'wav', 'flac', 'aac']
12
+ };
@@ -0,0 +1,209 @@
1
+ import path from 'node:path';
2
+ import { BalmConfig, BundlerType } from '../types/index.js';
3
+
4
+ export function createDefaultConfig(workspace = process.cwd()): BalmConfig {
5
+ const isProd = process.env.NODE_ENV === 'production';
6
+ const isDev = !isProd;
7
+ const isTest = process.env.NODE_ENV === 'test';
8
+
9
+ const roots = {
10
+ source: 'src',
11
+ tmp: '.tmp',
12
+ target: 'dist'
13
+ };
14
+
15
+ const paths = {
16
+ source: {
17
+ base: '',
18
+ html: '',
19
+ css: 'styles',
20
+ js: 'scripts',
21
+ img: 'images',
22
+ font: 'fonts',
23
+ media: 'media'
24
+ },
25
+ tmp: {
26
+ base: '',
27
+ css: 'css',
28
+ js: 'js',
29
+ img: 'img',
30
+ font: 'fonts',
31
+ media: 'media'
32
+ },
33
+ target: {
34
+ base: '',
35
+ css: 'css',
36
+ js: 'js',
37
+ img: 'img',
38
+ font: 'font',
39
+ media: 'media'
40
+ }
41
+ };
42
+
43
+ const alias: Record<string, string> = {
44
+ '@': path.join(workspace, roots.source)
45
+ };
46
+
47
+ const styles = {
48
+ extname: 'scss',
49
+ minify: false,
50
+ atImportPaths: [],
51
+ alias: {},
52
+ options: {},
53
+ sassOptions: {},
54
+ lessOptions: {},
55
+ postcssLoaderOptions: {},
56
+ postcssPlugins: [],
57
+ sprites: [],
58
+ spriteOptions: {}
59
+ };
60
+
61
+ const scripts = {
62
+ bundler: BundlerType.webpack,
63
+ minify: false,
64
+ minifyOptions: {},
65
+ entry: '',
66
+ target: 'web',
67
+ library: '',
68
+ libraryTarget: 'var',
69
+ externals: {},
70
+ injectHtml: false,
71
+ htmlName: 'index.html',
72
+ alias: {},
73
+ plugins: [],
74
+ loaders: [],
75
+ defaultLoaders: {
76
+ html: true,
77
+ css: true,
78
+ js: true,
79
+ url: true
80
+ },
81
+ options: {},
82
+ esbuildOptions: {},
83
+ rollupOptions: {},
84
+ webpackOptions: {},
85
+ useCache: false
86
+ };
87
+
88
+ const html = {
89
+ options: {
90
+ collapseWhitespace: true,
91
+ minifyCSS: true,
92
+ minifyJS: {
93
+ compress: {
94
+ drop_console: true
95
+ }
96
+ },
97
+ processConditionalComments: true,
98
+ removeComments: true,
99
+ removeEmptyAttributes: true,
100
+ removeScriptTypeAttributes: true,
101
+ removeStyleLinkTypeAttributes: true
102
+ }
103
+ };
104
+
105
+ const assets = {
106
+ root: 'assets',
107
+ mainDir: 'public',
108
+ subDir: '',
109
+ buildDir: 'build',
110
+ virtualDir: '',
111
+ cache: false,
112
+ options: {
113
+ fileNameManifest: 'rev-manifest.json',
114
+ dontRenameFile: ['.html'],
115
+ dontUpdateReference: []
116
+ },
117
+ includes: [],
118
+ excludes: []
119
+ };
120
+
121
+ const server = {
122
+ host: null,
123
+ port: 3000,
124
+ open: true,
125
+ proxy: false,
126
+ proxyOptions: false,
127
+ historyOptions: false,
128
+ useHMR: false,
129
+ options: {}
130
+ };
131
+
132
+ const pwa = {
133
+ enabled: false,
134
+ mode: 'generateSW' as const,
135
+ version: '',
136
+ manifest: 'manifest.json',
137
+ swSrcFilename: 'service-worker.js',
138
+ swDestFilename: 'service-worker.js',
139
+ options: {}
140
+ };
141
+
142
+ const ftp = {
143
+ options: {},
144
+ watchFiles: []
145
+ };
146
+
147
+ const images = {
148
+ plugins: []
149
+ };
150
+
151
+ const env = {
152
+ isProd,
153
+ isDev,
154
+ isTest,
155
+ inFrontend: true,
156
+ inSSR: false,
157
+ inDesktopApp: false,
158
+ isMP: false
159
+ };
160
+
161
+ const src = {
162
+ base: path.join(workspace, roots.source),
163
+ html: path.join(workspace, roots.source, paths.source.html),
164
+ css: path.join(workspace, roots.source, paths.source.css),
165
+ js: path.join(workspace, roots.source, paths.source.js),
166
+ img: path.join(workspace, roots.source, paths.source.img),
167
+ font: path.join(workspace, roots.source, paths.source.font),
168
+ media: path.join(workspace, roots.source, paths.source.media)
169
+ };
170
+
171
+ const targetBase = path.join(workspace, isProd ? roots.target : roots.tmp);
172
+ const dest = {
173
+ base: targetBase,
174
+ html: targetBase,
175
+ css: path.join(targetBase, isProd ? paths.target.css : paths.tmp.css),
176
+ js: path.join(targetBase, isProd ? paths.target.js : paths.tmp.js),
177
+ img: path.join(targetBase, isProd ? paths.target.img : paths.tmp.img),
178
+ font: path.join(targetBase, isProd ? paths.target.font : paths.tmp.font),
179
+ media: path.join(targetBase, isProd ? paths.target.media : paths.tmp.media),
180
+ static: path.join(targetBase, assets.virtualDir, assets.subDir)
181
+ };
182
+
183
+ return {
184
+ workspace,
185
+ workspaces: {
186
+ local: workspace,
187
+ global: path.resolve(workspace, '..')
188
+ },
189
+ alias,
190
+ env,
191
+ inFrontend: true,
192
+ useDefaults: true,
193
+ roots,
194
+ paths,
195
+ styles,
196
+ scripts,
197
+ html,
198
+ assets,
199
+ server,
200
+ pwa,
201
+ ftp,
202
+ images,
203
+ logs: {
204
+ level: 1
205
+ },
206
+ src,
207
+ dest
208
+ };
209
+ }
@@ -0,0 +1,112 @@
1
+ import path from 'node:path';
2
+ import { BalmConfig, BalmCustomConfig } from '../types/index.js';
3
+ import { createDefaultConfig } from './defaults.js';
4
+ import { deepMerge } from '../utilities/utils.js';
5
+ import { ASSETS_TYPES } from './constants.js';
6
+ import { setWorkspaces } from '../utilities/workspace.js';
7
+
8
+ export function resolveConfig(
9
+ customConfig: BalmCustomConfig = {},
10
+ defaultWorkspace = process.cwd()
11
+ ): BalmConfig {
12
+ let localWorkspace = defaultWorkspace;
13
+ let globalWorkspace = path.resolve(defaultWorkspace, '..');
14
+
15
+ if (customConfig.workspace) {
16
+ if (typeof customConfig.workspace === 'string') {
17
+ localWorkspace = path.resolve(customConfig.workspace);
18
+ globalWorkspace = path.resolve(localWorkspace, '..');
19
+ } else if (typeof customConfig.workspace === 'object') {
20
+ localWorkspace = path.resolve(customConfig.workspace.local || defaultWorkspace);
21
+ globalWorkspace = path.resolve(
22
+ customConfig.workspace.global || path.resolve(localWorkspace, '..')
23
+ );
24
+ }
25
+ }
26
+
27
+ setWorkspaces(localWorkspace, globalWorkspace);
28
+
29
+ const defaultConfig = createDefaultConfig(localWorkspace);
30
+ const config = deepMerge(defaultConfig, customConfig) as BalmConfig;
31
+
32
+ // Set normalized workspace path
33
+ config.workspace = localWorkspace;
34
+ config.workspaces = {
35
+ local: localWorkspace,
36
+ global: globalWorkspace
37
+ };
38
+
39
+ // Update src quick directories
40
+ config.src = {
41
+ base: path.join(config.workspace, config.roots.source),
42
+ html: path.join(config.workspace, config.roots.source, config.paths.source.html),
43
+ css: path.join(config.workspace, config.roots.source, config.paths.source.css),
44
+ js: path.join(config.workspace, config.roots.source, config.paths.source.js),
45
+ img: path.join(config.workspace, config.roots.source, config.paths.source.img),
46
+ font: path.join(config.workspace, config.roots.source, config.paths.source.font),
47
+ media: path.join(config.workspace, config.roots.source, config.paths.source.media)
48
+ };
49
+
50
+ // Update dest quick directories
51
+ const targetBase = path.join(
52
+ config.workspace,
53
+ config.env.isProd || !config.inFrontend ? config.roots.target : config.roots.tmp
54
+ );
55
+
56
+ const isProd = config.env.isProd || !config.inFrontend;
57
+ const pathMap = isProd ? config.paths.target : config.paths.tmp;
58
+
59
+ const destStatic = path.join(
60
+ targetBase,
61
+ config.assets.virtualDir,
62
+ config.assets.subDir
63
+ );
64
+
65
+ config.dest = {
66
+ base: targetBase,
67
+ html: targetBase,
68
+ css: path.join(targetBase, pathMap.css),
69
+ js: path.join(targetBase, pathMap.js),
70
+ img: path.join(targetBase, pathMap.img),
71
+ font: path.join(targetBase, pathMap.font),
72
+ media: path.join(targetBase, pathMap.media),
73
+ static: destStatic
74
+ };
75
+
76
+ // Set assets.static
77
+ config.assets.static = path.join(
78
+ config.assets.root,
79
+ config.assets.mainDir,
80
+ config.assets.subDir
81
+ );
82
+
83
+ for (const assetType of ASSETS_TYPES) {
84
+ (config.assets as any)[assetType] = path.join(
85
+ config.assets.static,
86
+ (config.paths.target as any)[assetType]
87
+ );
88
+ }
89
+
90
+ // Set HMR flag
91
+ const hmrEnv =
92
+ config.useDefaults &&
93
+ config.env.isDev &&
94
+ !config.env.inSSR &&
95
+ !config.env.isMP;
96
+ const hmrEnabling = config.scripts.bundler === 'webpack';
97
+ config.server.useHMR = hmrEnv && hmrEnabling;
98
+
99
+ // Set desktop app
100
+ if (/^electron-.*/.test(config.scripts.target as string)) {
101
+ config.env.inDesktopApp = true;
102
+ }
103
+
104
+ // Set use cache for webpack
105
+ config.scripts.useCache =
106
+ config.env.isProd && config.assets.cache && config.scripts.injectHtml;
107
+
108
+ return config;
109
+ }
110
+
111
+ export * from './constants.js';
112
+ export * from './defaults.js';