mirror of
https://github.com/nocobase/nocobase.git
synced 2026-10-13 16:19:28 +08:00
* feat(app-cli)!: add the AppCommand authoring API on the root entry
AppCommand exposes rootDir, withApp(({ app, env }) => ...), setStatus and
appPath() flags; --json prints one envelope for success and failure, and
CommandError carries a code, suggestions and details. The authoring API moves
from ./plugins to the package root, a ./testing entry provides
bindAppCommand, the runner closes runtimes a command left open, and console
logs of an application a command creates go to stderr.
* feat(app-cli)!: move every command to the AppCommand output contract
Built-in, plugin and generated commands extend AppCommand, return their
result, and throw CommandError on failure, so --json prints one envelope for
every command. Plugin commands reach the application through withApp() and
take appPath() flags; the CLI example's artifact build is a devCommand.
The testing entry exports runAppCommand next to bindAppCommand, dev-config's
ESLint presets refuse the patterns the contract forbids in cli/, app-cli is
registered as identity-sensitive, and the application and plugin-development
Skills each carry the command-authoring guide, kept identical by a test.
* feat(app-cli): keep command diagnostics on stderr and behind NOCOBASE_CLI_DEBUG
An AppCommand's logToStderr keeps writing under --json: stderr never carries
the document, so progress and confirmations no longer disappear for the agent
that asked for JSON. A CommandError keeps its cause off the chain oclif prints,
and NOCOBASE_CLI_DEBUG prints the redacted error chain behind any command's
failure, from source or dist, replacing release's own handling. The Skills
describe using the application's logger inside withApp() for records that
belong in its log files.
* feat(app-cli): make commands discoverable, previewable and recoverable for agents
- `nocobase commands --json` lists every registered command with its source,
arguments, flags and whether it takes --json, --dry-run and --force; a
deployment lists no development command.
- Invalid usage suggests the flag or command that was probably meant and the
command's --help, drops oclif's trailing hint from the message, and always
exits 2.
- db apply, rollback, redo and reset take --dry-run and return the plan;
FORCE_REQUIRED carries that plan and the --force/--dry-run forms; a busy task
lock fails with DATABASE_LOCKED, backed by TaskLockBusyError in
@nocobase/db. Help examples lead with --dry-run.
- release reports upload and deployment progress on stderr while it waits.
- The runner no longer exits 13 with an unsettled top-level await when a
reader such as `| head` closes stdout early.
* fix(app-cli): address review findings on the command contract
- withApp() and the db commands report a failure to put the application away as a warning instead of failing work that already succeeded or replacing the failure it ended in; a rerun of `db rollback` no longer rolls back a second batch
- suggestions and config init's next steps name `node <dist>/cli/index.js` in a built dist/, which has no pnpm; AppCommand gains `this.cliCommand(args)` for the same in a command's own suggestions
- usage errors never repeat a typed value, list allowed values and the flags a conflict involves, and release upload/deploy report them as INVALID_USAGE like every other command; `this.error()` reports COMMAND_FAILED rather than invalid usage
- NOCOBASE_CLI_DEBUG prints a failure's diagnostics once, and oclif's raw stack no longer replaces the message and its suggestions
- appPath() defaults declared in baseFlags resolve against the application root
- every --dry-run answers success-noop, and so does a db command that found nothing to do
- a dry run creates no SQLite file that does not exist yet: drivers may report hasStorage(), and a dry run then answers for an empty database without connecting
- the runner's safety net destroys a leaked runtime's scope even when shutdown fails
- a command bound without an id is named after its class, and the Skills' examples name app commands as the runner does
* fix(app-cli): address the remaining review threads on the command contract
- a single misspelled topic, such as `plugn`, now suggests that topic's help instead of only the full command list
- `commands --json` marks an appPath() default with `defaultRelativeTo: "application-root"`, matching what --help says
- the reason oclif gives for a `combinable` conflict is repeated instead of collapsing to a generic message: the pattern expected "Only of the following" where oclif writes "Only the following"
- the runner's own EPIPE handler is removed: it never installed, because @oclif/core swallows EPIPE on stdout at import, and exiting there would have skipped withApp() and the runner's cleanup; a test now covers a command that keeps printing after its reader leaves
* test(ai-employee): give the Skills tests' first render room to load the page
The first render in the file waits for the employee heading with findBy's default 1 s, which the page's import graph can outlast when CI runs every package's tests at once. The Tools tests hit the same wait and got a 10 s timeout in #413; the Skills tests now match.
* test(app-cli): inspect a workspace of the test's own rather than the repository
The workspace-root inspection test from #439 scanned the real repository's packages/, where other app-cli tests create and delete temporary applications under tests/.tmp while they run. Run together, the scan read one mid-write and the inspection failed. It now builds the one-application workspace it needs.