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