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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import connect from 'connect';
|
|
3
|
+
import serveStatic from 'serve-static';
|
|
4
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
5
|
+
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
6
|
+
import { BaseTask } from '../runner/task.js';
|
|
7
|
+
import { BalmConfig } from '../types/index.js';
|
|
8
|
+
import { FileWatcher } from '../watcher/index.js';
|
|
9
|
+
import { logger } from '../utilities/logger.js';
|
|
10
|
+
import pc from 'picocolors';
|
|
11
|
+
|
|
12
|
+
export class ServerTask extends BaseTask {
|
|
13
|
+
private watcher: FileWatcher | null = null;
|
|
14
|
+
private wsServer: WebSocketServer | null = null;
|
|
15
|
+
private clients = new Set<WebSocket>();
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
super({ name: 'serve', description: 'Start development server with live reload' });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
broadcast(data: { type: 'reload' | 'reload-css'; file?: string }): void {
|
|
22
|
+
const payload = JSON.stringify(data);
|
|
23
|
+
for (const client of this.clients) {
|
|
24
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
25
|
+
client.send(payload);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async run(config: BalmConfig): Promise<void> {
|
|
31
|
+
if (config.env.isProd) {
|
|
32
|
+
logger.warn('server', 'Development server is disabled in production mode');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const app = connect();
|
|
37
|
+
const port = config.server.port || 3000;
|
|
38
|
+
const host = config.server.host || 'localhost';
|
|
39
|
+
|
|
40
|
+
// Static assets
|
|
41
|
+
app.use(serveStatic(config.dest.base));
|
|
42
|
+
app.use(serveStatic(config.src.base));
|
|
43
|
+
|
|
44
|
+
// Proxy middleware
|
|
45
|
+
if (config.server.proxy && typeof config.server.proxy === 'object') {
|
|
46
|
+
const proxyEntries = Array.isArray(config.server.proxy)
|
|
47
|
+
? config.server.proxy
|
|
48
|
+
: [config.server.proxy];
|
|
49
|
+
|
|
50
|
+
for (const entry of proxyEntries) {
|
|
51
|
+
if (entry.context && entry.options) {
|
|
52
|
+
app.use(createProxyMiddleware(entry.options));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const server = http.createServer(app);
|
|
58
|
+
|
|
59
|
+
// WebSocket Live Reload Server
|
|
60
|
+
this.wsServer = new WebSocketServer({ server, path: '/__balm_ws' });
|
|
61
|
+
this.wsServer.on('connection', (socket) => {
|
|
62
|
+
this.clients.add(socket);
|
|
63
|
+
socket.on('close', () => this.clients.delete(socket));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Start File Watcher
|
|
67
|
+
this.watcher = new FileWatcher(config, (data) => {
|
|
68
|
+
this.broadcast(data);
|
|
69
|
+
});
|
|
70
|
+
this.watcher.start();
|
|
71
|
+
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
server.listen(port, host, () => {
|
|
74
|
+
console.log('');
|
|
75
|
+
logger.success('server', pc.bold('BalmJS Dev Server is ready!'));
|
|
76
|
+
console.log(` ${pc.green('➜')} ${pc.bold('Local:')} ${pc.cyan(`http://${host}:${port}/`)}`);
|
|
77
|
+
console.log(` ${pc.green('➜')} ${pc.bold('Network:')} ${pc.cyan(`http://127.0.0.1:${port}/`)}`);
|
|
78
|
+
console.log('');
|
|
79
|
+
|
|
80
|
+
if (config.env.isTest) {
|
|
81
|
+
this.watcher?.stop();
|
|
82
|
+
this.wsServer?.close();
|
|
83
|
+
server.close();
|
|
84
|
+
resolve();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -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,200 @@
|
|
|
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
|
+
alias: Record<string, string>;
|
|
62
|
+
plugins: any[];
|
|
63
|
+
loaders: any[];
|
|
64
|
+
defaultLoaders: {
|
|
65
|
+
html?: boolean;
|
|
66
|
+
css?: boolean;
|
|
67
|
+
js?: boolean;
|
|
68
|
+
url?: boolean;
|
|
69
|
+
};
|
|
70
|
+
options: Record<string, any>;
|
|
71
|
+
esbuildOptions: Record<string, any>;
|
|
72
|
+
rollupOptions: Record<string, any>;
|
|
73
|
+
webpackOptions: Record<string, any>;
|
|
74
|
+
useCache: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface BalmHtml {
|
|
78
|
+
options: Record<string, any>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface BalmAssets {
|
|
82
|
+
root: string;
|
|
83
|
+
mainDir: string;
|
|
84
|
+
subDir: string;
|
|
85
|
+
buildDir: string;
|
|
86
|
+
virtualDir: string;
|
|
87
|
+
cache: boolean;
|
|
88
|
+
options: {
|
|
89
|
+
fileNameManifest?: string;
|
|
90
|
+
dontRenameFile?: (string | RegExp)[];
|
|
91
|
+
dontUpdateReference?: (string | RegExp)[];
|
|
92
|
+
hashLength?: number;
|
|
93
|
+
[key: string]: any;
|
|
94
|
+
};
|
|
95
|
+
includes: string[];
|
|
96
|
+
excludes: string[];
|
|
97
|
+
static?: string;
|
|
98
|
+
[key: string]: any;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface BalmServer {
|
|
102
|
+
host: string | null;
|
|
103
|
+
port: number;
|
|
104
|
+
open: boolean | string;
|
|
105
|
+
proxy: boolean | Record<string, any> | Array<Record<string, any>>;
|
|
106
|
+
proxyOptions: boolean | Record<string, any> | Array<Record<string, any>>;
|
|
107
|
+
historyOptions: boolean | Record<string, any>;
|
|
108
|
+
useHMR: boolean;
|
|
109
|
+
options: Record<string, any>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface BalmPwa {
|
|
113
|
+
enabled: boolean;
|
|
114
|
+
mode: 'generateSW' | 'injectManifest';
|
|
115
|
+
version: string;
|
|
116
|
+
manifest: string;
|
|
117
|
+
swSrcFilename: string;
|
|
118
|
+
swDestFilename: string;
|
|
119
|
+
options: Record<string, any>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface BalmFtp {
|
|
123
|
+
options: Record<string, any>;
|
|
124
|
+
watchFiles: string[];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface BalmImages {
|
|
128
|
+
plugins: any[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface BalmEnv {
|
|
132
|
+
isProd: boolean;
|
|
133
|
+
isDev: boolean;
|
|
134
|
+
isTest: boolean;
|
|
135
|
+
inFrontend: boolean;
|
|
136
|
+
inSSR: boolean;
|
|
137
|
+
inDesktopApp: boolean;
|
|
138
|
+
isMP: boolean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface BalmWorkspaces {
|
|
142
|
+
local: string;
|
|
143
|
+
global: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export type BalmWorkspaceConfig = string | { local?: string; global?: string };
|
|
147
|
+
|
|
148
|
+
export interface BalmConfig {
|
|
149
|
+
workspace: string;
|
|
150
|
+
workspaces: BalmWorkspaces;
|
|
151
|
+
alias: Record<string, string>;
|
|
152
|
+
env: BalmEnv;
|
|
153
|
+
inFrontend: boolean;
|
|
154
|
+
useDefaults: boolean;
|
|
155
|
+
roots: BalmRoots;
|
|
156
|
+
paths: BalmPaths;
|
|
157
|
+
styles: BalmStyles;
|
|
158
|
+
scripts: BalmScripts;
|
|
159
|
+
html: BalmHtml;
|
|
160
|
+
assets: BalmAssets;
|
|
161
|
+
server: BalmServer;
|
|
162
|
+
pwa: BalmPwa;
|
|
163
|
+
ftp: BalmFtp;
|
|
164
|
+
images: BalmImages;
|
|
165
|
+
logs: {
|
|
166
|
+
level: number;
|
|
167
|
+
};
|
|
168
|
+
src: BalmPathMap;
|
|
169
|
+
dest: BalmPathMap & { static: string };
|
|
170
|
+
[key: string]: any;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export type BalmCustomConfig = Omit<DeepPartial<BalmConfig>, 'workspace'> & {
|
|
174
|
+
workspace?: BalmWorkspaceConfig;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export interface RenameOptions {
|
|
178
|
+
dirname?: string;
|
|
179
|
+
prefix?: string;
|
|
180
|
+
basename?: string;
|
|
181
|
+
suffix?: string;
|
|
182
|
+
extname?: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface ReplaceOptions {
|
|
186
|
+
substr: string | RegExp;
|
|
187
|
+
replacement: string | ((substring: string, ...args: any[]) => string);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface TemplateOption {
|
|
191
|
+
input: string;
|
|
192
|
+
output: string;
|
|
193
|
+
renameOptions?: string | Function | RenameOptions;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface TaskContext {
|
|
197
|
+
config: BalmConfig;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
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;
|