balm-core 5.2.0 → 6.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/index.cjs +2625 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +569 -0
- package/dist/index.d.ts +569 -0
- package/dist/index.js +2527 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -123
- package/src/balm.ts +108 -0
- package/src/bundler/esbuild.ts +47 -0
- package/src/bundler/index.ts +3 -0
- package/src/bundler/rollup.ts +45 -0
- package/src/bundler/webpack.ts +124 -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 +224 -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 +135 -0
- package/src/pipeline/transforms/cache.ts +146 -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 +72 -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 +232 -0
- package/src/tasks/index.ts +14 -0
- package/src/tasks/publish.ts +71 -0
- package/src/tasks/pwa.ts +99 -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 +183 -0
- package/src/tasks/static.ts +104 -0
- package/src/tasks/style.ts +57 -0
- package/src/tasks/zip.ts +65 -0
- package/src/types/index.ts +202 -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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { BaseTask } from '../runner/task.js';
|
|
4
|
+
import { BalmConfig } from '../types/index.js';
|
|
5
|
+
import { Pipeline } from '../pipeline/pipeline.js';
|
|
6
|
+
import { PUBLIC_URL } from '../config/constants.js';
|
|
7
|
+
|
|
8
|
+
export class StaticTask extends BaseTask {
|
|
9
|
+
constructor() {
|
|
10
|
+
super({ name: 'static', description: 'Copy static assets, images, fonts, and manifest' });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async run(config: BalmConfig): Promise<void> {
|
|
14
|
+
const srcBase = config.src.base;
|
|
15
|
+
const destBase = config.dest.base;
|
|
16
|
+
|
|
17
|
+
// 1. Copy root static files (favicon.ico, robots.txt, icons, etc.)
|
|
18
|
+
const staticPatterns = [
|
|
19
|
+
path.join(srcBase, '*.{ico,png,svg,json,txt,xml,webmanifest}'),
|
|
20
|
+
`!${path.join(srcBase, '*.html')}`
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const pipeline = Pipeline.from(staticPatterns, {
|
|
24
|
+
cwd: config.workspace,
|
|
25
|
+
base: srcBase
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const publicUrlReplacement = config.assets.virtualDir ? `/${config.assets.virtualDir}` : '';
|
|
29
|
+
pipeline.pipe(async (file) => {
|
|
30
|
+
if (file.basename === 'manifest.json' || file.extname === '.json') {
|
|
31
|
+
let content = file.toString();
|
|
32
|
+
content = content.replaceAll(PUBLIC_URL, publicUrlReplacement);
|
|
33
|
+
file.contents = Buffer.from(content);
|
|
34
|
+
}
|
|
35
|
+
return file;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
await pipeline.dest(destBase);
|
|
39
|
+
|
|
40
|
+
// 2. Copy images folder if exists in src
|
|
41
|
+
if (config.src.img && existsSync(config.src.img)) {
|
|
42
|
+
const imgPipeline = Pipeline.from(path.join(config.src.img, '**/*'), {
|
|
43
|
+
cwd: config.workspace,
|
|
44
|
+
base: config.src.img
|
|
45
|
+
});
|
|
46
|
+
await imgPipeline.dest(config.dest.img);
|
|
47
|
+
|
|
48
|
+
// If source and target img dirs differ (e.g. images vs img), also copy to source dir for compatibility
|
|
49
|
+
if (config.paths.source.img && config.paths.target.img && config.paths.source.img !== config.paths.target.img) {
|
|
50
|
+
const compatPipeline = Pipeline.from(path.join(config.src.img, '**/*'), {
|
|
51
|
+
cwd: config.workspace,
|
|
52
|
+
base: config.src.img
|
|
53
|
+
});
|
|
54
|
+
await compatPipeline.dest(path.join(destBase, config.paths.source.img));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 3. Copy fonts folder if exists in src
|
|
59
|
+
if (config.src.font && existsSync(config.src.font)) {
|
|
60
|
+
const fontPipeline = Pipeline.from(path.join(config.src.font, '**/*'), {
|
|
61
|
+
cwd: config.workspace,
|
|
62
|
+
base: config.src.font
|
|
63
|
+
});
|
|
64
|
+
await fontPipeline.dest(config.dest.font);
|
|
65
|
+
|
|
66
|
+
// Ensure both 'font' and 'fonts' directories exist in dest for compatibility
|
|
67
|
+
const targetFontsDir = path.join(destBase, 'fonts');
|
|
68
|
+
if (config.dest.font !== targetFontsDir) {
|
|
69
|
+
const fontsPipeline = Pipeline.from(path.join(config.src.font, '**/*'), {
|
|
70
|
+
cwd: config.workspace,
|
|
71
|
+
base: config.src.font
|
|
72
|
+
});
|
|
73
|
+
await fontsPipeline.dest(targetFontsDir);
|
|
74
|
+
}
|
|
75
|
+
const targetFontDir = path.join(destBase, 'font');
|
|
76
|
+
if (config.dest.font !== targetFontDir) {
|
|
77
|
+
const fontCompatPipeline = Pipeline.from(path.join(config.src.font, '**/*'), {
|
|
78
|
+
cwd: config.workspace,
|
|
79
|
+
base: config.src.font
|
|
80
|
+
});
|
|
81
|
+
await fontCompatPipeline.dest(targetFontDir);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 4. Copy media folder if exists in src
|
|
86
|
+
if (config.src.media && existsSync(config.src.media)) {
|
|
87
|
+
const mediaPipeline = Pipeline.from(path.join(config.src.media, '**/*'), {
|
|
88
|
+
cwd: config.workspace,
|
|
89
|
+
base: config.src.media
|
|
90
|
+
});
|
|
91
|
+
await mediaPipeline.dest(config.dest.media);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 5. Copy public folder if exists in workspace
|
|
95
|
+
const publicDir = path.join(config.workspace, 'public');
|
|
96
|
+
if (existsSync(publicDir)) {
|
|
97
|
+
const pubPipeline = Pipeline.from(path.join(publicDir, '**/*'), {
|
|
98
|
+
cwd: config.workspace,
|
|
99
|
+
base: publicDir
|
|
100
|
+
});
|
|
101
|
+
await pubPipeline.dest(destBase);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { BaseTask } from '../runner/task.js';
|
|
3
|
+
import { BalmConfig } from '../types/index.js';
|
|
4
|
+
import { Pipeline } from '../pipeline/pipeline.js';
|
|
5
|
+
import { transformSass } from '../pipeline/transforms/sass.js';
|
|
6
|
+
import { transformLess } from '../pipeline/transforms/less.js';
|
|
7
|
+
import { transformPostcss } from '../pipeline/transforms/postcss.js';
|
|
8
|
+
|
|
9
|
+
export class StyleTask extends BaseTask {
|
|
10
|
+
constructor() {
|
|
11
|
+
super({ name: 'style', description: 'Compile stylesheets' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async run(config: BalmConfig): Promise<void> {
|
|
15
|
+
const ext = config.styles.extname;
|
|
16
|
+
const srcPattern = path.join(config.src.css, `**/*.${ext}`);
|
|
17
|
+
const isProd = config.env.isProd;
|
|
18
|
+
|
|
19
|
+
const pipeline = Pipeline.from([srcPattern, `!${path.join(config.src.css, '**/_*.scss')}`, `!${path.join(config.src.css, '**/_*.less')}`], {
|
|
20
|
+
cwd: config.workspace,
|
|
21
|
+
base: config.src.css
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const styleAlias = {
|
|
25
|
+
...config.alias,
|
|
26
|
+
...config.styles.alias
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (ext === 'scss' || ext === 'sass') {
|
|
30
|
+
pipeline.pipe(
|
|
31
|
+
transformSass({
|
|
32
|
+
includePaths: [config.src.css, ...config.styles.atImportPaths],
|
|
33
|
+
alias: styleAlias,
|
|
34
|
+
...config.styles.sassOptions
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
} else if (ext === 'less') {
|
|
38
|
+
pipeline.pipe(
|
|
39
|
+
transformLess({
|
|
40
|
+
paths: [config.src.css, ...config.styles.atImportPaths],
|
|
41
|
+
alias: styleAlias,
|
|
42
|
+
...config.styles.lessOptions
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
pipeline.pipe(
|
|
48
|
+
transformPostcss({
|
|
49
|
+
plugins: config.styles.postcssPlugins,
|
|
50
|
+
minify: isProd || config.styles.minify,
|
|
51
|
+
...config.styles.postcssLoaderOptions
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
await pipeline.dest(config.dest.css);
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/tasks/zip.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import archiver from 'archiver';
|
|
4
|
+
import { BaseTask } from '../runner/task.js';
|
|
5
|
+
import { BalmConfig } from '../types/index.js';
|
|
6
|
+
import { file as fsUtil } from '../utilities/file.js';
|
|
7
|
+
import { logger } from '../utilities/logger.js';
|
|
8
|
+
|
|
9
|
+
export interface ZipTaskOptions {
|
|
10
|
+
input?: string | string[];
|
|
11
|
+
output?: string;
|
|
12
|
+
filename?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class ZipTask extends BaseTask {
|
|
16
|
+
private options: ZipTaskOptions;
|
|
17
|
+
|
|
18
|
+
constructor(options: ZipTaskOptions = {}) {
|
|
19
|
+
super({ name: 'zip', description: 'Compress files into archive' });
|
|
20
|
+
this.options = options;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async run(config: BalmConfig): Promise<void> {
|
|
24
|
+
const input = this.options.input || config.dest.base;
|
|
25
|
+
const outputDir = this.options.output
|
|
26
|
+
? (path.isAbsolute(this.options.output) ? this.options.output : path.join(config.workspace, this.options.output))
|
|
27
|
+
: config.workspace;
|
|
28
|
+
const filename = this.options.filename || 'archive.zip';
|
|
29
|
+
const zipPath = path.join(outputDir, filename);
|
|
30
|
+
|
|
31
|
+
await fsUtil.ensureDir(outputDir);
|
|
32
|
+
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const outputStream = fs.createWriteStream(zipPath);
|
|
35
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
36
|
+
|
|
37
|
+
outputStream.on('close', () => {
|
|
38
|
+
logger.success('zip', `Created ${zipPath} (${archive.pointer()} total bytes)`);
|
|
39
|
+
resolve();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
archive.on('error', (err) => {
|
|
43
|
+
logger.error('zip', err.message);
|
|
44
|
+
reject(err);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
archive.pipe(outputStream);
|
|
48
|
+
|
|
49
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
50
|
+
for (const item of inputs) {
|
|
51
|
+
const fullPath = path.isAbsolute(item) ? item : path.join(config.workspace, item);
|
|
52
|
+
if (fs.existsSync(fullPath)) {
|
|
53
|
+
const stat = fs.statSync(fullPath);
|
|
54
|
+
if (stat.isDirectory()) {
|
|
55
|
+
archive.directory(fullPath, false);
|
|
56
|
+
} else {
|
|
57
|
+
archive.file(fullPath, { name: path.basename(fullPath) });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
archive.finalize();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
export type LooseObject = Record<string, any>;
|
|
2
|
+
export type DeepPartial<T> = {
|
|
3
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type BalmEntry = string | string[] | Record<string, string | string[]>;
|
|
7
|
+
|
|
8
|
+
export interface BalmRoots {
|
|
9
|
+
source: string;
|
|
10
|
+
tmp: string;
|
|
11
|
+
target: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface BalmPathMap {
|
|
15
|
+
base: string;
|
|
16
|
+
html: string;
|
|
17
|
+
css: string;
|
|
18
|
+
js: string;
|
|
19
|
+
img: string;
|
|
20
|
+
font: string;
|
|
21
|
+
media: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface BalmPaths {
|
|
25
|
+
source: BalmPathMap;
|
|
26
|
+
tmp: Omit<BalmPathMap, 'html'>;
|
|
27
|
+
target: Omit<BalmPathMap, 'html'>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface BalmStyles {
|
|
31
|
+
extname: string;
|
|
32
|
+
minify: boolean;
|
|
33
|
+
atImportPaths: string[];
|
|
34
|
+
alias: Record<string, string>;
|
|
35
|
+
options: Record<string, any>;
|
|
36
|
+
sassOptions: Record<string, any>;
|
|
37
|
+
lessOptions: Record<string, any>;
|
|
38
|
+
postcssLoaderOptions: Record<string, any>;
|
|
39
|
+
postcssPlugins: any[];
|
|
40
|
+
sprites: string[];
|
|
41
|
+
spriteOptions: Record<string, any>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export enum BundlerType {
|
|
45
|
+
webpack = 'webpack',
|
|
46
|
+
rollup = 'rollup',
|
|
47
|
+
esbuild = 'esbuild'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface BalmScripts {
|
|
51
|
+
bundler: BundlerType | 'webpack' | 'rollup' | 'esbuild';
|
|
52
|
+
minify: boolean;
|
|
53
|
+
minifyOptions: Record<string, any>;
|
|
54
|
+
entry: BalmEntry;
|
|
55
|
+
target: string | string[];
|
|
56
|
+
library: string | Record<string, any>;
|
|
57
|
+
libraryTarget: string;
|
|
58
|
+
externals: string | string[] | Record<string, any> | RegExp | Function;
|
|
59
|
+
injectHtml: boolean;
|
|
60
|
+
htmlName: string;
|
|
61
|
+
htmlPluginOptions?: Record<string, any>;
|
|
62
|
+
alias: Record<string, string>;
|
|
63
|
+
extensions?: string[];
|
|
64
|
+
plugins: any[];
|
|
65
|
+
loaders: any[];
|
|
66
|
+
defaultLoaders: {
|
|
67
|
+
html?: boolean;
|
|
68
|
+
css?: boolean;
|
|
69
|
+
js?: boolean;
|
|
70
|
+
url?: boolean;
|
|
71
|
+
};
|
|
72
|
+
options: Record<string, any>;
|
|
73
|
+
esbuildOptions: Record<string, any>;
|
|
74
|
+
rollupOptions: Record<string, any>;
|
|
75
|
+
webpackOptions: Record<string, any>;
|
|
76
|
+
useCache: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface BalmHtml {
|
|
80
|
+
options: Record<string, any>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface BalmAssets {
|
|
84
|
+
root: string;
|
|
85
|
+
mainDir: string;
|
|
86
|
+
subDir: string;
|
|
87
|
+
buildDir: string;
|
|
88
|
+
virtualDir: string;
|
|
89
|
+
cache: boolean;
|
|
90
|
+
options: {
|
|
91
|
+
fileNameManifest?: string;
|
|
92
|
+
dontRenameFile?: (string | RegExp)[];
|
|
93
|
+
dontUpdateReference?: (string | RegExp)[];
|
|
94
|
+
hashLength?: number;
|
|
95
|
+
[key: string]: any;
|
|
96
|
+
};
|
|
97
|
+
includes: string[];
|
|
98
|
+
excludes: string[];
|
|
99
|
+
static?: string;
|
|
100
|
+
[key: string]: any;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface BalmServer {
|
|
104
|
+
host: string | null;
|
|
105
|
+
port: number;
|
|
106
|
+
open: boolean | string;
|
|
107
|
+
proxy: boolean | Record<string, any> | Array<Record<string, any>>;
|
|
108
|
+
proxyOptions: boolean | Record<string, any> | Array<Record<string, any>>;
|
|
109
|
+
historyOptions: boolean | Record<string, any>;
|
|
110
|
+
useHMR: boolean;
|
|
111
|
+
options: Record<string, any>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface BalmPwa {
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
mode: 'generateSW' | 'injectManifest';
|
|
117
|
+
version: string;
|
|
118
|
+
manifest: string;
|
|
119
|
+
swSrcFilename: string;
|
|
120
|
+
swDestFilename: string;
|
|
121
|
+
options: Record<string, any>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface BalmFtp {
|
|
125
|
+
options: Record<string, any>;
|
|
126
|
+
watchFiles: string[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface BalmImages {
|
|
130
|
+
plugins: any[];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface BalmEnv {
|
|
134
|
+
isProd: boolean;
|
|
135
|
+
isDev: boolean;
|
|
136
|
+
isTest: boolean;
|
|
137
|
+
inFrontend: boolean;
|
|
138
|
+
inSSR: boolean;
|
|
139
|
+
inDesktopApp: boolean;
|
|
140
|
+
isMP: boolean;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface BalmWorkspaces {
|
|
144
|
+
local: string;
|
|
145
|
+
global: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type BalmWorkspaceConfig = string | { local?: string; global?: string };
|
|
149
|
+
|
|
150
|
+
export interface BalmConfig {
|
|
151
|
+
workspace: string;
|
|
152
|
+
workspaces: BalmWorkspaces;
|
|
153
|
+
alias: Record<string, string>;
|
|
154
|
+
env: BalmEnv;
|
|
155
|
+
inFrontend: boolean;
|
|
156
|
+
useDefaults: boolean;
|
|
157
|
+
roots: BalmRoots;
|
|
158
|
+
paths: BalmPaths;
|
|
159
|
+
styles: BalmStyles;
|
|
160
|
+
scripts: BalmScripts;
|
|
161
|
+
html: BalmHtml;
|
|
162
|
+
assets: BalmAssets;
|
|
163
|
+
server: BalmServer;
|
|
164
|
+
pwa: BalmPwa;
|
|
165
|
+
ftp: BalmFtp;
|
|
166
|
+
images: BalmImages;
|
|
167
|
+
logs: {
|
|
168
|
+
level: number;
|
|
169
|
+
};
|
|
170
|
+
src: BalmPathMap;
|
|
171
|
+
dest: BalmPathMap & { static: string };
|
|
172
|
+
[key: string]: any;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export type BalmCustomConfig = Omit<DeepPartial<BalmConfig>, 'workspace'> & {
|
|
176
|
+
workspace?: BalmWorkspaceConfig;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export interface RenameOptions {
|
|
180
|
+
dirname?: string;
|
|
181
|
+
prefix?: string;
|
|
182
|
+
basename?: string;
|
|
183
|
+
suffix?: string;
|
|
184
|
+
extname?: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface ReplaceOptions {
|
|
188
|
+
substr: string | RegExp;
|
|
189
|
+
replacement: string | ((substring: string, ...args: any[]) => string);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface TemplateOption {
|
|
193
|
+
input: string;
|
|
194
|
+
output: string;
|
|
195
|
+
renameOptions?: string | Function | RenameOptions;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface TaskContext {
|
|
199
|
+
config: BalmConfig;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export type TaskFn = (context: TaskContext) => Promise<any> | any;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import fg from 'fast-glob';
|
|
6
|
+
|
|
7
|
+
export class FileSystem {
|
|
8
|
+
workspace: string = process.cwd();
|
|
9
|
+
|
|
10
|
+
resolveApp(...paths: string[]): string {
|
|
11
|
+
return path.resolve(this.workspace, ...paths);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
absPath(filePath: string): string {
|
|
15
|
+
return path.isAbsolute(filePath) ? filePath : this.resolveApp(filePath);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
absPaths(filePaths: string | string[]): string | string[] {
|
|
19
|
+
if (Array.isArray(filePaths)) {
|
|
20
|
+
return filePaths.map((p) => this.absPath(p));
|
|
21
|
+
}
|
|
22
|
+
return this.absPath(filePaths);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async exists(targetPath: string): Promise<boolean> {
|
|
26
|
+
try {
|
|
27
|
+
await fs.access(this.absPath(targetPath));
|
|
28
|
+
return true;
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
existsSync(targetPath: string): boolean {
|
|
35
|
+
return existsSync(this.absPath(targetPath));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async ensureDir(dirPath: string): Promise<void> {
|
|
39
|
+
await fs.mkdir(this.absPath(dirPath), { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async readFile(filePath: string, encoding: BufferEncoding = 'utf8'): Promise<string> {
|
|
43
|
+
return fs.readFile(this.absPath(filePath), { encoding });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async readBuffer(filePath: string): Promise<Buffer> {
|
|
47
|
+
return fs.readFile(this.absPath(filePath));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async writeFile(filePath: string, data: string | Buffer): Promise<void> {
|
|
51
|
+
const fullPath = this.absPath(filePath);
|
|
52
|
+
await this.ensureDir(path.dirname(fullPath));
|
|
53
|
+
await fs.writeFile(fullPath, data);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async remove(targetPath: string | string[]): Promise<string[]> {
|
|
57
|
+
const targets = Array.isArray(targetPath) ? targetPath : [targetPath];
|
|
58
|
+
const removed: string[] = [];
|
|
59
|
+
|
|
60
|
+
for (const item of targets) {
|
|
61
|
+
const fullPath = this.absPath(item);
|
|
62
|
+
try {
|
|
63
|
+
const stat = await fs.stat(fullPath);
|
|
64
|
+
if (stat.isDirectory()) {
|
|
65
|
+
await fs.rm(fullPath, { recursive: true, force: true });
|
|
66
|
+
} else {
|
|
67
|
+
await fs.unlink(fullPath);
|
|
68
|
+
}
|
|
69
|
+
removed.push(fullPath);
|
|
70
|
+
} catch {
|
|
71
|
+
// file doesn't exist or already removed
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return removed;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async copyFile(src: string, dest: string): Promise<void> {
|
|
79
|
+
const srcPath = this.absPath(src);
|
|
80
|
+
const destPath = this.absPath(dest);
|
|
81
|
+
await this.ensureDir(path.dirname(destPath));
|
|
82
|
+
await fs.copyFile(srcPath, destPath);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async copyDir(srcDir: string, destDir: string): Promise<void> {
|
|
86
|
+
const src = this.absPath(srcDir);
|
|
87
|
+
const dest = this.absPath(destDir);
|
|
88
|
+
await this.ensureDir(dest);
|
|
89
|
+
|
|
90
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const srcItem = path.join(src, entry.name);
|
|
93
|
+
const destItem = path.join(dest, entry.name);
|
|
94
|
+
if (entry.isDirectory()) {
|
|
95
|
+
await this.copyDir(srcItem, destItem);
|
|
96
|
+
} else {
|
|
97
|
+
await this.copyFile(srcItem, destItem);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async matchFiles(
|
|
103
|
+
patterns: string | string[],
|
|
104
|
+
options: fg.Options = {}
|
|
105
|
+
): Promise<string[]> {
|
|
106
|
+
const defaultOptions: fg.Options = {
|
|
107
|
+
cwd: this.workspace,
|
|
108
|
+
absolute: true,
|
|
109
|
+
dot: true,
|
|
110
|
+
onlyFiles: true
|
|
111
|
+
};
|
|
112
|
+
return fg(patterns, { ...defaultOptions, ...options });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
hash(content: string | Buffer, length = 8): string {
|
|
116
|
+
return crypto.createHash('md5').update(content).digest('hex').slice(0, length);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const file = new FileSystem();
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
|
|
3
|
+
export enum LogLevel {
|
|
4
|
+
Debug = 0,
|
|
5
|
+
Info = 1,
|
|
6
|
+
Warn = 2,
|
|
7
|
+
Error = 3,
|
|
8
|
+
Silent = 4
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class Logger {
|
|
12
|
+
level: LogLevel = LogLevel.Info;
|
|
13
|
+
|
|
14
|
+
private formatTag(tag?: string): string {
|
|
15
|
+
return tag ? pc.cyan(`[${tag}]`) : pc.bgBlue(pc.black(' BalmJS '));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private timestamp(): string {
|
|
19
|
+
const d = new Date();
|
|
20
|
+
const pad = (n: number) => n.toString().padStart(2, '0');
|
|
21
|
+
return pc.gray(`[${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}]`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
debug(tag: string, message: any, ...args: any[]): void {
|
|
25
|
+
if (this.level <= LogLevel.Debug) {
|
|
26
|
+
console.log(this.timestamp(), this.formatTag(tag), pc.magenta('※'), message, ...args);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
info(tag: string, message: any, ...args: any[]): void {
|
|
31
|
+
if (this.level <= LogLevel.Info) {
|
|
32
|
+
console.log(this.timestamp(), this.formatTag(tag), pc.blue('ℹ'), message, ...args);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
success(tag: string, message: any, ...args: any[]): void {
|
|
37
|
+
if (this.level <= LogLevel.Info) {
|
|
38
|
+
console.log(this.timestamp(), this.formatTag(tag), pc.green('✔'), pc.green(message), ...args);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
warn(tag: string, message: any, ...args: any[]): void {
|
|
43
|
+
if (this.level <= LogLevel.Warn) {
|
|
44
|
+
console.warn(this.timestamp(), this.formatTag(tag), pc.yellow('⚠'), pc.yellow(message), ...args);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
error(tag: string, message: any, ...args: any[]): void {
|
|
49
|
+
if (this.level <= LogLevel.Error) {
|
|
50
|
+
console.error(this.timestamp(), this.formatTag(tag), pc.red('✖'), pc.red(message), ...args);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
time(label: string): () => void {
|
|
55
|
+
const start = performance.now();
|
|
56
|
+
return () => {
|
|
57
|
+
const duration = (performance.now() - start).toFixed(2);
|
|
58
|
+
this.info('time', `${label} completed in ${pc.bold(duration + 'ms')}`);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const logger = new Logger();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function isObject(val: any): val is Record<string, any> {
|
|
2
|
+
return val !== null && typeof val === 'object' && !Array.isArray(val);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isArray(val: any): val is any[] {
|
|
6
|
+
return Array.isArray(val);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isString(val: any): val is string {
|
|
10
|
+
return typeof val === 'string';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isFunction(val: any): val is Function {
|
|
14
|
+
return typeof val === 'function';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isBoolean(val: any): val is boolean {
|
|
18
|
+
return typeof val === 'boolean';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function deepMerge<T extends Record<string, any>>(target: T, ...sources: any[]): T {
|
|
22
|
+
if (!sources.length) return target;
|
|
23
|
+
const source = sources.shift();
|
|
24
|
+
|
|
25
|
+
if (isObject(target) && isObject(source)) {
|
|
26
|
+
for (const key in source) {
|
|
27
|
+
if (isObject(source[key])) {
|
|
28
|
+
if (!target[key]) Object.assign(target, { [key]: {} });
|
|
29
|
+
deepMerge(target[key], source[key]);
|
|
30
|
+
} else if (isArray(source[key])) {
|
|
31
|
+
(target as any)[key] = [...source[key]];
|
|
32
|
+
} else if (source[key] !== undefined) {
|
|
33
|
+
Object.assign(target, { [key]: source[key] });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return deepMerge(target, ...sources);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function toNamespace(name: string | string[], namespace = 'balm'): string | string[] {
|
|
42
|
+
if (isArray(name)) {
|
|
43
|
+
return name.map((item) => `${namespace}:${item}`);
|
|
44
|
+
}
|
|
45
|
+
return `${namespace}:${name}`;
|
|
46
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
export interface WorkspacePaths {
|
|
4
|
+
local: string;
|
|
5
|
+
global: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let currentLocalWorkspace: string = process.cwd();
|
|
9
|
+
let currentGlobalWorkspace: string = path.resolve(process.cwd(), '..');
|
|
10
|
+
|
|
11
|
+
export function setWorkspaces(local?: string, global?: string): void {
|
|
12
|
+
if (local) {
|
|
13
|
+
currentLocalWorkspace = path.resolve(local);
|
|
14
|
+
}
|
|
15
|
+
if (global) {
|
|
16
|
+
currentGlobalWorkspace = path.resolve(global);
|
|
17
|
+
} else if (local && !global) {
|
|
18
|
+
currentGlobalWorkspace = path.resolve(currentLocalWorkspace, '..');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getWorkspaces(): WorkspacePaths {
|
|
23
|
+
return {
|
|
24
|
+
local: currentLocalWorkspace,
|
|
25
|
+
global: currentGlobalWorkspace
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function localWorkspace(subPath: string = ''): string {
|
|
30
|
+
return subPath ? path.resolve(currentLocalWorkspace, subPath) : currentLocalWorkspace;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function globalWorkspace(subPath: string = ''): string {
|
|
34
|
+
return subPath ? path.resolve(currentGlobalWorkspace, subPath) : currentGlobalWorkspace;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const localResolve = localWorkspace;
|
|
38
|
+
export const globalResolve = globalWorkspace;
|