balm-core 5.2.0 → 6.0.0-alpha.0

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 (299) hide show
  1. package/dist/index.cjs +2191 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +559 -0
  4. package/dist/index.d.ts +559 -0
  5. package/dist/index.js +2098 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +48 -123
  8. package/src/balm.ts +103 -0
  9. package/src/bundler/esbuild.ts +47 -0
  10. package/src/bundler/index.ts +3 -0
  11. package/src/bundler/rollup.ts +39 -0
  12. package/src/bundler/webpack.ts +82 -0
  13. package/src/config/constants.ts +12 -0
  14. package/src/config/defaults.ts +209 -0
  15. package/src/config/index.ts +112 -0
  16. package/src/hooks/index.ts +192 -0
  17. package/src/index.ts +16 -0
  18. package/src/pipeline/file.ts +69 -0
  19. package/src/pipeline/index.ts +10 -0
  20. package/src/pipeline/pipeline.ts +132 -0
  21. package/src/pipeline/transforms/cache.ts +96 -0
  22. package/src/pipeline/transforms/htmlmin.ts +18 -0
  23. package/src/pipeline/transforms/less.ts +75 -0
  24. package/src/pipeline/transforms/postcss.ts +43 -0
  25. package/src/pipeline/transforms/rename.ts +37 -0
  26. package/src/pipeline/transforms/replace.ts +30 -0
  27. package/src/pipeline/transforms/sass.ts +106 -0
  28. package/src/pipeline/transforms/terser.ts +20 -0
  29. package/src/runner/dag.ts +77 -0
  30. package/src/runner/task.ts +38 -0
  31. package/src/shims.d.ts +5 -0
  32. package/src/tasks/cache.ts +58 -0
  33. package/src/tasks/clean.ts +21 -0
  34. package/src/tasks/copy.ts +36 -0
  35. package/src/tasks/ftp.ts +90 -0
  36. package/src/tasks/html.ts +78 -0
  37. package/src/tasks/index.ts +13 -0
  38. package/src/tasks/publish.ts +71 -0
  39. package/src/tasks/pwa.ts +49 -0
  40. package/src/tasks/remove.ts +24 -0
  41. package/src/tasks/replace.ts +34 -0
  42. package/src/tasks/script.ts +28 -0
  43. package/src/tasks/server.ts +89 -0
  44. package/src/tasks/style.ts +57 -0
  45. package/src/tasks/zip.ts +65 -0
  46. package/src/types/index.ts +200 -0
  47. package/src/utilities/file.ts +120 -0
  48. package/src/utilities/logger.ts +63 -0
  49. package/src/utilities/utils.ts +46 -0
  50. package/src/utilities/workspace.ts +38 -0
  51. package/src/watcher/index.ts +100 -0
  52. package/tsconfig.json +8 -0
  53. package/tsup.config.ts +12 -0
  54. package/README.md +0 -196
  55. package/index.d.ts +0 -360
  56. package/lib/balm.js +0 -49
  57. package/lib/bootstrap/check_config.js +0 -43
  58. package/lib/bootstrap/index.js +0 -87
  59. package/lib/bundler/esbuild/build.js +0 -26
  60. package/lib/bundler/esbuild/index.js +0 -7
  61. package/lib/bundler/esbuild/options.js +0 -7
  62. package/lib/bundler/esbuild/transform.js +0 -36
  63. package/lib/bundler/rollup/build.js +0 -52
  64. package/lib/bundler/rollup/entry.js +0 -28
  65. package/lib/bundler/rollup/index.js +0 -20
  66. package/lib/bundler/rollup/output.js +0 -20
  67. package/lib/bundler/rollup/plugins.js +0 -31
  68. package/lib/bundler/webpack/config/common.js +0 -135
  69. package/lib/bundler/webpack/config/dev.js +0 -12
  70. package/lib/bundler/webpack/config/env.js +0 -67
  71. package/lib/bundler/webpack/config/index.js +0 -6
  72. package/lib/bundler/webpack/config/prod.js +0 -39
  73. package/lib/bundler/webpack/config/regex.js +0 -10
  74. package/lib/bundler/webpack/entry.js +0 -65
  75. package/lib/bundler/webpack/index.js +0 -32
  76. package/lib/bundler/webpack/loaders.js +0 -50
  77. package/lib/bundler/webpack/output.js +0 -41
  78. package/lib/bundler/webpack/rules/asset.js +0 -33
  79. package/lib/bundler/webpack/rules/babel.js +0 -19
  80. package/lib/bundler/webpack/rules/css.js +0 -109
  81. package/lib/bundler/webpack/rules/html.js +0 -15
  82. package/lib/bundler/webpack/rules/index.js +0 -10
  83. package/lib/config/assets.js +0 -30
  84. package/lib/config/constants.js +0 -14
  85. package/lib/config/env.js +0 -35
  86. package/lib/config/extras.js +0 -6
  87. package/lib/config/ftp.js +0 -6
  88. package/lib/config/globals.js +0 -43
  89. package/lib/config/html.js +0 -22
  90. package/lib/config/images.js +0 -4
  91. package/lib/config/index.js +0 -63
  92. package/lib/config/logs.js +0 -11
  93. package/lib/config/paths.js +0 -46
  94. package/lib/config/pwa.js +0 -24
  95. package/lib/config/roots.js +0 -9
  96. package/lib/config/scripts.js +0 -162
  97. package/lib/config/server.js +0 -84
  98. package/lib/config/spinner.js +0 -9
  99. package/lib/config/styles.js +0 -67
  100. package/lib/hello.js +0 -19
  101. package/lib/hooks/index.js +0 -94
  102. package/lib/hooks/maker.js +0 -59
  103. package/lib/index.js +0 -5
  104. package/lib/middlewares/history.js +0 -6
  105. package/lib/middlewares/index.js +0 -11
  106. package/lib/middlewares/proxy.js +0 -28
  107. package/lib/middlewares/webpack.js +0 -26
  108. package/lib/plugins/htmlmin.js +0 -39
  109. package/lib/plugins/imagemin.js +0 -95
  110. package/lib/plugins/index.js +0 -27
  111. package/lib/plugins/jsmin.js +0 -37
  112. package/lib/plugins/less.js +0 -97
  113. package/lib/plugins/plumber.js +0 -87
  114. package/lib/plugins/postcss-plugins.js +0 -13
  115. package/lib/plugins/postcss.js +0 -117
  116. package/lib/plugins/rename.js +0 -51
  117. package/lib/plugins/replace.js +0 -91
  118. package/lib/plugins/sass-legacy.js +0 -131
  119. package/lib/plugins/sass.js +0 -134
  120. package/lib/plugins/sftp.js +0 -288
  121. package/lib/tasks/default.js +0 -46
  122. package/lib/tasks/foundation/balm.js +0 -72
  123. package/lib/tasks/foundation/balm_style.js +0 -65
  124. package/lib/tasks/foundation/index.js +0 -10
  125. package/lib/tasks/index.js +0 -48
  126. package/lib/tasks/private/build.js +0 -18
  127. package/lib/tasks/private/cache.js +0 -31
  128. package/lib/tasks/private/clean.js +0 -69
  129. package/lib/tasks/private/end.js +0 -24
  130. package/lib/tasks/private/extra.js +0 -35
  131. package/lib/tasks/private/font.js +0 -15
  132. package/lib/tasks/private/image.js +0 -37
  133. package/lib/tasks/private/index.js +0 -34
  134. package/lib/tasks/private/lint.js +0 -20
  135. package/lib/tasks/private/media.js +0 -15
  136. package/lib/tasks/private/modernizr.js +0 -59
  137. package/lib/tasks/private/pwa-cache.js +0 -32
  138. package/lib/tasks/private/script.js +0 -9
  139. package/lib/tasks/private/sprite.js +0 -105
  140. package/lib/tasks/private/start.js +0 -16
  141. package/lib/tasks/private/style.js +0 -9
  142. package/lib/tasks/private/workbox-sw.js +0 -15
  143. package/lib/tasks/public/copy.js +0 -16
  144. package/lib/tasks/public/esbuild.js +0 -18
  145. package/lib/tasks/public/ftp.js +0 -39
  146. package/lib/tasks/public/html.js +0 -65
  147. package/lib/tasks/public/index.js +0 -38
  148. package/lib/tasks/public/jsmin.js +0 -23
  149. package/lib/tasks/public/less.js +0 -21
  150. package/lib/tasks/public/postcss.js +0 -16
  151. package/lib/tasks/public/publish.js +0 -51
  152. package/lib/tasks/public/pwa.js +0 -84
  153. package/lib/tasks/public/remove.js +0 -46
  154. package/lib/tasks/public/replace.js +0 -26
  155. package/lib/tasks/public/rollup.js +0 -17
  156. package/lib/tasks/public/sass.js +0 -27
  157. package/lib/tasks/public/server.js +0 -130
  158. package/lib/tasks/public/url.js +0 -35
  159. package/lib/tasks/public/version.js +0 -23
  160. package/lib/tasks/public/webpack.js +0 -39
  161. package/lib/tasks/public/zip.js +0 -19
  162. package/lib/utilities/address.js +0 -55
  163. package/lib/utilities/cache-core.js +0 -66
  164. package/lib/utilities/color.js +0 -27
  165. package/lib/utilities/compiling.js +0 -24
  166. package/lib/utilities/detect-port.js +0 -100
  167. package/lib/utilities/escape-string-regexp.js +0 -10
  168. package/lib/utilities/file.js +0 -70
  169. package/lib/utilities/index.js +0 -8
  170. package/lib/utilities/loading.js +0 -37
  171. package/lib/utilities/logger.js +0 -99
  172. package/lib/utilities/merge-stream.js +0 -38
  173. package/lib/utilities/namespace.js +0 -11
  174. package/lib/utilities/public-url.js +0 -37
  175. package/lib/utilities/replacestream.js +0 -106
  176. package/lib/utilities/typeof.js +0 -5
  177. package/lib/utilities/utils.js +0 -43
  178. package/tslib/balm.js +0 -44
  179. package/tslib/bootstrap/check_config.js +0 -36
  180. package/tslib/bootstrap/index.js +0 -82
  181. package/tslib/bundler/esbuild/build.js +0 -30
  182. package/tslib/bundler/esbuild/index.js +0 -11
  183. package/tslib/bundler/esbuild/options.js +0 -7
  184. package/tslib/bundler/esbuild/transform.js +0 -38
  185. package/tslib/bundler/rollup/build.js +0 -17
  186. package/tslib/bundler/rollup/entry.js +0 -24
  187. package/tslib/bundler/rollup/index.js +0 -21
  188. package/tslib/bundler/rollup/output.js +0 -23
  189. package/tslib/bundler/rollup/plugins.js +0 -27
  190. package/tslib/bundler/webpack/config/common.js +0 -130
  191. package/tslib/bundler/webpack/config/dev.js +0 -14
  192. package/tslib/bundler/webpack/config/env.js +0 -44
  193. package/tslib/bundler/webpack/config/index.js +0 -8
  194. package/tslib/bundler/webpack/config/prod.js +0 -43
  195. package/tslib/bundler/webpack/config/regex.js +0 -10
  196. package/tslib/bundler/webpack/entry.js +0 -68
  197. package/tslib/bundler/webpack/index.js +0 -30
  198. package/tslib/bundler/webpack/loaders.js +0 -51
  199. package/tslib/bundler/webpack/output.js +0 -41
  200. package/tslib/bundler/webpack/rules/asset.js +0 -33
  201. package/tslib/bundler/webpack/rules/babel.js +0 -16
  202. package/tslib/bundler/webpack/rules/css.js +0 -95
  203. package/tslib/bundler/webpack/rules/html.js +0 -15
  204. package/tslib/bundler/webpack/rules/index.js +0 -10
  205. package/tslib/config/assets.js +0 -24
  206. package/tslib/config/constants.js +0 -14
  207. package/tslib/config/env.js +0 -43
  208. package/tslib/config/extras.js +0 -6
  209. package/tslib/config/ftp.js +0 -6
  210. package/tslib/config/globals.js +0 -47
  211. package/tslib/config/html.js +0 -17
  212. package/tslib/config/images.js +0 -4
  213. package/tslib/config/index.js +0 -56
  214. package/tslib/config/logs.js +0 -6
  215. package/tslib/config/paths.js +0 -30
  216. package/tslib/config/pwa.js +0 -18
  217. package/tslib/config/roots.js +0 -8
  218. package/tslib/config/scripts.js +0 -93
  219. package/tslib/config/server.js +0 -33
  220. package/tslib/config/spinner.js +0 -10
  221. package/tslib/config/styles.js +0 -37
  222. package/tslib/hello.js +0 -19
  223. package/tslib/hooks/index.js +0 -75
  224. package/tslib/hooks/maker.js +0 -66
  225. package/tslib/index.js +0 -5
  226. package/tslib/middlewares/history.js +0 -12
  227. package/tslib/middlewares/index.js +0 -18
  228. package/tslib/middlewares/proxy.js +0 -27
  229. package/tslib/middlewares/webpack.js +0 -29
  230. package/tslib/plugins/htmlmin.js +0 -38
  231. package/tslib/plugins/imagemin.js +0 -97
  232. package/tslib/plugins/index.js +0 -27
  233. package/tslib/plugins/jsmin.js +0 -39
  234. package/tslib/plugins/less.js +0 -90
  235. package/tslib/plugins/plumber.js +0 -81
  236. package/tslib/plugins/postcss-plugins.js +0 -24
  237. package/tslib/plugins/postcss.js +0 -111
  238. package/tslib/plugins/rename.js +0 -51
  239. package/tslib/plugins/replace.js +0 -72
  240. package/tslib/plugins/sass-legacy.js +0 -95
  241. package/tslib/plugins/sass.js +0 -109
  242. package/tslib/plugins/sftp.js +0 -258
  243. package/tslib/tasks/default.js +0 -59
  244. package/tslib/tasks/foundation/balm.js +0 -75
  245. package/tslib/tasks/foundation/balm_style.js +0 -68
  246. package/tslib/tasks/foundation/index.js +0 -10
  247. package/tslib/tasks/index.js +0 -43
  248. package/tslib/tasks/private/build.js +0 -15
  249. package/tslib/tasks/private/cache.js +0 -48
  250. package/tslib/tasks/private/clean.js +0 -82
  251. package/tslib/tasks/private/end.js +0 -21
  252. package/tslib/tasks/private/extra.js +0 -34
  253. package/tslib/tasks/private/font.js +0 -12
  254. package/tslib/tasks/private/image.js +0 -42
  255. package/tslib/tasks/private/index.js +0 -34
  256. package/tslib/tasks/private/lint.js +0 -17
  257. package/tslib/tasks/private/media.js +0 -12
  258. package/tslib/tasks/private/modernizr.js +0 -54
  259. package/tslib/tasks/private/pwa-cache.js +0 -32
  260. package/tslib/tasks/private/script.js +0 -9
  261. package/tslib/tasks/private/sprite.js +0 -93
  262. package/tslib/tasks/private/start.js +0 -13
  263. package/tslib/tasks/private/style.js +0 -12
  264. package/tslib/tasks/private/workbox-sw.js +0 -15
  265. package/tslib/tasks/public/copy.js +0 -18
  266. package/tslib/tasks/public/esbuild.js +0 -18
  267. package/tslib/tasks/public/ftp.js +0 -39
  268. package/tslib/tasks/public/html.js +0 -75
  269. package/tslib/tasks/public/index.js +0 -38
  270. package/tslib/tasks/public/jsmin.js +0 -24
  271. package/tslib/tasks/public/less.js +0 -21
  272. package/tslib/tasks/public/postcss.js +0 -16
  273. package/tslib/tasks/public/publish.js +0 -50
  274. package/tslib/tasks/public/pwa.js +0 -87
  275. package/tslib/tasks/public/remove.js +0 -44
  276. package/tslib/tasks/public/replace.js +0 -27
  277. package/tslib/tasks/public/rollup.js +0 -17
  278. package/tslib/tasks/public/sass.js +0 -27
  279. package/tslib/tasks/public/server.js +0 -129
  280. package/tslib/tasks/public/url.js +0 -35
  281. package/tslib/tasks/public/version.js +0 -27
  282. package/tslib/tasks/public/webpack.js +0 -41
  283. package/tslib/tasks/public/zip.js +0 -19
  284. package/tslib/utilities/address.js +0 -48
  285. package/tslib/utilities/cache-core.js +0 -57
  286. package/tslib/utilities/color.js +0 -33
  287. package/tslib/utilities/compiling.js +0 -16
  288. package/tslib/utilities/detect-port.js +0 -91
  289. package/tslib/utilities/escape-string-regexp.js +0 -7
  290. package/tslib/utilities/file.js +0 -78
  291. package/tslib/utilities/index.js +0 -8
  292. package/tslib/utilities/loading.js +0 -25
  293. package/tslib/utilities/logger.js +0 -92
  294. package/tslib/utilities/merge-stream.js +0 -34
  295. package/tslib/utilities/namespace.js +0 -12
  296. package/tslib/utilities/public-url.js +0 -31
  297. package/tslib/utilities/replacestream.js +0 -112
  298. package/tslib/utilities/typeof.js +0 -8
  299. package/tslib/utilities/utils.js +0 -38
