Configure applications with defineConfig - #514
Draft
tuler wants to merge 1 commit into
Draft
Conversation
Replace `cartesi.toml` with a `cartesi.config.ts` file that exports its configuration through `defineConfig`, imported from `@cartesi/cli/config`. The helper does nothing at runtime, and exists so the configuration is type checked and completed by the editor, without any annotation. A configuration file may also export a function, which receives the command being run and the mode, so a project can configure itself differently for `build` and `run`. TypeScript configuration files are read by the runtime itself, which covers the standalone binaries (bun) and recent versions of node; older versions of node fall back to jiti, kept external so it can transpile at runtime. Applications not written in TypeScript or JavaScript describe the same configuration as plain data, in a `cartesi.config.json`, `cartesi.config.yaml` or `cartesi.config` file, the last one read as YAML so it accepts JSON too. Because those are not type checked, the whole configuration is validated at load time, whichever format it came from. The configuration gained a `run` section with the project defaults of the local development environment, so they do not have to be repeated on every `cartesi run`. Command line options take precedence over it, which is why the commander defaults were moved into `run` itself. `cartesi.toml` keeps working, and is read when a project has no other configuration file, but is deprecated and prints a warning. Its parser moves to `config/toml.ts` and is otherwise left frozen. Along the way: - sizes are parsed strictly and understand the IEC units, so `"64Mi"` is 64 MiB instead of being silently read as 64 bytes by `bytes.parse`, which falls back to `parseInt`. This drops the `bytes` dependency, now unused; - errors of an asynchronous command action are reported without a stack trace, as intended: they surfaced as unhandled rejections, which had no handler, and the handler that did exist was dead code because the bundler replaces `process.env.NODE_ENV` at build time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHFyMTf1k57qtDwcbwVjrs
🦋 Changeset detectedLatest commit: 0471fc9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Contributor
Coverage Report
📁 File Coverage (20 files)
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces
cartesi.tomlwith acartesi.config.tsfile that exports its configuration throughdefineConfig, in the style of rolldown and tsdown, so an application can be configured without reaching for the programmatic API.defineConfigdoes nothing at runtime: it exists so the configuration is type checked and completed by the editor, without any annotation. A configuration file may also export a function, which receives the command being run and the mode, so a project can configure itself differently forbuildandrun:Based on #512, which it builds directly on top of.
Key Changes
defineConfig(src/config/user.ts), exported from a new@cartesi/cli/configsubpath so a configuration file does not pull in the rest of the CLI. Also re-exported from the main entrypoint.Configuration subsystem (
src/config/): the oldsrc/config.tsbecomes a module withtypes.ts(resolved types),user.ts(input types anddefineConfig),normalize.ts(validation and defaulting),load.ts(discovery and loading),merge.ts,size.ts,errors.ts, andtoml.tsfor the deprecated format.Applications not written in TypeScript describe the very same configuration as plain data. The configuration file of a project is the first of these that exists:
cartesi.config.ts,.mts,.cts,.js,.mjs,.cjsdefineConfig({ ... })cartesi.config.jsoncartesi.config.yaml,cartesi.config.ymlcartesi.configcartesi.tomlBecause the data formats are not type checked, the whole configuration is validated at load time, whichever format it came from. A
$schemakey is accepted and ignored.runsection: project level defaults of the local development environment (epochLength,services,blockTime,forkUrl,projectName, ...), so they do not have to be repeated on everycartesi run. Command line options take precedence, which is why the commander defaults moved intorunitself; the layering is a pureresolveRunOptionsfunction.cartesi.tomlkeeps working, and is read when a project has no other configuration file, but is deprecated and prints a warning. Its parser moves toconfig/toml.tsand is otherwise left frozen: it stays snake_case and has no[run]section.Notable Implementation Details
jiti, keptexternalin the bundle because it lazily requires its own transform at runtime and cannot be bundled. Both paths were verified against the built artifacts.path.extnamereads a file with no format in its name, such ascartesi.config, as.config, which is handled as YAML.Configis a validUserConfig, so it can be given straight back toresolveConfig, and normalizing it again is idempotent.withdrawalis the name in the input, withwithdrawalConfigaccepted for that reason.runshell relies on.Behavior Changes
resolveConfigis now asynchronous, since a configuration file has to be imported, and itsconfigoption accepts a configuration written inline, in the same shape acartesi.config.tsfile exports.-c/--configdefaults to looking the configuration file of the project up, rather than tocartesi.toml. An explicitly given file that does not exist is an error, as before.--default-blockwarning moved from theruncommand intorun(), where the resolved value is known, and is silenced along with the rest of the progress output.Fixes Found Along the Way
"64Mi"is 64 MiB instead of being silently read as 64 bytes:bytes.parsefalls back toparseInton strings it does not recognize, which made a drive several orders of magnitude too small. This drops thebytesdependency, now unused.process.env.NODE_ENVwith its build time value.Testing
Linting, type checking and 217 unit tests pass, up from 154. The new tests cover
defineConfig, normalization and validation of every section, size parsing, file discovery and precedence, loading each supported format, merging a list of files, and the layering of therunoptions.End to end, against the built artifacts rather than the sources: a TypeScript configuration exporting a function was loaded both by
dist/lib.jsunder node and by the compiledlinux-x64binary, along with the YAML, barecartesi.configand deprecated TOML files, and the error paths were checked to print a single line. Docker was not available in the development environment, so the build itself was only exercised up to the point where it shells out.Two things left out, both easy to add later: a generated JSON Schema for
$schemadriven completion in the data formats, and the application templates, which live in another repository.https://claude.ai/code/session_01BHFyMTf1k57qtDwcbwVjrs
Generated by Claude Code