balm-core 5.2.0 → 6.0.0-alpha.1

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