Skip to content
Closed
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
35 changes: 29 additions & 6 deletions apps/cli/scripts/__tests__/ensure-superdoc-build.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from 'bun:test';
import { ensureDocumentApiBuild, ensureSuperdocBuild } from '../ensure-superdoc-build.js';
import { ensureDocumentApiBuild, ensureNodeSdkBuild, ensureSuperdocBuild } from '../ensure-superdoc-build.js';

type CommandCall = {
command: string;
Expand Down Expand Up @@ -30,8 +30,31 @@ describe('ensureDocumentApiBuild', () => {
});
});

describe('ensureNodeSdkBuild', () => {
test('generates SDK artifacts and rebuilds the Node SDK package', () => {
const calls: CommandCall[] = [];

ensureNodeSdkBuild((command, args, label) => {
calls.push({ command, args, label });
});

expect(calls).toEqual([
{
command: 'pnpm',
args: ['--prefix', expect.stringContaining('/packages/sdk'), 'run', 'generate'],
label: 'Generate SDK artifacts for CLI runtime',
},
{
command: 'pnpm',
args: ['--prefix', expect.stringContaining('/packages/sdk/langs/node'), 'run', 'build'],
label: 'Build Node SDK for CLI runtime',
Comment on lines +41 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Os-dependent path assertions 🐞 Bug ☼ Reliability

The new ensureNodeSdkBuild test hard-codes POSIX fragments ("/packages/sdk"), but production code
uses path.join(...) for --prefix, which yields platform-specific separators. This will fail on
Windows (and is fragile across path normalization differences).
Agent Prompt
### Issue description
The test for `ensureNodeSdkBuild()` asserts that `--prefix` arguments contain strings like `'/packages/sdk'`, but the implementation builds those paths via `path.join(repoRoot, ...)`, which will produce `\packages\sdk` on Windows.

### Issue Context
This is a unit test fragility that can break Windows CI/local runs even though the code is correct.

### Fix Focus Areas
- apps/cli/scripts/__tests__/ensure-superdoc-build.test.ts[41-50]

### Suggested fix
Update assertions to be separator-agnostic, e.g.:
- Import `node:path` in the test and assert against `path.join('packages','sdk')` and `path.join('packages','sdk','langs','node')`.
- Or normalize both sides: `expect(path.normalize(args[1])).toContain(path.normalize('/packages/sdk'))`.
- Or use a regex that accepts both separators: `/[\\/]packages[\\/]sdk/`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

},
]);
});
});