package/dist/index.cjs ADDED
@@ -0,0 +1,2191 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ASSET: () => ASSET,
34
+ ASSETS_TYPES: () => ASSETS_TYPES,
35
+ ASSET_EXT: () => ASSET_EXT,
36
+ AssetRevisioner: () => AssetRevisioner,
37
+ Balm: () => Balm,
38
+ BalmHooks: () => BalmHooks,
39
+ BaseTask: () => BaseTask,
40
+ BundlerType: () => BundlerType,
41
+ CHUNK: () => CHUNK,
42
+ CacheTask: () => CacheTask,
43
+ CleanTask: () => CleanTask,
44
+ CopyTask: () => CopyTask,
45
+ FileSystem: () => FileSystem,
46
+ FtpTask: () => FtpTask,
47
+ FunctionTask: () => FunctionTask,
48
+ HtmlTask: () => HtmlTask,
49
+ LogLevel: () => LogLevel,
50
+ PUBLIC_URL: () => PUBLIC_URL,
51
+ Pipeline: () => Pipeline,
52
+ PublishTask: () => PublishTask,
53
+ PwaTask: () => PwaTask,
54
+ RemoveTask: () => RemoveTask,
55
+ ReplaceTask: () => ReplaceTask,
56
+ ScriptTask: () => ScriptTask,
57
+ ServerTask: () => ServerTask,
58
+ StyleTask: () => StyleTask,
59
+ TaskDAG: () => TaskDAG,
60
+ VirtualFile: () => VirtualFile,
61
+ ZipTask: () => ZipTask,
62
+ balm: () => balm,
63
+ createDefaultConfig: () => createDefaultConfig,
64
+ deepMerge: () => deepMerge,
65
+ default: () => index_default,
66
+ file: () => file,
67
+ getWorkspaces: () => getWorkspaces,
68
+ globalResolve: () => globalResolve,
69
+ globalWorkspace: () => globalWorkspace,
70
+ isArray: () => isArray,
71
+ isBoolean: () => isBoolean,
72
+ isFunction: () => isFunction,
73
+ isObject: () => isObject,
74
+ isString: () => isString,
75
+ localResolve: () => localResolve,
76
+ localWorkspace: () => localWorkspace,
77
+ logger: () => logger,
78
+ resolveConfig: () => resolveConfig,
79
+ runEsbuild: () => runEsbuild,
80
+ runRollup: () => runRollup,
81
+ runWebpack: () => runWebpack,
82
+ setWorkspaces: () => setWorkspaces,
83
+ toNamespace: () => toNamespace,
84
+ transformHtmlmin: () => transformHtmlmin,
85
+ transformLess: () => transformLess,
86
+ transformPostcss: () => transformPostcss,
87
+ transformRename: () => transformRename,
88
+ transformReplace: () => transformReplace,
89
+ transformSass: () => transformSass,
90
+ transformTerser: () => transformTerser
91
+ });
92
+ module.exports = __toCommonJS(index_exports);
93
+
94
+ // src/types/index.ts
95
+ var BundlerType = /* @__PURE__ */ ((BundlerType2) => {
96
+ BundlerType2["webpack"] = "webpack";
97
+ BundlerType2["rollup"] = "rollup";
98
+ BundlerType2["esbuild"] = "esbuild";
99
+ return BundlerType2;
100
+ })(BundlerType || {});
101
+
102
+ // src/config/index.ts
103
+ var import_node_path3 = __toESM(require("path"), 1);
104
+
105
+ // src/config/defaults.ts
106
+ var import_node_path = __toESM(require("path"), 1);
107
+ function createDefaultConfig(workspace = process.cwd()) {
108
+ const isProd = process.env.NODE_ENV === "production";
109
+ const isDev = !isProd;
110
+ const isTest = process.env.NODE_ENV === "test";
111
+ const roots = {
112
+ source: "src",
113
+ tmp: ".tmp",
114
+ target: "dist"
115
+ };
116
+ const paths = {
117
+ source: {
118
+ base: "",
119
+ html: "",
120
+ css: "styles",
121
+ js: "scripts",
122
+ img: "images",
123
+ font: "fonts",
124
+ media: "media"
125
+ },
126
+ tmp: {
127
+ base: "",
128
+ css: "css",
129
+ js: "js",
130
+ img: "img",
131
+ font: "fonts",
132
+ media: "media"
133
+ },
134
+ target: {
135
+ base: "",
136
+ css: "css",
137
+ js: "js",
138
+ img: "img",
139
+ font: "font",
140
+ media: "media"
141
+ }
142
+ };
143
+ const alias = {
144
+ "@": import_node_path.default.join(workspace, roots.source)
145
+ };
146
+ const styles = {
147
+ extname: "scss",
148
+ minify: false,
149
+ atImportPaths: [],
150
+ alias: {},
151
+ options: {},
152
+ sassOptions: {},
153
+ lessOptions: {},
154
+ postcssLoaderOptions: {},
155
+ postcssPlugins: [],
156
+ sprites: [],
157
+ spriteOptions: {}
158
+ };
159
+ const scripts = {
160
+ bundler: "webpack" /* webpack */,
161
+ minify: false,
162
+ minifyOptions: {},
163
+ entry: "",
164
+ target: "web",
165
+ library: "",
166
+ libraryTarget: "var",
167
+ externals: {},
168
+ injectHtml: false,
169
+ htmlName: "index.html",
170
+ alias: {},
171
+ plugins: [],
172
+ loaders: [],
173
+ defaultLoaders: {
174
+ html: true,
175
+ css: true,
176
+ js: true,
177
+ url: true
178
+ },
179
+ options: {},
180
+ esbuildOptions: {},
181
+ rollupOptions: {},
182
+ webpackOptions: {},
183
+ useCache: false
184
+ };
185
+ const html = {
186
+ options: {
187
+ collapseWhitespace: true,
188
+ minifyCSS: true,
189
+ minifyJS: {
190
+ compress: {
191
+ drop_console: true
192
+ }
193
+ },
194
+ processConditionalComments: true,
195
+ removeComments: true,
196
+ removeEmptyAttributes: true,
197
+ removeScriptTypeAttributes: true,
198
+ removeStyleLinkTypeAttributes: true
199
+ }
200
+ };
201
+ const assets = {
202
+ root: "assets",
203
+ mainDir: "public",
204
+ subDir: "",
205
+ buildDir: "build",
206
+ virtualDir: "",
207
+ cache: false,
208
+ options: {
209
+ fileNameManifest: "rev-manifest.json",
210
+ dontRenameFile: [".html"],
211
+ dontUpdateReference: []
212
+ },
213
+ includes: [],
214
+ excludes: []
215
+ };
216
+ const server = {
217
+ host: null,
218
+ port: 3e3,
219
+ open: true,
220
+ proxy: false,
221
+ proxyOptions: false,
222
+ historyOptions: false,
223
+ useHMR: false,
224
+ options: {}
225
+ };
226
+ const pwa = {
227
+ enabled: false,
228
+ mode: "generateSW",
229
+ version: "",
230
+ manifest: "manifest.json",
231
+ swSrcFilename: "service-worker.js",
232
+ swDestFilename: "sw.js",
233
+ options: {}
234
+ };
235
+ const ftp = {
236
+ options: {},
237
+ watchFiles: []
238
+ };
239
+ const images = {
240
+ plugins: []
241
+ };
242
+ const env = {
243
+ isProd,
244
+ isDev,
245
+ isTest,
246
+ inFrontend: true,
247
+ inSSR: false,
248
+ inDesktopApp: false,
249
+ isMP: false
250
+ };
251
+ const src = {
252
+ base: import_node_path.default.join(workspace, roots.source),
253
+ html: import_node_path.default.join(workspace, roots.source, paths.source.html),
254
+ css: import_node_path.default.join(workspace, roots.source, paths.source.css),
255
+ js: import_node_path.default.join(workspace, roots.source, paths.source.js),
256
+ img: import_node_path.default.join(workspace, roots.source, paths.source.img),
257
+ font: import_node_path.default.join(workspace, roots.source, paths.source.font),
258
+ media: import_node_path.default.join(workspace, roots.source, paths.source.media)
259
+ };
260
+ const targetBase = import_node_path.default.join(workspace, isProd ? roots.target : roots.tmp);
261
+ const dest = {
262
+ base: targetBase,
263
+ html: targetBase,
264
+ css: import_node_path.default.join(targetBase, isProd ? paths.target.css : paths.tmp.css),
265
+ js: import_node_path.default.join(targetBase, isProd ? paths.target.js : paths.tmp.js),
266
+ img: import_node_path.default.join(targetBase, isProd ? paths.target.img : paths.tmp.img),
267
+ font: import_node_path.default.join(targetBase, isProd ? paths.target.font : paths.tmp.font),
268
+ media: import_node_path.default.join(targetBase, isProd ? paths.target.media : paths.tmp.media),
269
+ static: import_node_path.default.join(targetBase, assets.virtualDir, assets.subDir)
270
+ };
271
+ return {
272
+ workspace,
273
+ workspaces: {
274
+ local: workspace,
275
+ global: import_node_path.default.resolve(workspace, "..")
276
+ },
277
+ alias,
278
+ env,
279
+ inFrontend: true,
280
+ useDefaults: true,
281
+ roots,
282
+ paths,
283
+ styles,
284
+ scripts,
285
+ html,
286
+ assets,
287
+ server,
288
+ pwa,
289
+ ftp,
290
+ images,
291
+ logs: {
292
+ level: 1
293
+ },
294
+ src,
295
+ dest
296
+ };
297
+ }
298
+
299
+ // src/utilities/utils.ts
300
+ function isObject(val) {
301
+ return val !== null && typeof val === "object" && !Array.isArray(val);
302
+ }
303
+ function isArray(val) {
304
+ return Array.isArray(val);
305
+ }
306
+ function isString(val) {
307
+ return typeof val === "string";
308
+ }
309
+ function isFunction(val) {
310
+ return typeof val === "function";
311
+ }
312
+ function isBoolean(val) {
313
+ return typeof val === "boolean";
314
+ }
315
+ function deepMerge(target, ...sources) {
316
+ if (!sources.length) return target;
317
+ const source = sources.shift();
318
+ if (isObject(target) && isObject(source)) {
319
+ for (const key in source) {
320
+ if (isObject(source[key])) {
321
+ if (!target[key]) Object.assign(target, { [key]: {} });
322
+ deepMerge(target[key], source[key]);
323
+ } else if (isArray(source[key])) {
324
+ target[key] = [...source[key]];
325
+ } else if (source[key] !== void 0) {
326
+ Object.assign(target, { [key]: source[key] });
327
+ }
328
+ }
329
+ }
330
+ return deepMerge(target, ...sources);
331
+ }
332
+ function toNamespace(name, namespace = "balm") {
333
+ if (isArray(name)) {
334
+ return name.map((item) => `${namespace}:${item}`);
335
+ }
336
+ return `${namespace}:${name}`;
337
+ }
338
+
339
+ // src/config/constants.ts
340
+ var ASSETS_TYPES = ["css", "js", "img", "font", "media"];
341
+ var PUBLIC_URL = "%PUBLIC_URL%";
342
+ var CHUNK = { dir: "chunk" };
343
+ var ASSET = { dir: "asset" };
344
+ var ASSET_EXT = {
345
+ styles: ["css", "scss", "sass", "less"],
346
+ scripts: ["js", "mjs", "cjs", "ts", "mts", "cts", "jsx", "tsx"],
347
+ images: ["png", "jpg", "jpeg", "gif", "svg", "webp", "ico"],
348
+ fonts: ["woff", "woff2", "ttf", "eot", "otf"],
349
+ media: ["mp4", "webm", "ogg", "mp3", "wav", "flac", "aac"]
350
+ };
351
+
352
+ // src/utilities/workspace.ts
353
+ var import_node_path2 = __toESM(require("path"), 1);
354
+ var currentLocalWorkspace = process.cwd();
355
+ var currentGlobalWorkspace = import_node_path2.default.resolve(process.cwd(), "..");
356
+ function setWorkspaces(local, global) {
357
+ if (local) {
358
+ currentLocalWorkspace = import_node_path2.default.resolve(local);
359
+ }
360
+ if (global) {
361
+ currentGlobalWorkspace = import_node_path2.default.resolve(global);
362
+ } else if (local && !global) {
363
+ currentGlobalWorkspace = import_node_path2.default.resolve(currentLocalWorkspace, "..");
364
+ }
365
+ }
366
+ function getWorkspaces() {
367
+ return {
368
+ local: currentLocalWorkspace,
369
+ global: currentGlobalWorkspace
370
+ };
371
+ }
372
+ function localWorkspace(subPath = "") {
373
+ return subPath ? import_node_path2.default.resolve(currentLocalWorkspace, subPath) : currentLocalWorkspace;
374
+ }
375
+ function globalWorkspace(subPath = "") {
376
+ return subPath ? import_node_path2.default.resolve(currentGlobalWorkspace, subPath) : currentGlobalWorkspace;
377
+ }
378
+ var localResolve = localWorkspace;
379
+ var globalResolve = globalWorkspace;
380
+
381
+ // src/config/index.ts
382
+ function resolveConfig(customConfig = {}, defaultWorkspace = process.cwd()) {
383
+ let localWorkspace2 = defaultWorkspace;
384
+ let globalWorkspace2 = import_node_path3.default.resolve(defaultWorkspace, "..");
385
+ if (customConfig.workspace) {
386
+ if (typeof customConfig.workspace === "string") {
387
+ localWorkspace2 = import_node_path3.default.resolve(customConfig.workspace);
388
+ globalWorkspace2 = import_node_path3.default.resolve(localWorkspace2, "..");
389
+ } else if (typeof customConfig.workspace === "object") {
390
+ localWorkspace2 = import_node_path3.default.resolve(customConfig.workspace.local || defaultWorkspace);
391
+ globalWorkspace2 = import_node_path3.default.resolve(
392
+ customConfig.workspace.global || import_node_path3.default.resolve(localWorkspace2, "..")
393
+ );
394
+ }
395
+ }
396
+ setWorkspaces(localWorkspace2, globalWorkspace2);
397
+ const defaultConfig = createDefaultConfig(localWorkspace2);
398
+ const config = deepMerge(defaultConfig, customConfig);
399
+ config.workspace = localWorkspace2;
400
+ config.workspaces = {
401
+ local: localWorkspace2,
402
+ global: globalWorkspace2
403
+ };
404
+ config.src = {
405
+ base: import_node_path3.default.join(config.workspace, config.roots.source),
406
+ html: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.html),
407
+ css: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.css),
408
+ js: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.js),
409
+ img: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.img),
410
+ font: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.font),
411
+ media: import_node_path3.default.join(config.workspace, config.roots.source, config.paths.source.media)
412
+ };
413
+ const targetBase = import_node_path3.default.join(
414
+ config.workspace,
415
+ config.env.isProd || !config.inFrontend ? config.roots.target : config.roots.tmp
416
+ );
417
+ const isProd = config.env.isProd || !config.inFrontend;
418
+ const pathMap = isProd ? config.paths.target : config.paths.tmp;
419
+ const destStatic = import_node_path3.default.join(
420
+ targetBase,
421
+ config.assets.virtualDir,
422
+ config.assets.subDir
423
+ );
424
+ config.dest = {
425
+ base: targetBase,
426
+ html: targetBase,
427
+ css: import_node_path3.default.join(targetBase, pathMap.css),
428
+ js: import_node_path3.default.join(targetBase, pathMap.js),
429
+ img: import_node_path3.default.join(targetBase, pathMap.img),
430
+ font: import_node_path3.default.join(targetBase, pathMap.font),
431
+ media: import_node_path3.default.join(targetBase, pathMap.media),
432
+ static: destStatic
433
+ };
434
+ config.assets.static = import_node_path3.default.join(
435
+ config.assets.root,
436
+ config.assets.mainDir,
437
+ config.assets.subDir
438
+ );
439
+ for (const assetType of ASSETS_TYPES) {
440
+ config.assets[assetType] = import_node_path3.default.join(
441
+ config.assets.static,
442
+ config.paths.target[assetType]
443
+ );
444
+ }
445
+ const hmrEnv = config.useDefaults && config.env.isDev && !config.env.inSSR && !config.env.isMP;
446
+ const hmrEnabling = config.scripts.bundler === "webpack";
447
+ config.server.useHMR = hmrEnv && hmrEnabling;
448
+ if (/^electron-.*/.test(config.scripts.target)) {
449
+ config.env.inDesktopApp = true;
450
+ }
451
+ config.scripts.useCache = config.env.isProd && config.assets.cache && config.scripts.injectHtml;
452
+ return config;
453
+ }
454
+
455
+ // src/utilities/logger.ts
456
+ var import_picocolors = __toESM(require("picocolors"), 1);
457
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
458
+ LogLevel2[LogLevel2["Debug"] = 0] = "Debug";
459
+ LogLevel2[LogLevel2["Info"] = 1] = "Info";
460
+ LogLevel2[LogLevel2["Warn"] = 2] = "Warn";
461
+ LogLevel2[LogLevel2["Error"] = 3] = "Error";
462
+ LogLevel2[LogLevel2["Silent"] = 4] = "Silent";
463
+ return LogLevel2;
464
+ })(LogLevel || {});
465
+ var Logger = class {
466
+ level = 1 /* Info */;
467
+ formatTag(tag) {
468
+ return tag ? import_picocolors.default.cyan(`[${tag}]`) : import_picocolors.default.bgBlue(import_picocolors.default.black(" BalmJS "));
469
+ }
470
+ timestamp() {
471
+ const d = /* @__PURE__ */ new Date();
472
+ const pad = (n) => n.toString().padStart(2, "0");
473
+ return import_picocolors.default.gray(`[${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}]`);
474
+ }
475
+ debug(tag, message, ...args) {
476
+ if (this.level <= 0 /* Debug */) {
477
+ console.log(this.timestamp(), this.formatTag(tag), import_picocolors.default.magenta("\u203B"), message, ...args);
478
+ }
479
+ }
480
+ info(tag, message, ...args) {
481
+ if (this.level <= 1 /* Info */) {
482
+ console.log(this.timestamp(), this.formatTag(tag), import_picocolors.default.blue("\u2139"), message, ...args);
483
+ }
484
+ }
485
+ success(tag, message, ...args) {
486
+ if (this.level <= 1 /* Info */) {
487
+ console.log(this.timestamp(), this.formatTag(tag), import_picocolors.default.green("\u2714"), import_picocolors.default.green(message), ...args);
488
+ }
489
+ }
490
+ warn(tag, message, ...args) {
491
+ if (this.level <= 2 /* Warn */) {
492
+ console.warn(this.timestamp(), this.formatTag(tag), import_picocolors.default.yellow("\u26A0"), import_picocolors.default.yellow(message), ...args);
493
+ }
494
+ }
495
+ error(tag, message, ...args) {
496
+ if (this.level <= 3 /* Error */) {
497
+ console.error(this.timestamp(), this.formatTag(tag), import_picocolors.default.red("\u2716"), import_picocolors.default.red(message), ...args);
498
+ }
499
+ }
500
+ time(label) {
501
+ const start = performance.now();
502
+ return () => {
503
+ const duration = (performance.now() - start).toFixed(2);
504
+ this.info("time", `${label} completed in ${import_picocolors.default.bold(duration + "ms")}`);
505
+ };
506
+ }
507
+ };
508
+ var logger = new Logger();
509
+
510
+ // src/runner/dag.ts
511
+ var import_picocolors2 = __toESM(require("picocolors"), 1);
512
+ var TaskDAG = class {
513
+ tasks = /* @__PURE__ */ new Map();
514
+ registerTask(task) {
515
+ this.tasks.set(task.name, task);
516
+ }
517
+ getTask(name) {
518
+ return this.tasks.get(name);
519
+ }
520
+ hasTask(name) {
521
+ return this.tasks.has(name);
522
+ }
523
+ clear() {
524
+ this.tasks.clear();
525
+ }
526
+ /**
527
+ * Run a list of tasks in strict series
528
+ */
529
+ async runSeries(taskNames, config) {
530
+ for (const name of taskNames) {
531
+ await this.executeTask(name, config);
532
+ }
533
+ }
534
+ /**
535
+ * Run a list of tasks in parallel
536
+ */
537
+ async runParallel(taskNames, config) {
538
+ await Promise.all(taskNames.map((name) => this.executeTask(name, config)));
539
+ }
540
+ /**
541
+ * Execute a single task resolving its dependencies first
542
+ */
543
+ async executeTask(taskName, config, executed = /* @__PURE__ */ new Set()) {
544
+ if (executed.has(taskName)) return;
545
+ const task = this.tasks.get(taskName);
546
+ if (!task) {
547
+ logger.warn("task", `Task ${import_picocolors2.default.bold(taskName)} not found, skipping.`);
548
+ return;
549
+ }
550
+ if (task.deps && task.deps.length > 0) {
551
+ for (const dep of task.deps) {
552
+ await this.executeTask(dep, config, executed);
553
+ }
554
+ }
555
+ const start = performance.now();
556
+ try {
557
+ await task.run(config);
558
+ executed.add(taskName);
559
+ const duration = (performance.now() - start).toFixed(1);
560
+ if (!task.hidden) {
561
+ logger.info("task", `${import_picocolors2.default.cyan(task.name)} finished in ${import_picocolors2.default.bold(duration + "ms")}`);
562
+ }
563
+ } catch (error) {
564
+ logger.error("task", `Task ${import_picocolors2.default.bold(task.name)} failed: ${error?.message || error}`);
565
+ throw error;
566
+ }
567
+ }
568
+ };
569
+
570
+ // src/tasks/clean.ts
571
+ var import_node_path5 = __toESM(require("path"), 1);
572
+
573
+ // src/runner/task.ts
574
+ var BaseTask = class {
575
+ name;
576
+ deps;
577
+ description;
578
+ hidden;
579
+ constructor(options) {
580
+ this.name = options.name;
581
+ this.deps = options.deps || [];
582
+ this.description = options.description;
583
+ this.hidden = options.hidden || false;
584
+ }
585
+ };
586
+ var FunctionTask = class extends BaseTask {
587
+ fn;
588
+ constructor(name, fn, deps = []) {
589
+ super({ name, deps });
590
+ this.fn = fn;
591
+ }
592
+ async run(config) {
593
+ await this.fn(config);
594
+ }
595
+ };
596
+
597
+ // src/utilities/file.ts
598
+ var import_promises = __toESM(require("fs/promises"), 1);
599
+ var import_node_fs = require("fs");
600
+ var import_node_path4 = __toESM(require("path"), 1);
601
+ var import_node_crypto = __toESM(require("crypto"), 1);
602
+ var import_fast_glob = __toESM(require("fast-glob"), 1);
603
+ var FileSystem = class {
604
+ workspace = process.cwd();
605
+ resolveApp(...paths) {
606
+ return import_node_path4.default.resolve(this.workspace, ...paths);
607
+ }
608
+ absPath(filePath) {
609
+ return import_node_path4.default.isAbsolute(filePath) ? filePath : this.resolveApp(filePath);
610
+ }
611
+ absPaths(filePaths) {
612
+ if (Array.isArray(filePaths)) {
613
+ return filePaths.map((p) => this.absPath(p));
614
+ }
615
+ return this.absPath(filePaths);
616
+ }
617
+ async exists(targetPath) {
618
+ try {
619
+ await import_promises.default.access(this.absPath(targetPath));
620
+ return true;
621
+ } catch {
622
+ return false;
623
+ }
624
+ }
625
+ existsSync(targetPath) {
626
+ return (0, import_node_fs.existsSync)(this.absPath(targetPath));
627
+ }
628
+ async ensureDir(dirPath) {
629
+ await import_promises.default.mkdir(this.absPath(dirPath), { recursive: true });
630
+ }
631
+ async readFile(filePath, encoding = "utf8") {
632
+ return import_promises.default.readFile(this.absPath(filePath), { encoding });
633
+ }
634
+ async readBuffer(filePath) {
635
+ return import_promises.default.readFile(this.absPath(filePath));
636
+ }
637
+ async writeFile(filePath, data) {
638
+ const fullPath = this.absPath(filePath);
639
+ await this.ensureDir(import_node_path4.default.dirname(fullPath));
640
+ await import_promises.default.writeFile(fullPath, data);
641
+ }
642
+ async remove(targetPath) {
643
+ const targets = Array.isArray(targetPath) ? targetPath : [targetPath];
644
+ const removed = [];
645
+ for (const item of targets) {
646
+ const fullPath = this.absPath(item);
647
+ try {
648
+ const stat = await import_promises.default.stat(fullPath);
649
+ if (stat.isDirectory()) {
650
+ await import_promises.default.rm(fullPath, { recursive: true, force: true });
651
+ } else {
652
+ await import_promises.default.unlink(fullPath);
653
+ }
654
+ removed.push(fullPath);
655
+ } catch {
656
+ }
657
+ }
658
+ return removed;
659
+ }
660
+ async copyFile(src, dest) {
661
+ const srcPath = this.absPath(src);
662
+ const destPath = this.absPath(dest);
663
+ await this.ensureDir(import_node_path4.default.dirname(destPath));
664
+ await import_promises.default.copyFile(srcPath, destPath);
665
+ }
666
+ async copyDir(srcDir, destDir) {
667
+ const src = this.absPath(srcDir);
668
+ const dest = this.absPath(destDir);
669
+ await this.ensureDir(dest);
670
+ const entries = await import_promises.default.readdir(src, { withFileTypes: true });
671
+ for (const entry of entries) {
672
+ const srcItem = import_node_path4.default.join(src, entry.name);
673
+ const destItem = import_node_path4.default.join(dest, entry.name);
674
+ if (entry.isDirectory()) {
675
+ await this.copyDir(srcItem, destItem);
676
+ } else {
677
+ await this.copyFile(srcItem, destItem);
678
+ }
679
+ }
680
+ }
681
+ async matchFiles(patterns, options = {}) {
682
+ const defaultOptions = {
683
+ cwd: this.workspace,
684
+ absolute: true,
685
+ dot: true,
686
+ onlyFiles: true
687
+ };
688
+ return (0, import_fast_glob.default)(patterns, { ...defaultOptions, ...options });
689
+ }
690
+ hash(content, length = 8) {
691
+ return import_node_crypto.default.createHash("md5").update(content).digest("hex").slice(0, length);
692
+ }
693
+ };
694
+ var file = new FileSystem();
695
+
696
+ // src/tasks/clean.ts
697
+ var CleanTask = class extends BaseTask {
698
+ constructor() {
699
+ super({ name: "clean", description: "Clean output directories" });
700
+ }
701
+ async run(config) {
702
+ const targets = [
703
+ import_node_path5.default.join(config.workspace, config.roots.tmp),
704
+ import_node_path5.default.join(config.workspace, config.roots.target)
705
+ ];
706
+ const deleted = await file.remove(targets);
707
+ logger.info("clean", `Deleted ${deleted.length} directories`);
708
+ }
709
+ };
710
+
711
+ // src/tasks/style.ts
712
+ var import_node_path10 = __toESM(require("path"), 1);
713
+
714
+ // src/pipeline/pipeline.ts
715
+ var import_node_path7 = __toESM(require("path"), 1);
716
+ var import_fast_glob2 = __toESM(require("fast-glob"), 1);
717
+ var import_promises2 = __toESM(require("fs/promises"), 1);
718
+
719
+ // src/pipeline/file.ts
720
+ var import_node_path6 = __toESM(require("path"), 1);
721
+ var VirtualFile = class _VirtualFile {
722
+ cwd;
723
+ base;
724
+ path;
725
+ contents;
726
+ revPathOriginal;
727
+ constructor(options) {
728
+ this.cwd = options.cwd;
729
+ this.base = options.base;
730
+ this.path = options.path;
731
+ this.contents = typeof options.contents === "string" ? Buffer.from(options.contents) : options.contents;
732
+ }
733
+ get relative() {
734
+ return import_node_path6.default.relative(this.base, this.path);
735
+ }
736
+ get extname() {
737
+ return import_node_path6.default.extname(this.path);
738
+ }
739
+ set extname(val) {
740
+ const dir = import_node_path6.default.dirname(this.path);
741
+ const basename = import_node_path6.default.basename(this.path, this.extname);
742
+ this.path = import_node_path6.default.join(dir, `${basename}${val.startsWith(".") ? val : `.${val}`}`);
743
+ }
744
+ get basename() {
745
+ return import_node_path6.default.basename(this.path);
746
+ }
747
+ set basename(val) {
748
+ const dir = import_node_path6.default.dirname(this.path);
749
+ this.path = import_node_path6.default.join(dir, val);
750
+ }
751
+ get stem() {
752
+ return import_node_path6.default.basename(this.path, this.extname);
753
+ }
754
+ set stem(val) {
755
+ const dir = import_node_path6.default.dirname(this.path);
756
+ this.path = import_node_path6.default.join(dir, `${val}${this.extname}`);
757
+ }
758
+ toString(encoding = "utf8") {
759
+ return this.contents.toString(encoding);
760
+ }
761
+ clone() {
762
+ const cloned = new _VirtualFile({
763
+ cwd: this.cwd,
764
+ base: this.base,
765
+ path: this.path,
766
+ contents: Buffer.from(this.contents)
767
+ });
768
+ cloned.revPathOriginal = this.revPathOriginal;
769
+ return cloned;
770
+ }
771
+ };
772
+
773
+ // src/pipeline/pipeline.ts
774
+ var Pipeline = class _Pipeline {
775
+ cwd;
776
+ base;
777
+ allowEmpty;
778
+ files = [];
779
+ transforms = [];
780
+ constructor(options = {}) {
781
+ this.cwd = options.cwd || process.cwd();
782
+ this.base = options.base;
783
+ this.allowEmpty = options.allowEmpty ?? true;
784
+ }
785
+ static from(patterns, options = {}) {
786
+ const pipeline = new _Pipeline(options);
787
+ return pipeline.src(patterns);
788
+ }
789
+ src(patterns, options = {}) {
790
+ if (options.cwd) this.cwd = options.cwd;
791
+ if (options.base) this.base = options.base;
792
+ if (options.allowEmpty !== void 0) this.allowEmpty = options.allowEmpty;
793
+ this.transforms.push(async () => {
794
+ const matched = await (0, import_fast_glob2.default)(patterns, {
795
+ cwd: this.cwd,
796
+ absolute: true,
797
+ dot: true,
798
+ onlyFiles: true
799
+ });
800
+ if (!matched.length && !this.allowEmpty) {
801
+ throw new Error(`File not found with pattern: ${patterns}`);
802
+ }
803
+ let effectiveBase = this.base;
804
+ if (!effectiveBase) {
805
+ const patternArr = Array.isArray(patterns) ? patterns : [patterns];
806
+ const firstPos = patternArr.find((p) => !p.startsWith("!"));
807
+ if (firstPos) {
808
+ const globIdx = firstPos.indexOf("*");
809
+ if (globIdx !== -1) {
810
+ effectiveBase = import_node_path7.default.resolve(this.cwd, firstPos.slice(0, globIdx));
811
+ } else {
812
+ effectiveBase = import_node_path7.default.resolve(this.cwd, import_node_path7.default.dirname(firstPos));
813
+ }
814
+ } else {
815
+ effectiveBase = this.cwd;
816
+ }
817
+ }
818
+ this.files = await Promise.all(
819
+ matched.map(async (filePath) => {
820
+ const buffer = await import_promises2.default.readFile(filePath);
821
+ return new VirtualFile({
822
+ cwd: this.cwd,
823
+ base: effectiveBase,
824
+ path: filePath,
825
+ contents: buffer
826
+ });
827
+ })
828
+ );
829
+ });
830
+ return this;
831
+ }
832
+ pipe(transform) {
833
+ this.transforms.push(transform);
834
+ return this;
835
+ }
836
+ async process() {
837
+ let isSrcLoaded = false;
838
+ for (const transform of this.transforms) {
839
+ if (!isSrcLoaded) {
840
+ await transform(null);
841
+ isSrcLoaded = true;
842
+ } else {
843
+ if (this.files.length === 0) break;
844
+ const nextFiles = [];
845
+ for (const file2 of this.files) {
846
+ const result = await transform(file2);
847
+ if (result === void 0 || result === file2) {
848
+ nextFiles.push(file2);
849
+ } else if (Array.isArray(result)) {
850
+ nextFiles.push(...result);
851
+ } else if (result !== null) {
852
+ nextFiles.push(result);
853
+ }
854
+ }
855
+ this.files = nextFiles;
856
+ }
857
+ }
858
+ return this.files;
859
+ }
860
+ async dest(outDir) {
861
+ const files = await this.process();
862
+ const writtenPaths = [];
863
+ const absOutDir = import_node_path7.default.isAbsolute(outDir) ? outDir : import_node_path7.default.resolve(this.cwd, outDir);
864
+ for (const file2 of files) {
865
+ const targetPath = import_node_path7.default.resolve(absOutDir, file2.relative);
866
+ await file.writeFile(targetPath, file2.contents);
867
+ writtenPaths.push(targetPath);
868
+ }
869
+ return writtenPaths;
870
+ }
871
+ };
872
+
873
+ // src/pipeline/transforms/sass.ts
874
+ var sass = __toESM(require("sass"), 1);
875
+ var import_node_path8 = __toESM(require("path"), 1);
876
+ var import_node_fs2 = __toESM(require("fs"), 1);
877
+ function resolveFile(baseDir, url) {
878
+ const possiblePaths = [
879
+ import_node_path8.default.resolve(baseDir, url),
880
+ import_node_path8.default.resolve(baseDir, `${url}.scss`),
881
+ import_node_path8.default.resolve(baseDir, `${url}.sass`),
882
+ import_node_path8.default.resolve(baseDir, `${url}.css`),
883
+ import_node_path8.default.resolve(baseDir, import_node_path8.default.dirname(url), `_${import_node_path8.default.basename(url)}.scss`),
884
+ import_node_path8.default.resolve(baseDir, import_node_path8.default.dirname(url), `_${import_node_path8.default.basename(url)}.sass`),
885
+ import_node_path8.default.resolve(baseDir, url, "_index.scss"),
886
+ import_node_path8.default.resolve(baseDir, url, "_index.sass"),
887
+ import_node_path8.default.resolve(baseDir, url, "index.scss"),
888
+ import_node_path8.default.resolve(baseDir, url, "index.sass")
889
+ ];
890
+ for (const p of possiblePaths) {
891
+ try {
892
+ if (import_node_fs2.default.existsSync(p) && import_node_fs2.default.statSync(p).isFile()) {
893
+ return p;
894
+ }
895
+ } catch {
896
+ }
897
+ }
898
+ return null;
899
+ }
900
+ function transformSass(options = {}) {
901
+ return async (file2) => {
902
+ if (!/\.(scss|sass)$/i.test(file2.extname)) return file2;
903
+ if (import_node_path8.default.basename(file2.path).startsWith("_")) return null;
904
+ try {
905
+ const searchDirs = [
906
+ import_node_path8.default.dirname(file2.path),
907
+ import_node_path8.default.resolve(file2.cwd, "node_modules"),
908
+ import_node_path8.default.resolve(process.cwd(), "node_modules"),
909
+ import_node_path8.default.resolve(process.cwd(), "..", "node_modules"),
910
+ ...options.includePaths || []
911
+ ];
912
+ const customImporter = {
913
+ findFileUrl(url) {
914
+ let cleanUrl = url;
915
+ if (cleanUrl.startsWith("~")) {
916
+ cleanUrl = cleanUrl.slice(1);
917
+ }
918
+ if (options.alias) {
919
+ for (const [aliasKey, aliasTarget] of Object.entries(options.alias)) {
920
+ if (cleanUrl === aliasKey) {
921
+ const resolved = resolveFile(import_node_path8.default.dirname(aliasTarget), import_node_path8.default.basename(aliasTarget));
922
+ if (resolved) return new URL(`file://${resolved}`);
923
+ } else if (cleanUrl.startsWith(`${aliasKey}/`)) {
924
+ const subPath = cleanUrl.slice(aliasKey.length + 1);
925
+ const resolved = resolveFile(aliasTarget, subPath);
926
+ if (resolved) return new URL(`file://${resolved}`);
927
+ }
928
+ }
929
+ }
930
+ for (const dir of searchDirs) {
931
+ const resolved = resolveFile(dir, cleanUrl);
932
+ if (resolved) {
933
+ return new URL(`file://${resolved}`);
934
+ }
935
+ }
936
+ return null;
937
+ }
938
+ };
939
+ const result = await sass.compileStringAsync(file2.toString(), {
940
+ url: new URL(`file://${file2.path}`),
941
+ syntax: file2.extname === ".sass" ? "indented" : "scss",
942
+ loadPaths: searchDirs,
943
+ importers: [customImporter, new sass.NodePackageImporter()],
944
+ style: options.style || "expanded",
945
+ sourceMap: options.sourceMap || false
946
+ });
947
+ file2.contents = Buffer.from(result.css);
948
+ file2.extname = ".css";
949
+ return file2;
950
+ } catch (err) {
951
+ logger.error("sass", `Error compiling ${file2.path}: ${err.message}`);
952
+ throw err;
953
+ }
954
+ };
955
+ }
956
+
957
+ // src/pipeline/transforms/less.ts
958
+ var import_less = __toESM(require("less"), 1);
959
+ var import_node_path9 = __toESM(require("path"), 1);
960
+ var AliasFileManager = class extends import_less.default.FileManager {
961
+ alias;
962
+ constructor(alias = {}) {
963
+ super();
964
+ this.alias = alias;
965
+ }
966
+ supports(filename) {
967
+ const clean = filename.startsWith("~") ? filename.slice(1) : filename;
968
+ return Object.keys(this.alias).some((k) => clean === k || clean.startsWith(`${k}/`));
969
+ }
970
+ loadFile(filename, currentDirectory, options, environment) {
971
+ const clean = filename.startsWith("~") ? filename.slice(1) : filename;
972
+ for (const [k, v] of Object.entries(this.alias)) {
973
+ if (clean === k) {
974
+ return super.loadFile(v, currentDirectory, options, environment);
975
+ } else if (clean.startsWith(`${k}/`)) {
976
+ const sub = clean.slice(k.length + 1);
977
+ return super.loadFile(import_node_path9.default.join(v, sub), currentDirectory, options, environment);
978
+ }
979
+ }
980
+ return super.loadFile(filename, currentDirectory, options, environment);
981
+ }
982
+ };
983
+ function transformLess(options = {}) {
984
+ return async (file2) => {
985
+ if (!/\.less$/i.test(file2.extname)) return file2;
986
+ if (import_node_path9.default.basename(file2.path).startsWith("_")) return null;
987
+ try {
988
+ const paths = [
989
+ import_node_path9.default.dirname(file2.path),
990
+ import_node_path9.default.resolve(file2.cwd, "node_modules"),
991
+ ...options.paths || []
992
+ ];
993
+ const plugins = [...options.plugins || []];
994
+ if (options.alias && Object.keys(options.alias).length > 0) {
995
+ plugins.push({
996
+ install: (lessInstance, pluginManager) => {
997
+ pluginManager.addFileManager(new AliasFileManager(options.alias));
998
+ }
999
+ });
1000
+ }
1001
+ const result = await import_less.default.render(file2.toString(), {
1002
+ filename: file2.path,
1003
+ paths,
1004
+ ...options,
1005
+ plugins
1006
+ });
1007
+ file2.contents = Buffer.from(result.css);
1008
+ file2.extname = ".css";
1009
+ return file2;
1010
+ } catch (err) {
1011
+ logger.error("less", `Error compiling ${file2.path}: ${err.message}`);
1012
+ throw err;
1013
+ }
1014
+ };
1015
+ }
1016
+
1017
+ // src/pipeline/transforms/postcss.ts
1018
+ var import_postcss = __toESM(require("postcss"), 1);
1019
+ var import_autoprefixer = __toESM(require("autoprefixer"), 1);
1020
+ var import_postcss_preset_env = __toESM(require("postcss-preset-env"), 1);
1021
+ var import_cssnano = __toESM(require("cssnano"), 1);
1022
+ function transformPostcss(options = {}) {
1023
+ const plugins = [
1024
+ ...options.plugins || [],
1025
+ (0, import_autoprefixer.default)(),
1026
+ (0, import_postcss_preset_env.default)()
1027
+ ];
1028
+ if (options.minify) {
1029
+ plugins.push((0, import_cssnano.default)({ preset: "default" }));
1030
+ }
1031
+ const processor = (0, import_postcss.default)(plugins);
1032
+ return async (file2) => {
1033
+ if (!/\.css$/i.test(file2.extname)) return file2;
1034
+ try {
1035
+ const result = await processor.process(file2.toString(), {
1036
+ from: file2.path,
1037
+ to: file2.path
1038
+ });
1039
+ file2.contents = Buffer.from(result.css);
1040
+ return file2;
1041
+ } catch (err) {
1042
+ logger.error("postcss", `Error processing ${file2.path}: ${err.message}`);
1043
+ throw err;
1044
+ }
1045
+ };
1046
+ }
1047
+
1048
+ // src/tasks/style.ts
1049
+ var StyleTask = class extends BaseTask {
1050
+ constructor() {
1051
+ super({ name: "style", description: "Compile stylesheets" });
1052
+ }
1053
+ async run(config) {
1054
+ const ext = config.styles.extname;
1055
+ const srcPattern = import_node_path10.default.join(config.src.css, `**/*.${ext}`);
1056
+ const isProd = config.env.isProd;
1057
+ const pipeline = Pipeline.from([srcPattern, `!${import_node_path10.default.join(config.src.css, "**/_*.scss")}`, `!${import_node_path10.default.join(config.src.css, "**/_*.less")}`], {
1058
+ cwd: config.workspace,
1059
+ base: config.src.css
1060
+ });
1061
+ const styleAlias = {
1062
+ ...config.alias,
1063
+ ...config.styles.alias
1064
+ };
1065
+ if (ext === "scss" || ext === "sass") {
1066
+ pipeline.pipe(
1067
+ transformSass({
1068
+ includePaths: [config.src.css, ...config.styles.atImportPaths],
1069
+ alias: styleAlias,
1070
+ ...config.styles.sassOptions
1071
+ })
1072
+ );
1073
+ } else if (ext === "less") {
1074
+ pipeline.pipe(
1075
+ transformLess({
1076
+ paths: [config.src.css, ...config.styles.atImportPaths],
1077
+ alias: styleAlias,
1078
+ ...config.styles.lessOptions
1079
+ })
1080
+ );
1081
+ }
1082
+ pipeline.pipe(
1083
+ transformPostcss({
1084
+ plugins: config.styles.postcssPlugins,
1085
+ minify: isProd || config.styles.minify,
1086
+ ...config.styles.postcssLoaderOptions
1087
+ })
1088
+ );
1089
+ await pipeline.dest(config.dest.css);
1090
+ }
1091
+ };
1092
+
1093
+ // src/bundler/webpack.ts
1094
+ var import_webpack = __toESM(require("webpack"), 1);
1095
+ var import_node_path11 = __toESM(require("path"), 1);
1096
+ async function runWebpack(config, customOptions = {}) {
1097
+ const isProd = config.env.isProd;
1098
+ let entry = customOptions.entry || config.scripts.entry;
1099
+ if (!entry) {
1100
+ entry = import_node_path11.default.join(config.src.js, "main.js");
1101
+ }
1102
+ const defaultWebpackConfig = {
1103
+ mode: isProd ? "production" : "development",
1104
+ context: config.workspace,
1105
+ entry,
1106
+ output: {
1107
+ path: config.dest.js,
1108
+ filename: isProd && config.assets.cache ? "[name].[contenthash:8].js" : "[name].js",
1109
+ chunkFilename: isProd && config.assets.cache ? "chunk/[name].[contenthash:8].js" : "chunk/[name].js",
1110
+ publicPath: config.assets.virtualDir ? `/${config.assets.virtualDir}/` : "/"
1111
+ },
1112
+ resolve: {
1113
+ extensions: [".wasm", ".mjs", ".js", ".jsx", ".ts", ".tsx", ".json"],
1114
+ alias: {
1115
+ ...config.alias,
1116
+ ...config.scripts.alias
1117
+ }
1118
+ },
1119
+ module: {
1120
+ rules: [
1121
+ {
1122
+ test: /\.(png|jpe?g|gif|svg|webp)$/i,
1123
+ type: "asset/resource",
1124
+ generator: {
1125
+ filename: "img/[name].[hash:8][ext]"
1126
+ }
1127
+ },
1128
+ {
1129
+ test: /\.(woff2?|eot|ttf|otf)$/i,
1130
+ type: "asset/resource",
1131
+ generator: {
1132
+ filename: "font/[name].[hash:8][ext]"
1133
+ }
1134
+ }
1135
+ ]
1136
+ },
1137
+ optimization: {
1138
+ minimize: isProd || config.scripts.minify
1139
+ },
1140
+ devtool: isProd ? false : "eval-cheap-module-source-map"
1141
+ };
1142
+ const webpackConfig = Object.assign(
1143
+ {},
1144
+ defaultWebpackConfig,
1145
+ config.scripts.webpackOptions,
1146
+ customOptions
1147
+ );
1148
+ return new Promise((resolve, reject) => {
1149
+ const compiler = (0, import_webpack.default)(webpackConfig);
1150
+ compiler.run((err, stats) => {
1151
+ if (err) {
1152
+ logger.error("webpack", err.stack || err);
1153
+ return reject(err);
1154
+ }
1155
+ if (stats?.hasErrors()) {
1156
+ const info = stats.toJson();
1157
+ logger.error("webpack", info.errors?.map((e) => e.message).join("\n"));
1158
+ return reject(new Error("Webpack compilation errors"));
1159
+ }
1160
+ resolve(stats);
1161
+ });
1162
+ });
1163
+ }
1164
+
1165
+ // src/bundler/rollup.ts
1166
+ var import_rollup = require("rollup");
1167
+ var import_node_path12 = __toESM(require("path"), 1);
1168
+ async function runRollup(config, customInputOptions = {}, customOutputOptions = {}) {
1169
+ const isProd = config.env.isProd;
1170
+ let input = customInputOptions.input || config.scripts.entry;
1171
+ if (!input) {
1172
+ input = import_node_path12.default.join(config.src.js, "main.js");
1173
+ }
1174
+ const inputOptions = {
1175
+ input,
1176
+ ...config.scripts.rollupOptions,
1177
+ ...customInputOptions
1178
+ };
1179
+ const outputOptions = {
1180
+ dir: config.dest.js,
1181
+ format: "es",
1182
+ sourcemap: !isProd,
1183
+ ...customOutputOptions
1184
+ };
1185
+ try {
1186
+ const bundle = await (0, import_rollup.rollup)(inputOptions);
1187
+ await bundle.write(outputOptions);
1188
+ await bundle.close();
1189
+ } catch (err) {
1190
+ logger.error("rollup", err.message || err);
1191
+ throw err;
1192
+ }
1193
+ }
1194
+
1195
+ // src/bundler/esbuild.ts
1196
+ var esbuild = __toESM(require("esbuild"), 1);
1197
+ var import_node_path13 = __toESM(require("path"), 1);
1198
+ async function runEsbuild(config, customOptions = {}) {
1199
+ const isProd = config.env.isProd;
1200
+ let entryPoints = customOptions.entryPoints || config.scripts.entry;
1201
+ if (!entryPoints) {
1202
+ entryPoints = [import_node_path13.default.join(config.src.js, "main.js")];
1203
+ }
1204
+ const defaultOptions = {
1205
+ entryPoints: Array.isArray(entryPoints) ? entryPoints : typeof entryPoints === "string" ? [entryPoints] : entryPoints,
1206
+ absWorkingDir: config.workspace,
1207
+ bundle: true,
1208
+ outdir: config.dest.js,
1209
+ alias: {
1210
+ ...config.alias,
1211
+ ...config.scripts.alias
1212
+ },
1213
+ minify: isProd || config.scripts.minify,
1214
+ sourcemap: !isProd,
1215
+ target: config.scripts.target && config.scripts.target !== "web" ? config.scripts.target : "es2020",
1216
+ format: "esm",
1217
+ ...config.scripts.esbuildOptions,
1218
+ ...customOptions
1219
+ };
1220
+ try {
1221
+ return await esbuild.build(defaultOptions);
1222
+ } catch (err) {
1223
+ logger.error("esbuild", err.message || err);
1224
+ throw err;
1225
+ }
1226
+ }
1227
+
1228
+ // src/tasks/script.ts
1229
+ var ScriptTask = class extends BaseTask {
1230
+ constructor() {
1231
+ super({ name: "script", description: "Bundle JavaScript/TypeScript" });
1232
+ }
1233
+ async run(config) {
1234
+ const bundler = config.scripts.bundler;
1235
+ switch (bundler) {
1236
+ case "rollup" /* rollup */:
1237
+ await runRollup(config);
1238
+ break;
1239
+ case "esbuild" /* esbuild */:
1240
+ await runEsbuild(config);
1241
+ break;
1242
+ case "webpack" /* webpack */:
1243
+ default:
1244
+ await runWebpack(config);
1245
+ break;
1246
+ }
1247
+ }
1248
+ };
1249
+
1250
+ // src/tasks/html.ts
1251
+ var import_node_path14 = __toESM(require("path"), 1);
1252
+
1253
+ // src/pipeline/transforms/htmlmin.ts
1254
+ var import_html_minifier_terser = require("html-minifier-terser");
1255
+ function transformHtmlmin(options = {}) {
1256
+ return async (file2) => {
1257
+ if (!/\.html$/i.test(file2.extname)) return file2;
1258
+ try {
1259
+ const minified = await (0, import_html_minifier_terser.minify)(file2.toString(), options);
1260
+ file2.contents = Buffer.from(minified);
1261
+ return file2;
1262
+ } catch (err) {
1263
+ logger.error("htmlmin", `Error minifying ${file2.path}: ${err.message}`);
1264
+ throw err;
1265
+ }
1266
+ };
1267
+ }
1268
+
1269
+ // src/pipeline/transforms/replace.ts
1270
+ function transformReplace(options, replacement) {
1271
+ let rules = [];
1272
+ if (Array.isArray(options)) {
1273
+ rules = options;
1274
+ } else if (typeof options === "object" && "substr" in options) {
1275
+ rules = [options];
1276
+ } else if (typeof options === "string" || options instanceof RegExp) {
1277
+ rules = [{ substr: options, replacement: replacement || "" }];
1278
+ }
1279
+ return async (file2) => {
1280
+ let content = file2.toString();
1281
+ for (const rule of rules) {
1282
+ if (typeof rule.replacement === "function") {
1283
+ content = content.replace(rule.substr, rule.replacement);
1284
+ } else {
1285
+ content = content.replace(rule.substr, rule.replacement);
1286
+ }
1287
+ }
1288
+ file2.contents = Buffer.from(content);
1289
+ return file2;
1290
+ };
1291
+ }
1292
+
1293
+ // src/tasks/html.ts
1294
+ var LIVE_RELOAD_SCRIPT = `
1295
+ <!-- BalmJS Live Reload -->
1296
+ <script>
1297
+ (() => {
1298
+ const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
1299
+ const ws = new WebSocket(\`\${protocol}//\${location.host}/__balm_ws\`);
1300
+ ws.onmessage = (e) => {
1301
+ try {
1302
+ const msg = JSON.parse(e.data);
1303
+ if (msg.type === 'reload') {
1304
+ console.log('[BalmJS] Reloading page...');
1305
+ location.reload();
1306
+ } else if (msg.type === 'reload-css') {
1307
+ console.log('[BalmJS] Reloading CSS...');
1308
+ const links = document.querySelectorAll('link[rel="stylesheet"]');
1309
+ for (const link of links) {
1310
+ const url = new URL(link.href);
1311
+ url.searchParams.set('_balm_t', Date.now().toString());
1312
+ link.href = url.href;
1313
+ }
1314
+ }
1315
+ } catch {}
1316
+ };
1317
+ ws.onclose = () => {
1318
+ setTimeout(() => location.reload(), 2000);
1319
+ };
1320
+ })();
1321
+ </script>
1322
+ `;
1323
+ var HtmlTask = class extends BaseTask {
1324
+ constructor() {
1325
+ super({ name: "html", description: "Process HTML templates" });
1326
+ }
1327
+ async run(config) {
1328
+ const templateDir = config.scripts.injectHtml ? config.src.base : config.src.html;
1329
+ const pattern = import_node_path14.default.join(templateDir, "*.html");
1330
+ const pipeline = Pipeline.from(pattern, {
1331
+ cwd: config.workspace,
1332
+ base: templateDir
1333
+ });
1334
+ const publicUrlReplacement = config.assets.virtualDir ? `/${config.assets.virtualDir}` : "";
1335
+ pipeline.pipe(transformReplace(new RegExp(PUBLIC_URL, "g"), publicUrlReplacement));
1336
+ if (config.env.isProd) {
1337
+ pipeline.pipe(transformHtmlmin(config.html.options));
1338
+ } else {
1339
+ pipeline.pipe(async (file2) => {
1340
+ if (/\.html$/i.test(file2.extname)) {
1341
+ let content = file2.toString();
1342
+ if (content.includes("</body>")) {
1343
+ content = content.replace("</body>", `${LIVE_RELOAD_SCRIPT}
1344
+ </body>`);
1345
+ } else {
1346
+ content += `
1347
+ ${LIVE_RELOAD_SCRIPT}`;
1348
+ }
1349
+ file2.contents = Buffer.from(content);
1350
+ }
1351
+ return file2;
1352
+ });
1353
+ }
1354
+ await pipeline.dest(config.dest.html);
1355
+ }
1356
+ };
1357
+
1358
+ // src/tasks/copy.ts
1359
+ var import_node_path16 = __toESM(require("path"), 1);
1360
+
1361
+ // src/pipeline/transforms/rename.ts
1362
+ var import_node_path15 = __toESM(require("path"), 1);
1363
+ function transformRename(options = {}) {
1364
+ return async (file2) => {
1365
+ if (typeof options === "string") {
1366
+ file2.path = import_node_path15.default.resolve(import_node_path15.default.dirname(file2.path), options);
1367
+ return file2;
1368
+ }
1369
+ if (typeof options === "function") {
1370
+ const parsed = {
1371
+ dirname: import_node_path15.default.dirname(file2.path),
1372
+ basename: file2.stem,
1373
+ extname: file2.extname
1374
+ };
1375
+ const result = options(parsed);
1376
+ if (result) {
1377
+ if (result.dirname) file2.path = import_node_path15.default.join(result.dirname, import_node_path15.default.basename(file2.path));
1378
+ if (result.basename) file2.stem = result.basename;
1379
+ if (result.extname) file2.extname = result.extname;
1380
+ }
1381
+ return file2;
1382
+ }
1383
+ const { dirname, prefix = "", basename, suffix = "", extname } = options;
1384
+ const currentDir = dirname ? import_node_path15.default.resolve(file2.cwd, dirname) : import_node_path15.default.dirname(file2.path);
1385
+ const base = basename !== void 0 ? basename : file2.stem;
1386
+ const ext = extname !== void 0 ? extname : file2.extname;
1387
+ file2.path = import_node_path15.default.join(currentDir, `${prefix}${base}${suffix}${ext.startsWith(".") ? ext : `.${ext}`}`);
1388
+ return file2;
1389
+ };
1390
+ }
1391
+
1392
+ // src/tasks/copy.ts
1393
+ var CopyTask = class extends BaseTask {
1394
+ options;
1395
+ constructor(options) {
1396
+ super({ name: "copy", description: "Copy files to destination" });
1397
+ this.options = options;
1398
+ }
1399
+ async run(config) {
1400
+ const pipeline = Pipeline.from(this.options.input, {
1401
+ cwd: config.workspace
1402
+ });
1403
+ if (this.options.rename) {
1404
+ pipeline.pipe(transformRename(this.options.rename));
1405
+ }
1406
+ const outDir = import_node_path16.default.isAbsolute(this.options.output) ? this.options.output : import_node_path16.default.join(config.workspace, this.options.output);
1407
+ await pipeline.dest(outDir);
1408
+ }
1409
+ };
1410
+
1411
+ // src/tasks/remove.ts
1412
+ var import_node_path17 = __toESM(require("path"), 1);
1413
+ var RemoveTask = class extends BaseTask {
1414
+ target;
1415
+ constructor(target) {
1416
+ super({ name: "remove", description: "Remove files and directories" });
1417
+ this.target = target;
1418
+ }
1419
+ async run(config) {
1420
+ const targets = Array.isArray(this.target) ? this.target : [this.target];
1421
+ const resolvedTargets = targets.map(
1422
+ (t) => import_node_path17.default.isAbsolute(t) ? t : import_node_path17.default.join(config.workspace, t)
1423
+ );
1424
+ const deleted = await file.remove(resolvedTargets);
1425
+ logger.warn("remove", `Removed: ${deleted.join(", ")}`);
1426
+ }
1427
+ };
1428
+
1429
+ // src/tasks/replace.ts
1430
+ var import_node_path18 = __toESM(require("path"), 1);
1431
+ var ReplaceTask = class extends BaseTask {
1432
+ taskOptions;
1433
+ constructor(taskOptions) {
1434
+ super({ name: "replace", description: "Replace content in files" });
1435
+ this.taskOptions = taskOptions;
1436
+ }
1437
+ async run(config) {
1438
+ const pipeline = Pipeline.from(this.taskOptions.input, {
1439
+ cwd: config.workspace
1440
+ });
1441
+ pipeline.pipe(transformReplace(this.taskOptions.options));
1442
+ const outDir = import_node_path18.default.isAbsolute(this.taskOptions.output) ? this.taskOptions.output : import_node_path18.default.join(config.workspace, this.taskOptions.output);
1443
+ await pipeline.dest(outDir);
1444
+ }
1445
+ };
1446
+
1447
+ // src/tasks/cache.ts
1448
+ var import_fast_glob3 = __toESM(require("fast-glob"), 1);
1449
+ var import_promises3 = __toESM(require("fs/promises"), 1);
1450
+
1451
+ // src/pipeline/transforms/cache.ts
1452
+ var import_node_path19 = __toESM(require("path"), 1);
1453
+ var import_picomatch = __toESM(require("picomatch"), 1);
1454
+ function matchesAny(filePath, rules) {
1455
+ if (!rules || !rules.length) return false;
1456
+ for (const rule of rules) {
1457
+ if (typeof rule === "string") {
1458
+ if (filePath.endsWith(rule) || import_picomatch.default.isMatch(filePath, rule)) {
1459
+ return true;
1460
+ }
1461
+ } else if (rule instanceof RegExp) {
1462
+ if (rule.test(filePath)) return true;
1463
+ }
1464
+ }
1465
+ return false;
1466
+ }
1467
+ var AssetRevisioner = class {
1468
+ options;
1469
+ manifest = {};
1470
+ constructor(options = {}) {
1471
+ this.options = {
1472
+ fileNameManifest: "rev-manifest.json",
1473
+ dontRenameFile: [".html"],
1474
+ dontUpdateReference: [],
1475
+ hashLength: 8,
1476
+ ...options
1477
+ };
1478
+ }
1479
+ process(files) {
1480
+ const hashLength = this.options.hashLength || 8;
1481
+ const outputFiles = [];
1482
+ for (const file2 of files) {
1483
+ const origRelative = file2.relative;
1484
+ file2.revPathOriginal = file2.path;
1485
+ const shouldRename = !matchesAny(file2.path, this.options.dontRenameFile) && !matchesAny(file2.relative, this.options.dontRenameFile);
1486
+ if (shouldRename) {
1487
+ const fileHash = file.hash(file2.contents, hashLength);
1488
+ const dir = import_node_path19.default.dirname(file2.path);
1489
+ const newFilename = `${file2.stem}.${fileHash}${file2.extname}`;
1490
+ file2.path = import_node_path19.default.join(dir, newFilename);
1491
+ }
1492
+ this.manifest[origRelative] = file2.relative;
1493
+ outputFiles.push(file2);
1494
+ }
1495
+ for (const file2 of outputFiles) {
1496
+ const shouldUpdate = !matchesAny(file2.path, this.options.dontUpdateReference) && !matchesAny(file2.relative, this.options.dontUpdateReference);
1497
+ if (shouldUpdate && /\.(html|css|js)$/i.test(file2.extname)) {
1498
+ let content = file2.toString();
1499
+ for (const [orig, reved] of Object.entries(this.manifest)) {
1500
+ if (orig !== reved) {
1501
+ const origBase = import_node_path19.default.basename(orig);
1502
+ const revedBase = import_node_path19.default.basename(reved);
1503
+ content = content.replaceAll(origBase, revedBase);
1504
+ }
1505
+ }
1506
+ file2.contents = Buffer.from(content);
1507
+ }
1508
+ }
1509
+ const manifestName = this.options.fileNameManifest || "rev-manifest.json";
1510
+ const firstBase = files[0]?.base || process.cwd();
1511
+ const manifestFile = new VirtualFile({
1512
+ cwd: files[0]?.cwd || process.cwd(),
1513
+ base: firstBase,
1514
+ path: import_node_path19.default.join(firstBase, manifestName),
1515
+ contents: JSON.stringify(this.manifest, null, 2)
1516
+ });
1517
+ outputFiles.push(manifestFile);
1518
+ return outputFiles;
1519
+ }
1520
+ };
1521
+
1522
+ // src/tasks/cache.ts
1523
+ var CacheTask = class extends BaseTask {
1524
+ constructor() {
1525
+ super({ name: "cache", description: "Revision assets and generate manifest" });
1526
+ }
1527
+ async run(config) {
1528
+ const destDir = config.dest.base;
1529
+ const filesToRev = await (0, import_fast_glob3.default)(["**/*"], {
1530
+ cwd: destDir,
1531
+ absolute: true,
1532
+ onlyFiles: true
1533
+ });
1534
+ if (!filesToRev.length) {
1535
+ logger.warn("cache", "No files found to cache");
1536
+ return;
1537
+ }
1538
+ const virtualFiles = await Promise.all(
1539
+ filesToRev.map(async (filePath) => {
1540
+ const buffer = await import_promises3.default.readFile(filePath);
1541
+ return new VirtualFile({
1542
+ cwd: config.workspace,
1543
+ base: destDir,
1544
+ path: filePath,
1545
+ contents: buffer
1546
+ });
1547
+ })
1548
+ );
1549
+ const revisioner = new AssetRevisioner(config.assets.options);
1550
+ const resultFiles = revisioner.process(virtualFiles);
1551
+ for (const vFile of resultFiles) {
1552
+ if (vFile.revPathOriginal && vFile.revPathOriginal !== vFile.path) {
1553
+ await file.remove(vFile.revPathOriginal);
1554
+ }
1555
+ }
1556
+ for (const vFile of resultFiles) {
1557
+ await file.writeFile(vFile.path, vFile.contents);
1558
+ }
1559
+ logger.success("cache", "Asset revisioning and rev-manifest.json completed");
1560
+ }
1561
+ };
1562
+
1563
+ // src/tasks/publish.ts
1564
+ var import_node_path20 = __toESM(require("path"), 1);
1565
+ var PublishTask = class extends BaseTask {
1566
+ options;
1567
+ constructor(options = {}) {
1568
+ super({ name: "publish", description: "Publish assets or templates" });
1569
+ this.options = options;
1570
+ }
1571
+ async run(config) {
1572
+ if (!config.env.isProd) {
1573
+ logger.warn("publish", "`mix.publish()` is only supported in production mode");
1574
+ return;
1575
+ }
1576
+ const { input, output, renameOptions } = this.options;
1577
+ if (Array.isArray(input)) {
1578
+ for (const item of input) {
1579
+ await this.publishItem(config, item.input, item.output, item.renameOptions);
1580
+ }
1581
+ } else if (typeof input === "string" && output) {
1582
+ await this.publishItem(config, input, output, renameOptions);
1583
+ } else {
1584
+ const srcDir = config.dest.base;
1585
+ const targetDir = config.assets.static || import_node_path20.default.join(config.assets.root, config.assets.mainDir);
1586
+ const pipeline = Pipeline.from(["**/*"], {
1587
+ cwd: srcDir,
1588
+ base: srcDir
1589
+ });
1590
+ await pipeline.dest(import_node_path20.default.resolve(config.workspace, targetDir));
1591
+ }
1592
+ }
1593
+ async publishItem(config, input, output, rename) {
1594
+ const srcPath = import_node_path20.default.isAbsolute(input) ? input : import_node_path20.default.join(config.dest.base, input);
1595
+ const destDir = import_node_path20.default.isAbsolute(output) ? output : import_node_path20.default.join(config.workspace, config.assets.root, output);
1596
+ const pipeline = Pipeline.from(srcPath, {
1597
+ cwd: config.dest.base
1598
+ });
1599
+ if (rename) {
1600
+ pipeline.pipe(transformRename(rename));
1601
+ }
1602
+ await pipeline.dest(destDir);
1603
+ }
1604
+ };
1605
+
1606
+ // src/tasks/pwa.ts
1607
+ var import_node_path21 = __toESM(require("path"), 1);
1608
+ var import_workbox_build = require("workbox-build");
1609
+ var PwaTask = class extends BaseTask {
1610
+ options;
1611
+ constructor(options = {}) {
1612
+ super({ name: "pwa", description: "Generate Progressive Web App Service Worker" });
1613
+ this.options = options;
1614
+ }
1615
+ async run(config) {
1616
+ const mode = this.options.mode || config.pwa.mode || "generateSW";
1617
+ const globDirectory = config.dest.base;
1618
+ const swDest = import_node_path21.default.join(globDirectory, config.pwa.swDestFilename);
1619
+ const swSrc = import_node_path21.default.join(config.src.base, config.pwa.swSrcFilename);
1620
+ const mergedOptions = {
1621
+ globDirectory,
1622
+ swDest,
1623
+ ...config.pwa.options,
1624
+ ...this.options.options
1625
+ };
1626
+ if (mode === "injectManifest") {
1627
+ mergedOptions.swSrc = mergedOptions.swSrc || swSrc;
1628
+ }
1629
+ try {
1630
+ if (mode === "generateSW") {
1631
+ const { count, size } = await (0, import_workbox_build.generateSW)(mergedOptions);
1632
+ logger.info("pwa", `Generated '${swDest}', precaching ${count} files (${size} bytes)`);
1633
+ } else {
1634
+ const { count, size } = await (0, import_workbox_build.injectManifest)(mergedOptions);
1635
+ logger.info("pwa", `Injected manifest into '${swDest}', precaching ${count} files (${size} bytes)`);
1636
+ }
1637
+ } catch (err) {
1638
+ logger.warn("pwa", `Service worker generation failed: ${err.message || err}`);
1639
+ }
1640
+ }
1641
+ };
1642
+
1643
+ // src/tasks/zip.ts
1644
+ var import_node_fs3 = __toESM(require("fs"), 1);
1645
+ var import_node_path22 = __toESM(require("path"), 1);
1646
+ var import_archiver = __toESM(require("archiver"), 1);
1647
+ var ZipTask = class extends BaseTask {
1648
+ options;
1649
+ constructor(options = {}) {
1650
+ super({ name: "zip", description: "Compress files into archive" });
1651
+ this.options = options;
1652
+ }
1653
+ async run(config) {
1654
+ const input = this.options.input || config.dest.base;
1655
+ const outputDir = this.options.output ? import_node_path22.default.isAbsolute(this.options.output) ? this.options.output : import_node_path22.default.join(config.workspace, this.options.output) : config.workspace;
1656
+ const filename = this.options.filename || "archive.zip";
1657
+ const zipPath = import_node_path22.default.join(outputDir, filename);
1658
+ await file.ensureDir(outputDir);
1659
+ return new Promise((resolve, reject) => {
1660
+ const outputStream = import_node_fs3.default.createWriteStream(zipPath);
1661
+ const archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } });
1662
+ outputStream.on("close", () => {
1663
+ logger.success("zip", `Created ${zipPath} (${archive.pointer()} total bytes)`);
1664
+ resolve();
1665
+ });
1666
+ archive.on("error", (err) => {
1667
+ logger.error("zip", err.message);
1668
+ reject(err);
1669
+ });
1670
+ archive.pipe(outputStream);
1671
+ const inputs = Array.isArray(input) ? input : [input];
1672
+ for (const item of inputs) {
1673
+ const fullPath = import_node_path22.default.isAbsolute(item) ? item : import_node_path22.default.join(config.workspace, item);
1674
+ if (import_node_fs3.default.existsSync(fullPath)) {
1675
+ const stat = import_node_fs3.default.statSync(fullPath);
1676
+ if (stat.isDirectory()) {
1677
+ archive.directory(fullPath, false);
1678
+ } else {
1679
+ archive.file(fullPath, { name: import_node_path22.default.basename(fullPath) });
1680
+ }
1681
+ }
1682
+ }
1683
+ archive.finalize();
1684
+ });
1685
+ }
1686
+ };
1687
+
1688
+ // src/tasks/ftp.ts
1689
+ var import_node_path23 = __toESM(require("path"), 1);
1690
+ var import_ssh2 = require("ssh2");
1691
+ var import_fast_glob4 = __toESM(require("fast-glob"), 1);
1692
+ var FtpTask = class extends BaseTask {
1693
+ ftpOptions;
1694
+ constructor(ftpOptions = {}) {
1695
+ super({ name: "ftp", description: "Upload files via SFTP" });
1696
+ this.ftpOptions = ftpOptions;
1697
+ }
1698
+ async run(config) {
1699
+ const options = {
1700
+ port: 22,
1701
+ remotePath: "/",
1702
+ ...config.ftp.options,
1703
+ ...this.ftpOptions.options
1704
+ };
1705
+ if (!options.host) {
1706
+ logger.error("ftp", "`host` required for SFTP");
1707
+ return;
1708
+ }
1709
+ const localFiles = this.ftpOptions.localFiles || config.dest.base;
1710
+ const files = await (0, import_fast_glob4.default)(localFiles, { cwd: config.workspace, absolute: true, onlyFiles: true });
1711
+ if (!files.length) {
1712
+ logger.warn("ftp", "No files to upload");
1713
+ return;
1714
+ }
1715
+ return new Promise((resolve, reject) => {
1716
+ const conn = new import_ssh2.Client();
1717
+ conn.on("ready", () => {
1718
+ conn.sftp((err, sftp) => {
1719
+ if (err) {
1720
+ conn.end();
1721
+ return reject(err);
1722
+ }
1723
+ let pending = files.length;
1724
+ for (const file2 of files) {
1725
+ const rel = import_node_path23.default.relative(config.workspace, file2);
1726
+ const remoteFile = import_node_path23.default.posix.join(options.remotePath, rel);
1727
+ sftp.fastPut(file2, remoteFile, (putErr) => {
1728
+ if (putErr) {
1729
+ logger.error("ftp", `Failed uploading ${file2}: ${putErr.message}`);
1730
+ } else {
1731
+ logger.info("ftp", `Uploaded ${file2} -> ${remoteFile}`);
1732
+ }
1733
+ pending--;
1734
+ if (pending === 0) {
1735
+ conn.end();
1736
+ resolve();
1737
+ }
1738
+ });
1739
+ }
1740
+ });
1741
+ });
1742
+ conn.on("error", (connErr) => {
1743
+ logger.error("ftp", connErr.message);
1744
+ reject(connErr);
1745
+ });
1746
+ conn.connect(options);
1747
+ });
1748
+ }
1749
+ };
1750
+
1751
+ // src/tasks/server.ts
1752
+ var import_node_http = __toESM(require("http"), 1);
1753
+ var import_connect = __toESM(require("connect"), 1);
1754
+ var import_serve_static = __toESM(require("serve-static"), 1);
1755
+ var import_ws = require("ws");
1756
+ var import_http_proxy_middleware = require("http-proxy-middleware");
1757
+
1758
+ // src/watcher/index.ts
1759
+ var import_node_fs4 = __toESM(require("fs"), 1);
1760
+ var import_picocolors3 = __toESM(require("picocolors"), 1);
1761
+ var FileWatcher = class {
1762
+ config;
1763
+ broadcast;
1764
+ debounceTimer = null;
1765
+ pendingFiles = /* @__PURE__ */ new Set();
1766
+ styleTask;
1767
+ scriptTask;
1768
+ htmlTask;
1769
+ watcher = null;
1770
+ constructor(config, broadcast) {
1771
+ this.config = config;
1772
+ this.broadcast = broadcast;
1773
+ this.styleTask = new StyleTask();
1774
+ this.scriptTask = new ScriptTask();
1775
+ this.htmlTask = new HtmlTask();
1776
+ }
1777
+ start() {
1778
+ const watchDir = this.config.src.base;
1779
+ if (!import_node_fs4.default.existsSync(watchDir)) return;
1780
+ logger.info("watch", `Watching for file changes in ${import_picocolors3.default.cyan(watchDir)}`);
1781
+ try {
1782
+ this.watcher = import_node_fs4.default.watch(watchDir, { recursive: true }, (eventType, filename) => {
1783
+ if (!filename) return;
1784
+ this.pendingFiles.add(filename);
1785
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
1786
+ this.debounceTimer = setTimeout(() => {
1787
+ this.handleChanges();
1788
+ }, 50);
1789
+ });
1790
+ } catch (err) {
1791
+ logger.warn("watch", `Native recursive watch failed: ${err.message}`);
1792
+ }
1793
+ }
1794
+ async handleChanges() {
1795
+ const changed = Array.from(this.pendingFiles);
1796
+ this.pendingFiles.clear();
1797
+ const hasStyle = changed.some((f) => /\.(scss|sass|less|css)$/i.test(f));
1798
+ const hasScript = changed.some((f) => /\.(js|mjs|cjs|ts|jsx|tsx)$/i.test(f));
1799
+ const hasHtml = changed.some((f) => /\.html$/i.test(f));
1800
+ try {
1801
+ if (hasStyle) {
1802
+ const start = performance.now();
1803
+ await this.styleTask.run(this.config);
1804
+ const duration = (performance.now() - start).toFixed(1);
1805
+ logger.info("watch", `Recompiled styles in ${import_picocolors3.default.bold(duration + "ms")}`);
1806
+ this.broadcast({ type: "reload-css" });
1807
+ }
1808
+ if (hasScript) {
1809
+ const start = performance.now();
1810
+ await this.scriptTask.run(this.config);
1811
+ const duration = (performance.now() - start).toFixed(1);
1812
+ logger.info("watch", `Rebundled scripts in ${import_picocolors3.default.bold(duration + "ms")}`);
1813
+ this.broadcast({ type: "reload" });
1814
+ }
1815
+ if (hasHtml) {
1816
+ const start = performance.now();
1817
+ await this.htmlTask.run(this.config);
1818
+ const duration = (performance.now() - start).toFixed(1);
1819
+ logger.info("watch", `Recompiled HTML in ${import_picocolors3.default.bold(duration + "ms")}`);
1820
+ this.broadcast({ type: "reload" });
1821
+ }
1822
+ if (!hasStyle && !hasScript && !hasHtml && changed.length > 0) {
1823
+ this.broadcast({ type: "reload" });
1824
+ }
1825
+ } catch (err) {
1826
+ logger.error("watch", `Incremental rebuild failed: ${err?.message || err}`);
1827
+ }
1828
+ }
1829
+ stop() {
1830
+ if (this.watcher) {
1831
+ this.watcher.close();
1832
+ this.watcher = null;
1833
+ }
1834
+ }
1835
+ };
1836
+
1837
+ // src/tasks/server.ts
1838
+ var import_picocolors4 = __toESM(require("picocolors"), 1);
1839
+ var ServerTask = class extends BaseTask {
1840
+ watcher = null;
1841
+ wsServer = null;
1842
+ clients = /* @__PURE__ */ new Set();
1843
+ constructor() {
1844
+ super({ name: "serve", description: "Start development server with live reload" });
1845
+ }
1846
+ broadcast(data) {
1847
+ const payload = JSON.stringify(data);
1848
+ for (const client of this.clients) {
1849
+ if (client.readyState === import_ws.WebSocket.OPEN) {
1850
+ client.send(payload);
1851
+ }
1852
+ }
1853
+ }
1854
+ async run(config) {
1855
+ if (config.env.isProd) {
1856
+ logger.warn("server", "Development server is disabled in production mode");
1857
+ return;
1858
+ }
1859
+ const app = (0, import_connect.default)();
1860
+ const port = config.server.port || 3e3;
1861
+ const host = config.server.host || "localhost";
1862
+ app.use((0, import_serve_static.default)(config.dest.base));
1863
+ app.use((0, import_serve_static.default)(config.src.base));
1864
+ if (config.server.proxy && typeof config.server.proxy === "object") {
1865
+ const proxyEntries = Array.isArray(config.server.proxy) ? config.server.proxy : [config.server.proxy];
1866
+ for (const entry of proxyEntries) {
1867
+ if (entry.context && entry.options) {
1868
+ app.use((0, import_http_proxy_middleware.createProxyMiddleware)(entry.options));
1869
+ }
1870
+ }
1871
+ }
1872
+ const server = import_node_http.default.createServer(app);
1873
+ this.wsServer = new import_ws.WebSocketServer({ server, path: "/__balm_ws" });
1874
+ this.wsServer.on("connection", (socket) => {
1875
+ this.clients.add(socket);
1876
+ socket.on("close", () => this.clients.delete(socket));
1877
+ });
1878
+ this.watcher = new FileWatcher(config, (data) => {
1879
+ this.broadcast(data);
1880
+ });
1881
+ this.watcher.start();
1882
+ return new Promise((resolve) => {
1883
+ server.listen(port, host, () => {
1884
+ console.log("");
1885
+ logger.success("server", import_picocolors4.default.bold("BalmJS Dev Server is ready!"));
1886
+ console.log(` ${import_picocolors4.default.green("\u279C")} ${import_picocolors4.default.bold("Local:")} ${import_picocolors4.default.cyan(`http://${host}:${port}/`)}`);
1887
+ console.log(` ${import_picocolors4.default.green("\u279C")} ${import_picocolors4.default.bold("Network:")} ${import_picocolors4.default.cyan(`http://127.0.0.1:${port}/`)}`);
1888
+ console.log("");
1889
+ if (config.env.isTest) {
1890
+ this.watcher?.stop();
1891
+ this.wsServer?.close();
1892
+ server.close();
1893
+ resolve();
1894
+ }
1895
+ });
1896
+ });
1897
+ }
1898
+ };
1899
+
1900
+ // src/hooks/index.ts
1901
+ var BalmHooks = class {
1902
+ dag;
1903
+ recipeIndex = 0;
1904
+ constructor(dag) {
1905
+ this.dag = dag;
1906
+ }
1907
+ addRecipeTask(fn) {
1908
+ this.recipeIndex++;
1909
+ const taskName = `recipe:${this.recipeIndex}`;
1910
+ this.dag.registerTask(new FunctionTask(taskName, fn));
1911
+ }
1912
+ copy(input, output, options = {}) {
1913
+ this.addRecipeTask(async (config) => {
1914
+ const task = new CopyTask({ input, output, rename: options.rename });
1915
+ await task.run(config);
1916
+ });
1917
+ return this;
1918
+ }
1919
+ remove(target) {
1920
+ this.addRecipeTask(async (config) => {
1921
+ const task = new RemoveTask(target);
1922
+ await task.run(config);
1923
+ });
1924
+ return this;
1925
+ }
1926
+ replace(input, output, options) {
1927
+ this.addRecipeTask(async (config) => {
1928
+ const task = new ReplaceTask({ input, output, options });
1929
+ await task.run(config);
1930
+ });
1931
+ return this;
1932
+ }
1933
+ sass(input, output, options = {}) {
1934
+ this.addRecipeTask(async (config) => {
1935
+ const pipeline = Pipeline.from(input, { cwd: config.workspace });
1936
+ pipeline.pipe(transformSass(options));
1937
+ pipeline.pipe(transformPostcss({ minify: config.env.isProd }));
1938
+ await pipeline.dest(output);
1939
+ });
1940
+ return this;
1941
+ }
1942
+ less(input, output, options = {}) {
1943
+ this.addRecipeTask(async (config) => {
1944
+ const pipeline = Pipeline.from(input, { cwd: config.workspace });
1945
+ pipeline.pipe(transformLess(options));
1946
+ pipeline.pipe(transformPostcss({ minify: config.env.isProd }));
1947
+ await pipeline.dest(output);
1948
+ });
1949
+ return this;
1950
+ }
1951
+ css(input, output, options = {}) {
1952
+ this.addRecipeTask(async (config) => {
1953
+ const pipeline = Pipeline.from(input, { cwd: config.workspace });
1954
+ pipeline.pipe(transformPostcss({ minify: config.env.isProd, ...options }));
1955
+ await pipeline.dest(output);
1956
+ });
1957
+ return this;
1958
+ }
1959
+ webpack(entry, output, customOptions = {}) {
1960
+ this.addRecipeTask(async (config) => {
1961
+ await runWebpack(config, {
1962
+ ...entry ? { entry } : {},
1963
+ ...output ? { output: { path: output } } : {},
1964
+ ...customOptions
1965
+ });
1966
+ });
1967
+ return this;
1968
+ }
1969
+ rollup(input, output, customInputOptions = {}, customOutputOptions = {}) {
1970
+ this.addRecipeTask(async (config) => {
1971
+ await runRollup(
1972
+ config,
1973
+ { ...input ? { input } : {}, ...customInputOptions },
1974
+ { ...output ? { dir: output } : {}, ...customOutputOptions }
1975
+ );
1976
+ });
1977
+ return this;
1978
+ }
1979
+ esbuild(entryPoints, outdir, customOptions = {}) {
1980
+ this.addRecipeTask(async (config) => {
1981
+ await runEsbuild(config, {
1982
+ ...entryPoints ? { entryPoints } : {},
1983
+ ...outdir ? { outdir } : {},
1984
+ ...customOptions
1985
+ });
1986
+ });
1987
+ return this;
1988
+ }
1989
+ js(input, output, options = {}) {
1990
+ logger.warn("balm api", "`mix.js` is deprecated, please use `mix.webpack`/`mix.rollup`/`mix.esbuild` instead.");
1991
+ return this.webpack(input, output, options);
1992
+ }
1993
+ publish(input, output, renameOptions) {
1994
+ this.addRecipeTask(async (config) => {
1995
+ const task = new PublishTask({ input, output, renameOptions });
1996
+ await task.run(config);
1997
+ });
1998
+ return this;
1999
+ }
2000
+ generateSW(options = {}) {
2001
+ this.addRecipeTask(async (config) => {
2002
+ const task = new PwaTask({ mode: "generateSW", options });
2003
+ await task.run(config);
2004
+ });
2005
+ return this;
2006
+ }
2007
+ injectManifest(options = {}) {
2008
+ this.addRecipeTask(async (config) => {
2009
+ const task = new PwaTask({ mode: "injectManifest", options });
2010
+ await task.run(config);
2011
+ });
2012
+ return this;
2013
+ }
2014
+ ftp(localFiles, options = {}) {
2015
+ this.addRecipeTask(async (config) => {
2016
+ const task = new FtpTask({ localFiles, options });
2017
+ await task.run(config);
2018
+ });
2019
+ return this;
2020
+ }
2021
+ zip(input, output, filename) {
2022
+ this.addRecipeTask(async (config) => {
2023
+ const task = new ZipTask({ input, output, filename });
2024
+ await task.run(config);
2025
+ });
2026
+ return this;
2027
+ }
2028
+ serve() {
2029
+ this.addRecipeTask(async (config) => {
2030
+ const task = new ServerTask();
2031
+ await task.run(config);
2032
+ });
2033
+ return this;
2034
+ }
2035
+ };
2036
+
2037
+ // src/balm.ts
2038
+ var Balm = class {
2039
+ _config;
2040
+ dag = new TaskDAG();
2041
+ beforeTask;
2042
+ afterTask;
2043
+ Bundler = BundlerType;
2044
+ constructor() {
2045
+ this._config = resolveConfig();
2046
+ }
2047
+ get config() {
2048
+ return this._config;
2049
+ }
2050
+ set config(customConfig) {
2051
+ this._config = resolveConfig(customConfig);
2052
+ if (this._config.logs?.level !== void 0) {
2053
+ logger.level = this._config.logs.level;
2054
+ }
2055
+ }
2056
+ async go(recipe) {
2057
+ const endTimer = logger.time("Build");
2058
+ const taskSequence = [];
2059
+ this.dag.registerTask(new CleanTask());
2060
+ this.dag.registerTask(new StyleTask());
2061
+ this.dag.registerTask(new ScriptTask());
2062
+ this.dag.registerTask(new HtmlTask());
2063
+ this.dag.registerTask(new CacheTask());
2064
+ this.dag.registerTask(new PwaTask());
2065
+ this.dag.registerTask(new ServerTask());
2066
+ if (typeof recipe === "function") {
2067
+ const hooks = new BalmHooks(this.dag);
2068
+ recipe(hooks);
2069
+ }
2070
+ if (this._config.useDefaults) {
2071
+ taskSequence.push("clean", "style", "script", "html");
2072
+ if (this._config.env.isProd) {
2073
+ if (this._config.assets.cache) {
2074
+ taskSequence.push("cache");
2075
+ }
2076
+ if (this._config.pwa.enabled) {
2077
+ taskSequence.push("pwa");
2078
+ }
2079
+ } else {
2080
+ taskSequence.push("serve");
2081
+ }
2082
+ }
2083
+ try {
2084
+ if (this.beforeTask) {
2085
+ await this.beforeTask();
2086
+ }
2087
+ await this.dag.runSeries(taskSequence, this._config);
2088
+ for (let i = 1; ; i++) {
2089
+ const recipeName = `recipe:${i}`;
2090
+ if (!this.dag.hasTask(recipeName)) break;
2091
+ await this.dag.executeTask(recipeName, this._config);
2092
+ }
2093
+ if (this.afterTask) {
2094
+ await this.afterTask();
2095
+ }
2096
+ endTimer();
2097
+ } catch (err) {
2098
+ logger.error("build", `Build failed: ${err?.message || err}`);
2099
+ throw err;
2100
+ }
2101
+ }
2102
+ reset() {
2103
+ this.dag.clear();
2104
+ this.beforeTask = void 0;
2105
+ this.afterTask = void 0;
2106
+ this._config = resolveConfig();
2107
+ }
2108
+ };
2109
+ var balm = new Balm();
2110
+
2111
+ // src/pipeline/transforms/terser.ts
2112
+ var import_terser = require("terser");
2113
+ function transformTerser(options = {}) {
2114
+ return async (file2) => {
2115
+ if (!/\.js$/i.test(file2.extname)) return file2;
2116
+ try {
2117
+ const result = await (0, import_terser.minify)(file2.toString(), options);
2118
+ if (result.code) {
2119
+ file2.contents = Buffer.from(result.code);
2120
+ }
2121
+ return file2;
2122
+ } catch (err) {
2123
+ logger.error("terser", `Error minifying ${file2.path}: ${err.message}`);
2124
+ throw err;
2125
+ }
2126
+ };
2127
+ }
2128
+
2129
+ // src/index.ts
2130
+ var index_default = balm;
2131
+ // Annotate the CommonJS export names for ESM import in node:
2132
+ 0 && (module.exports = {
2133
+ ASSET,
2134
+ ASSETS_TYPES,
2135
+ ASSET_EXT,
2136
+ AssetRevisioner,
2137
+ Balm,
2138
+ BalmHooks,
2139
+ BaseTask,
2140
+ BundlerType,
2141
+ CHUNK,
2142
+ CacheTask,
2143
+ CleanTask,
2144
+ CopyTask,
2145
+ FileSystem,
2146
+ FtpTask,
2147
+ FunctionTask,
2148
+ HtmlTask,
2149
+ LogLevel,
2150
+ PUBLIC_URL,
2151
+ Pipeline,
2152
+ PublishTask,
2153
+ PwaTask,
2154
+ RemoveTask,
2155
+ ReplaceTask,
2156
+ ScriptTask,
2157
+ ServerTask,
2158
+ StyleTask,
2159
+ TaskDAG,
2160
+ VirtualFile,
2161
+ ZipTask,
2162
+ balm,
2163
+ createDefaultConfig,
2164
+ deepMerge,
2165
+ file,
2166
+ getWorkspaces,
2167
+ globalResolve,
2168
+ globalWorkspace,
2169
+ isArray,
2170
+ isBoolean,
2171
+ isFunction,
2172
+ isObject,
2173
+ isString,
2174
+ localResolve,
2175
+ localWorkspace,
2176
+ logger,
2177
+ resolveConfig,
2178
+ runEsbuild,
2179
+ runRollup,
2180
+ runWebpack,
2181
+ setWorkspaces,
2182
+ toNamespace,
2183
+ transformHtmlmin,
2184
+ transformLess,
2185
+ transformPostcss,
2186
+ transformRename,
2187
+ transformReplace,
2188
+ transformSass,
2189
+ transformTerser
2190
+ });
2191
+ //# sourceMappingURL=index.cjs.map