Skip to content

feat: Removing /output wrapper project from CLI package.json template#111

Open
szanata wants to merge 4 commits into
mainfrom
chore/remove_output_wrapper
Open

feat: Removing /output wrapper project from CLI package.json template#111
szanata wants to merge 4 commits into
mainfrom
chore/remove_output_wrapper

Conversation

@szanata

@szanata szanata commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Dropped @outputai/output project.
  • Updated output init to installs all packages directly.
  • Updated output update to check each package version and update them individually.
  • Added a warning about using the deprecated package in output init, output migrate and output dev.

Reasoning

When installing the SDK modules via a third party dependency (@outputai/output), they all become indirect dependencies (only that is actually present in the package.json).

So, when the code imports "core" or "http", it is actually importing dependencies of a dependency, which is an anti-pattern in NPM and package managing in general.

@szanata
szanata marked this pull request as draft April 7, 2026 20:23
@szanata
szanata force-pushed the chore/remove_output_wrapper branch from d1d5094 to 5139dc4 Compare June 9, 2026 22:36
@szanata
szanata force-pushed the chore/remove_output_wrapper branch from 5139dc4 to 8601ea2 Compare June 29, 2026 17:39
@mintlify

mintlify Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
outputai 🟢 Ready View Preview Jun 29, 2026, 5:39 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@szanata
szanata marked this pull request as ready for review June 29, 2026 19:29

return packageJsonDeps;
} catch ( error ) {
debug( 'Failed to read local package.json: %O', error );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this conflates a corrupt or unreadable file (invalid/broken structure or file perms issue) with "file doesn't exist". The "doesn't exist" path seems fine, there's no warnings, but a corrupt file also shows no issues unless you have the debug flag on.

Build the packages locally then create a corrupt package.json and try it:

❯ printf '%s\n' '{ "name": "demo", "dependencies": { "@outputai/output": "^0.9.0" } }' > package.json

❯ cat package.json| jq
jq: parse error: Expected another key-value pair at line 1, column 67

❯ node sdk/cli/bin/run.js update --cli

Latest Output SDK version: v0.9.0

Global install: v0.9.0 (up to date)

with debug on:

❯ DEBUG=output-cli:npm-update node sdk/cli/bin/run.js update --cli

Latest Output SDK version: v0.9.0

Global install: v0.9.0 (up to date)
  output-cli:npm-update Failed to read local package.json: SyntaxError: Expected double-quoted property name in JSON at position 66 (line 1 column 67)
  output-cli:npm-update     at JSON.parse (<anonymous>)
  output-cli:npm-update     at readPackageJsonDependencies (file:///Users/clint/go/github.com/growthxai/output/.claude/worktrees/chore/remove_output_wrapper/sdk/cli/dist/services/npm_update_service.js:51:26)

}

export function isPackageJsonVersionOutdated( version: string, latest: string ): boolean {
const range = semver.validRange( version, { includePrerelease: true } );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

does validRange() handle latest etc?

return true;
} catch ( error: unknown ) {
this.warn( `Failed to update local install: ${getErrorMessage( error )}` );
return false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should we throw here? looking at the chain, it looks like we warn that we failed to install something but eventually exit with 0 status code in the CLI

this.warn( `Some Output SDK packages are still behind v${latest}: ${staleNames}` );
}
} else {
this.log( '\nLocal update completed (could not verify new versions)' );

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should we throw here? we log that we couldn't verify anything but then exit 0?

Comment on lines +164 to 184
export async function updateLocal( cwd: string, packageNames: string[], version: string ): Promise<void> {
const packages = packageNames.map( name => `${name}@${version}` );
await spawnInherit( 'npm', [ 'install', '--ignore-scripts', '--save-exact', ...packages ], cwd );
}

export async function updateLocalPackages( cwd: string, packages: LocalSdkPackage[], version: string ): Promise<void> {
const dependencies = packages
.filter( pkg => pkg.dependencyType === 'dependencies' )
.map( pkg => `${pkg.name}@${version}` );
const devDependencies = packages
.filter( pkg => pkg.dependencyType === 'devDependencies' )
.map( pkg => `${pkg.name}@${version}` );

if ( dependencies.length > 0 ) {
await spawnInherit( 'npm', [ 'install', '--ignore-scripts', '--save-exact', ...dependencies ], cwd );
}

if ( devDependencies.length > 0 ) {
await spawnInherit( 'npm', [ 'install', '--ignore-scripts', '--save-dev', '--save-exact', ...devDependencies ], cwd );
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

what is the difference between updateLocal() and updateLocalPackages() such that we need/want both?


function findVersionInTree( deps: Record<string, any> | undefined ): string | null {
export interface LocalSdkPackage {
name: string;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: This can only ever be something from LOCAL_SDK_PACKAGE_NAMES, right? Should or could we tighten it from string?

name: typeof LOCAL_SDK_PACKAGE_NAMES[number];   // '@outputai/cli' | '@outputai/core' | ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants