diff --git a/package.json b/package.json index 7a864c8..b6bc711 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "chalk": "^4.1.0", "chokidar": "^3.5.1", "esbuild": "^0.9.2", + "execa": "^5.0.0", "globby": "^11.0.2", "joycon": "^2.2.5", "postcss-load-config": "^3.0.1", @@ -41,15 +42,15 @@ "@types/node": "^14.14.35", "@types/resolve": "^1.20.0", "buble": "^0.20.0", - "execa": "^5.0.0", "fs-extra": "^9.1.0", "jest": "^26.6.3", "jju": "^1.4.0", "postcss": "^8.2.8", "postcss-simple-vars": "^6.0.3", "prettier": "^2.2.1", - "rollup-plugin-hashbang": "^2.2.2", "rollup-plugin-dts": "^2.0.1", + "rollup-plugin-hashbang": "^2.2.2", + "string-argv": "^0.3.1", "strip-json-comments": "^3.1.1", "svelte": "3.35.0", "ts-essentials": "^7.0.1", diff --git a/src/cli.ts b/src/cli.ts index 9b7db0a..d5bd293 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -40,6 +40,10 @@ async function main() { .option('--dts-resolve', 'Resolve externals types used for d.ts files') .option('--sourcemap', 'Generate sourcemap file') .option('--watch', 'Watch mode') + .option( + '--onSuccess ', + 'Execute command after successful build, specially useful for watch mode' + ) .option('--env.* ', 'Define compile-time env variables') .option('--define.* ', 'Define compile-time constants') .option('--external ', 'Mark specific packages as external') diff --git a/src/index.ts b/src/index.ts index 17f3ce3..edb7769 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,9 @@ import { postcssPlugin } from './plugins/postcss' import { externalPlugin } from './plugins/external' import { sveltePlugin } from './plugins/svelte' import resolveFrom from 'resolve-from' +import { parseArgsStringToArgv } from 'string-argv' +import type { ChildProcess } from 'child_process' +import execa from 'execa' const textDecoder = new TextDecoder('utf-8') @@ -42,6 +45,7 @@ export type Options = { minifySyntax?: boolean keepNames?: boolean watch?: boolean + onSuccess?: string jsxFactory?: string jsxFragment?: string outDir?: string @@ -344,6 +348,8 @@ export async function build(_options: Options) { }) } + let existingOnSuccess: ChildProcess | undefined + const buildAll = async () => { if (options.clean) { await removeFiles(['**/*', '!**/*.d.ts'], options.outDir) @@ -356,6 +362,16 @@ export async function build(_options: Options) { runEsbuild(options, { format, css: index === 0 ? css : undefined }) ), ]) + if (options.onSuccess) { + if (existingOnSuccess) existingOnSuccess.kill() + + const parts = parseArgsStringToArgv(options.onSuccess) + const exec = parts[0] + const args = parts.splice(1) + existingOnSuccess = execa(exec, args, { + stdio: 'inherit', + }) + } } try { diff --git a/test/index.test.ts b/test/index.test.ts index 84008b5..bb6d3af 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -495,3 +495,18 @@ test('bundle svelte', async () => { " `) }) + +test('onSuccess', async () => { + const randomNumber = Math.random() + '' + const { logs } = await run( + getTestName(), + { + 'input.ts': "console.log('test');", + }, + { + flags: ['--onSuccess', 'echo ' + randomNumber], + } + ) + + expect(logs.includes(randomNumber)).toBe(true) +}) diff --git a/yarn.lock b/yarn.lock index 8b5c0e5..ed45d0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3801,6 +3801,11 @@ stealthy-require@^1.1.1: resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= +string-argv@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + string-length@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1"