feat(sdk): add developer project tooling

docs(rfc): propose SDK developer project tooling

feat: rename / docs

ci: fix windows gates

docs: revert
This commit is contained in:
imccyu
2026-07-15 18:17:38 +08:00
parent 5a8466b774
commit 42b07a7022
115 changed files with 11315 additions and 27 deletions
+79
View File
@@ -0,0 +1,79 @@
/**
* User-owned tsdown configuration wrappers and child-process invocation.
*
* @module @deepseek-ai/dsh-scripts/build
*/
import { createRequire } from 'node:module'
import { existsSync, readFileSync, readdirSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import type { UserConfig } from 'tsdown'
import { NodeCommandRunner, type CommandRunner } from '@deepseek-ai/dsh-helper'
function hasLocalPluginPackages(root: string): boolean {
const directory = resolve(root, 'plugins')
return existsSync(directory) && readdirSync(directory, { withFileTypes: true }).some(
item => item.isDirectory() && existsSync(resolve(directory, item.name, 'package.json')),
)
}
function hasTsdownConfig(root: string): boolean {
return ['tsdown.config.ts', 'tsdown.config.js', 'tsdown.config.mjs', 'tsdown.config.mts']
.some(name => existsSync(resolve(root, name)))
}
/**
* Preserve the developer's root config and append a separate workspace pass
* when generated local plugin packages exist.
* @param tsdownConfig - developer-owned root tsdown config.
* @returns root tsdown config and optional local-plugin workspace pass.
*/
export function ProjectBuild(tsdownConfig: UserConfig): UserConfig[] {
if (tsdownConfig.workspace !== undefined) {
throw new Error('ProjectBuild owns workspace discovery; remove config.workspace')
}
const root = resolve(tsdownConfig.cwd ?? process.cwd())
return hasLocalPluginPackages(root)
? [{ ...tsdownConfig }, { workspace: { include: ['plugins/*'] } }]
: [{ ...tsdownConfig }]
}
/**
* Preserve a local plugin package's developer-owned tsdown config.
* @param tsdownConfig - developer-owned plugin tsdown config.
* @returns validated tsdown config copy.
*/
export function PluginBuild(tsdownConfig: UserConfig): UserConfig {
if (tsdownConfig.workspace !== undefined) throw new Error('PluginBuild does not accept nested workspace config')
return { ...tsdownConfig }
}
function resolveTsdownBin(cwd: string): string {
const require = createRequire(resolve(cwd, 'package.json'))
let manifestPath: string
try {
manifestPath = require.resolve('tsdown/package.json')
} catch (error) {
throw new Error(`dsh build requires tsdown in this project: ${String(error)}`)
}
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as { bin?: unknown }
const bin = typeof manifest.bin === 'string'
? manifest.bin
: manifest.bin && typeof manifest.bin === 'object'
? (manifest.bin as Record<string, unknown>).tsdown
: undefined
if (typeof bin !== 'string') throw new Error('installed tsdown package has no executable')
return resolve(dirname(manifestPath), bin)
}
/** Invoke the project's installed tsdown, forwarding all build arguments. */
export async function runProjectBuild(
args: readonly string[],
cwd: string = process.cwd(),
runner: CommandRunner = new NodeCommandRunner(),
): Promise<void> {
if (!hasTsdownConfig(cwd)) return
const result = await runner.run(process.execPath, [resolveTsdownBin(cwd), ...args], resolve(cwd))
if (result.signal) throw new Error(`tsdown was killed by ${result.signal}`)
if (result.exitCode !== 0) throw new Error(`tsdown exited with code ${String(result.exitCode)}`)
}