Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add onDTSSuccess option #1024

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ They should not be included in a published NPM package and should not be confuse

[Tsup is not able to generate those files](https://github.com/egoist/tsup/issues/564). Instead, you should use the TypeScript compiler directly, by running the following command after the build is done: `tsc --emitDeclarationOnly --declaration`.

You can combine this command with Tsup [`onSuccess`](https://tsup.egoist.dev/#onsuccess) callback.
You can combine this command with Tsup [`onSuccess`](https://tsup.egoist.dev/#onsuccess) callback.

### Generate sourcemap file

Expand Down Expand Up @@ -409,6 +409,9 @@ export default defineConfig({
})
```

### onDTSSuccess
`onSuccess` only fires when the JS assets are ready. `onDTSSuccess` fires when the typings are ready, which is a separate task. It functions exactly the same as `onSuccess`

### Minify output

You can also minify the output, resulting into lower bundle sizes by using the `--minify` flag.
Expand Down
5 changes: 4 additions & 1 deletion schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@
"onSuccess": {
"type": "string"
},
"onDTSSuccess": {
"type": "string"
},
"jsxFactory": {
"type": "string"
},
Expand Down Expand Up @@ -264,7 +267,7 @@
},
"silent": {
"type": "boolean",
"description": "Suppress non-error logs (excluding \"onSuccess\" process output)"
"description": "Suppress non-error logs (excluding \"onSuccess\" and \"onDTSSuccess\" process output)"
},
"skipNodeModulesBundle": {
"type": "boolean",
Expand Down
4 changes: 4 additions & 0 deletions src/cli-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ export async function main(options: Options = {}) {
'--onSuccess <command>',
'Execute command after successful build, specially useful for watch mode'
)
.option(
'--onDTSSuccess <command>',
'Execute command after successful build of the typings, specially useful for watch mode'
)
.option('--env.* <value>', 'Define compile-time env variables')
.option(
'--inject <file>',
Expand Down
54 changes: 45 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,27 @@ export async function build(_options: Options) {
logger.info('CLI', 'Running in watch mode')
}

let onDTSSuccessProcess: ChildProcess | undefined
let onDTSSuccessCleanup: (() => any) | undefined | void

const doonDTSSuccessCleanup = async () => {
if (onDTSSuccessProcess) {
await killProcess({
pid: onDTSSuccessProcess.pid,
signal: options.killSignal || 'SIGTERM',
})
} else if (onDTSSuccessCleanup) {
await onDTSSuccessCleanup()
}
// reset them in all occasions anyway
onDTSSuccessProcess = undefined
onDTSSuccessCleanup = undefined
}

const dtsTask = async () => {
if (options.dts) {
doonDTSSuccessCleanup();

await new Promise<void>((resolve, reject) => {
const worker = new Worker(path.join(__dirname, './rollup.js'))
worker.postMessage({
Expand All @@ -187,23 +206,40 @@ export async function build(_options: Options) {
plugins: undefined,
treeshake: undefined,
onSuccess: undefined,
onDTSSuccess: undefined,
outExtension: undefined,
},
})
worker.on('message', (data) => {
if (data === 'error') {
reject(new Error('error occured in dts build'))
} else if (data === 'success') {
resolve()
} else {
const { type, text } = data
if (type === 'log') {
console.log(text)
} else if (type === 'error') {
console.error(text)

if (options.onDTSSuccess) {
if (typeof options.onDTSSuccess === 'function') {
options.onDTSSuccess().then((v) => onDTSSuccessCleanup = v)
} else {
onDTSSuccessProcess = execa(options.onDTSSuccess, {
shell: true,
stdio: 'inherit',
})
onDTSSuccessProcess.on('exit', (code) => {
if (code && code !== 0) {
process.exitCode = code
}
})
}
}
}
})
resolve()
} else {
const { type, text } = data
if (type === 'log') {
console.log(text)
} else if (type === 'error') {
console.error(text)
}
}
})
})
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ export type Options = {
onSuccess?:
| string
| (() => Promise<void | undefined | (() => void | Promise<void>)>)
onDTSSuccess?:
| string
| (() => Promise<void | undefined | (() => void | Promise<void>)>)
jsxFactory?: string
jsxFragment?: string
outDir?: string
Expand All @@ -139,7 +142,7 @@ export type Options = {
/**
* Code splitting
* Default to `true` for ESM, `false` for CJS.
*
*
* You can set it to `true` explicitly, and may want to disable code splitting sometimes: [`#255`](https://github.com/egoist/tsup/issues/255)
*/
splitting?: boolean
Expand Down
83 changes: 83 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,89 @@ test('onSuccess: use a function from config file', async () => {
expect(logs.includes('world')).toEqual(true)
})

test('onDTSSuccess', async () => {
const { logs } = await run(
getTestName(),
{
'input.ts': "console.log('test');",
},
{
flags: [
'--dts',
'--onDTSSuccess', 'echo foo && echo bar'
],
}
)

expect(logs.includes('foo')).toEqual(true)
expect(logs.includes('bar')).toEqual(true)
})

test('onDTSSuccess: use a function from config file', async () => {
const { logs } = await run(getTestName(), {
'input.ts': "console.log('test');",
'tsup.config.ts': `
export default {
onDTSSuccess: async () => {
console.log('hello')
await new Promise((resolve) => {
setTimeout(() => {
console.log('world')
resolve('')
}, 1_000)
})
}
}`,
}, {
'flags': ['--dts']
})

expect(logs.includes('hello')).toEqual(true)
expect(logs.includes('world')).toEqual(true)
})

test('onSuccess and onDTSSuccess run separately: use a function from config file', async () => {
const { logs } = await run(getTestName(), {
'input.ts': "console.log('test');",
'tsup.config.ts': `
export default {
onSuccess: async () => {
console.log("onSuccess Called");
},
onDTSSuccess: async () => {
console.log("onDTSSuccess Called");
},
esbuildPlugins: [
{
name: "delay-success",
setup(build) {
build.onEnd(async (result) => {
console.log("delay plugin start");
await new Promise((resolve) => {
setTimeout(() => {
console.log("delay plugin end");
resolve("");
}, 2_000);
});
});
},
},
],
};
`,
}, {
'flags': ['--dts']
})

const dtsSuccessIndex = logs.indexOf('onDTSSuccess Called');
const onSuccessIndex = logs.indexOf('onSuccess Called');
const delayPluginStartIndex = logs.indexOf('delay plugin start');
const delayPluginEndIndex = logs.indexOf('delay plugin end');
expect(dtsSuccessIndex).toBeLessThan(onSuccessIndex)
expect(delayPluginStartIndex).toBeLessThan(delayPluginEndIndex)
expect(delayPluginEndIndex).toBeLessThan(onSuccessIndex)
})

test('custom tsconfig', async () => {
await run(
getTestName(),
Expand Down