describe('ensureSuperdocBuild', () => {
test('builds document-api first, then the fast packaged superdoc build by default', () => {
test('builds SDK first, then the fast packaged superdoc build by default', () => {
const calls: CommandCall[] = [];

ensureSuperdocBuild({}, (command, args, label) => {
Expand All @@ -41,13 +64,13 @@ describe('ensureSuperdocBuild', () => {
expect(calls).toEqual([
{
command: 'pnpm',
args: ['exec', 'tsc', '-b', '--clean', 'packages/document-api'],
label: 'Clean document-api dist for CLI runtime',
args: ['--prefix', expect.stringContaining('/packages/sdk'), 'run', 'generate'],
label: 'Generate SDK artifacts for CLI runtime',
},
{
command: 'pnpm',
args: ['exec', 'tsc', '-b', 'packages/document-api'],
label: 'Build document-api dist for CLI runtime',
args: ['--prefix', expect.stringContaining('/packages/sdk/langs/node'), 'run', 'build'],
label: 'Build Node SDK for CLI runtime',
},
{
command: 'pnpm',
Expand Down
22 changes: 20 additions & 2 deletions apps/cli/scripts/ensure-superdoc-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { ensureNoUnknownFlags, isDirectExecution, repoRoot, runCommand } from '.
const allowedFlags = new Set(['--types']);
const superdocRoot = path.join(repoRoot, 'packages/superdoc');
const documentApiRoot = path.join(repoRoot, 'packages/document-api');
const sdkWorkspaceRoot = path.join(repoRoot, 'packages/sdk');
const nodeSdkRoot = path.join(sdkWorkspaceRoot, 'langs/node');
const documentApiProject = path.relative(repoRoot, documentApiRoot);

/**
Expand All @@ -16,9 +18,25 @@ export function ensureDocumentApiBuild(run = runCommand) {
run('pnpm', ['exec', 'tsc', '-b', documentApiProject], 'Build document-api dist for CLI runtime');
}

/**
* Ensures the Node SDK package resolves for CLI builds.
*
* The CLI imports `@superdoc-dev/sdk` for `doc.preset.*`; Bun resolves that
* package through its dist export while compiling native binaries. SDK
* generation exports the CLI contract first, which builds document-api dist
* for clean checkouts.
*
* @returns {void}
*/
export function ensureNodeSdkBuild(run = runCommand) {
run('pnpm', ['--prefix', sdkWorkspaceRoot, 'run', 'generate'], 'Generate SDK artifacts for CLI runtime');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid running full SDK generation in CLI prep

When any CLI lifecycle script that calls ensure-superdoc-build runs (for example pretest, prebuild, prebuild:native, or pretypecheck in apps/cli/package.json), this invokes the SDK workspace's mutating generate script. That generator writes tracked outputs outside the CLI path, including apps/mcp/src/generated/*, packages/sdk/langs/browser/src/*, and prompt/dispatch artifacts under packages/sdk/tools, so a routine CLI build or test can dirty the checkout or silently update unrelated MCP/browser/Python SDK artifacts whenever the contract or prompt inputs drift. Please use a non-mutating currentness check or a Node-SDK-only generation/prep step here.

Useful? React with 👍 / 👎.

run('pnpm', ['--prefix', nodeSdkRoot, 'run', 'build'], 'Build Node SDK for CLI runtime');
}
Comment on lines +31 to +34

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Sdk tools dir not prepared 🐞 Bug ≡ Correctness

ensureNodeSdkBuild builds the Node SDK dist but never creates the package-level tools/ directory
that the SDK presets read at runtime; doc.preset.* can throw TOOLS_ASSET_NOT_FOUND on clean
checkouts/native binaries. This breaks CLI preset operations because the SDK resolves tool JSON
relative to @superdoc-dev/sdk’s package root, while codegen writes tools to packages/sdk/tools
instead.
Agent Prompt
### Issue description
`ensureNodeSdkBuild()` runs SDK generation and `@superdoc-dev/sdk` build, but it does not ensure that `packages/sdk/langs/node/tools/` exists. At runtime, the Node SDK preset loaders resolve tool artifacts via `.../tools/*.json` relative to the SDK package root and throw `TOOLS_ASSET_NOT_FOUND` if they are missing. In a clean checkout / release build environment, codegen writes tools to `packages/sdk/tools` (workspace root), not to the Node SDK package’s `tools/` directory.

### Issue Context
- CLI preset operations (`doc.preset.*`) execute the Node SDK preset machinery in-process via `@superdoc-dev/sdk`.
- The Node SDK preset code reads JSON artifacts from `<sdk package root>/tools`.
- The Node SDK package has `prepack/postpack` scripts that *are* responsible for copying/symlinking tools into the package root, but `ensureNodeSdkBuild()` does not run them.

### Fix Focus Areas
- apps/cli/scripts/ensure-superdoc-build.js[31-34]

### Suggested fix
After `pnpm --prefix packages/sdk run generate`, add a step that makes the Node SDK package’s `tools/` directory available before building/compiling the CLI, for example:
- Run the Node SDK’s `postpack` script to create the symlink: `pnpm --prefix packages/sdk/langs/node run postpack` (creates `tools -> ../../tools`).
  - If you need portability beyond *nix, replace `ln -s` in `postpack` with a Node-based symlink/copy script.
- Alternatively, add a small Node script invoked from `ensureNodeSdkBuild()` that ensures `packages/sdk/langs/node/tools` exists (symlink or copy) and points at `packages/sdk/tools`.

Make sure this step runs **before** `bun build --compile` so preset commands can load tool catalogs in the compiled binary.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


/**
* Ensures the CLI's runtime dependencies are freshly built:
* - document-api contract/catalog dist consumed by CLI + SDK generation
* - document-api contract/catalog dist consumed by CLI metadata export
* - Node SDK dist consumed by `doc.preset.*`
* - packaged `superdoc` for the v1 runtime path
*
* `--types` performs the full published build so package type exports exist.
Expand All @@ -32,7 +50,7 @@ export function ensureSuperdocBuild(options = {}, run = runCommand) {
const scriptName = includeTypes ? 'build:es' : 'build:dev';
const label = includeTypes ? 'Build packaged SuperDoc runtime and types' : 'Build packaged SuperDoc runtime';

ensureDocumentApiBuild(run);
ensureNodeSdkBuild(run);
run('pnpm', ['--prefix', superdocRoot, 'run', scriptName], label);
}

Expand Down
Loading