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