Repository navigation
feat(canton-create): build projects from a starter or an example dApp #240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
e755c8d
feat(templates): add the base Vite + React template
fernandomg 9481e35
feat(templates): add the localnet fragment
fernandomg 9704d60
feat: add the create-canton-dappbooster CLI
fernandomg a5aaecd
chore: register the scaffolder and templates with the root tooling
fernandomg 321aa9e
chore: bump the scaffolder and base template to 0.5.5
gabitoesmiapodo 595c3aa
refactor: move the templates into create-canton-dappbooster
gabitoesmiapodo 33762b2
refactor(kit): list the manifests the version scripts read
gabitoesmiapodo 5b2fb44
fix(templates): allow the localnet build scripts under pnpm
gabitoesmiapodo c04d7de
feat: redraw create-canton-dappbooster with Ink
gabitoesmiapodo b5c73e0
refactor: rename the create-canton-dappbooster folder to canton-create
gabitoesmiapodo 558457d
refactor(canton-create): split the scaffold into starter, daml-toolin…
gabitoesmiapodo 444b714
refactor: move the vesting dApp to examples/amulet-vesting
gabitoesmiapodo f5598a4
refactor: rename the examples folder to example-dapps
gabitoesmiapodo 9c65102
feat(canton-create): ask for the local network and the dApp, with a f…
gabitoesmiapodo 0f32581
feat(canton-create): pack the example dApps in try
gabitoesmiapodo e6b8248
feat(canton-create): record a demo of the installer
gabitoesmiapodo d502470
docs(canton-create): write the installer docs
gabitoesmiapodo 29a1b34
docs: write the scaffold and example READMEs for a new project
gabitoesmiapodo f45b145
docs: describe canton-create in the root docs
gabitoesmiapodo 3ae4cf1
docs: clean up the root CLAUDE.md and architecture.md wording
gabitoesmiapodo 1b65625
fix(canton-create): clean up after a failed demo recording and fix tr…
gabitoesmiapodo 41c6913
docs: correct facts in the installer and root docs
gabitoesmiapodo d923037
refactor(canton-create): trim the demo recorder and try
gabitoesmiapodo ec144d8
docs: stop repeating what other sections already say
gabitoesmiapodo 2fb7362
refactor: run the monorepo loop on the scaffold's own scripts
gabitoesmiapodo e8ecd45
chore: stop ignoring PNG files at the repo root
gabitoesmiapodo cced5d3
build: publish every public package in the release
gabitoesmiapodo d11cac3
Merge branch 'main' into feat/create-canton-dappbooster
gabitoesmiapodo 767b1fe
refactor: move kit/ into scripts/
gabitoesmiapodo 22411b1
refactor: point everything at scripts/
gabitoesmiapodo 5741732
chore: match the Biome schema to the installed CLI
gabitoesmiapodo a7d871d
fix(canton-create): remove what was written when Ctrl-C cancels a run
gabitoesmiapodo 379c8c0
fix(canton-create): keep a versioned example name in the example scope
gabitoesmiapodo 59fa001
docs(canton-create): reword the example name rule
gabitoesmiapodo cba4b8a
fix(canton-create): only use an installed example on the installer's …
gabitoesmiapodo 9d342f8
fix(canton-create): accept an example tarball with any top folder
gabitoesmiapodo 01e1e3a
test(canton-create): check every frame in the two App tests that race…
gabitoesmiapodo 65a466c
fix(canton-create): remove the parent folders a failed run created
gabitoesmiapodo 0f0b1b4
fix: read the workspace packages from pnpm in the version scripts
gabitoesmiapodo 8510545
build: declare canton-barebones only in the localnet layer
gabitoesmiapodo 17ee635
fix(canton-create): refuse a layer manifest field the merge would drop
gabitoesmiapodo 4999091
fix(canton-create): refuse an .env.example block that redefines a key
gabitoesmiapodo f81a64f
docs: drop the stale versions and package count
gabitoesmiapodo a6e38c8
fix(canton-create): stop pointing projects without a LocalNet at mint…
gabitoesmiapodo f8996d6
fix: drop the -- that pnpm forwards to the installer and dev-stack.sh
gabitoesmiapodo 190b0d4
chore: run the installer and script tests in the pre-commit hook
gabitoesmiapodo dd7afeb
docs: require pre-commit entries for every new workspace package
gabitoesmiapodo f90109d
fix(canton-create): run the scaffold scripts from a symlinked or spac…
gabitoesmiapodo 08e8c17
fix(canton-create): say why dpm build failed in build-dar.mjs
gabitoesmiapodo 9bec3af
docs: point the root README at create-canton-dappbooster
gabitoesmiapodo d6c4618
docs(canton-create): show the preselect commands for npm and pnpm
gabitoesmiapodo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| // The writing half of the pre-commit, kept apart so the read-only gates in .lintstagedrc.mjs can | ||
| // run concurrently behind it. See .husky/pre-commit. | ||
| export default { | ||
| '{canton-connect,canton-dappbooster,canton-theme,dapp/frontend,kit,scripts}/**/*.{ts,tsx,js,jsx,json,jsonc,mjs,cjs,css}': | ||
| '{canton-connect,canton-dappbooster,canton-theme,example-dapps,scripts,canton-create}/**/*.{ts,tsx,js,jsx,json,jsonc,mjs,cjs,css}': | ||
| 'biome check --write --no-errors-on-unmatched', | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,15 @@ | ||
| // Read-only gates only. The formatter runs first, from .lintstagedrc.format.mjs, so these are safe | ||
| // to run concurrently with each other. | ||
| export default { | ||
| 'canton-connect/src/**/*.{ts,tsx,js,jsx}': () => 'pnpm -C canton-connect test', | ||
| 'canton-dappbooster/src/**/*.{ts,tsx,js,jsx}': () => 'pnpm -C canton-dappbooster test', | ||
| 'dapp/frontend/src/**/*.{ts,tsx,js,jsx}': () => 'pnpm -C dapp/frontend test', | ||
| // One task for the whole doc gate, under the name CI uses: typedoc resolves both packages in a | ||
| // single run anyway, so splitting it per package bought a second and two ways to drift. | ||
| // Snippets live in the READMEs as well as in the doc blocks, so a doc edit re-runs the compile. | ||
| 'example-dapps/*/src/**/*.{ts,tsx,js,jsx}': (files) => | ||
| [...new Set(files.map((file) => file.match(/example-dapps\/[^/]+/)?.[0]))].map( | ||
| (example) => `pnpm -C ${example} test`, | ||
| ), | ||
| 'canton-create/**/*.{ts,tsx,mjs,sh,json}': () => 'pnpm -C canton-create test', | ||
| '{canton-create/scaffold/*/scripts,scripts}/*.{mjs,sh}': () => | ||
| 'node --test "canton-create/scaffold/*/scripts/*.test.mjs" "scripts/*.test.mjs"', | ||
| '{canton-connect,canton-dappbooster}/{src/**/*.{ts,tsx},doc-fixtures.d.ts,README.md,architecture.md,coming-from-wagmi.md,typedoc.json}': | ||
| () => 'pnpm docs:check', | ||
| // Either side of the L2/L3 contract moving on its own is what this catches. | ||
| '{canton-dappbooster/src/{components,providers}/**/anatomy.ts,canton-theme/src/**/*.css}': () => | ||
| 'pnpm run check:anatomy', | ||
| } | ||
Large diffs are not rendered by default.
Oops, something went wrong.
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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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
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
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
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
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
File renamed without changes.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| # Agent configuration: `canton-create` | ||
|
|
||
| This file applies only to `canton-create/`, the `create-canton-dappbooster` package. For | ||
| monorepo-wide rules see [`../CLAUDE.md`](../CLAUDE.md). For how a run and the scaffold layers fit | ||
| together, see [`architecture.md`](architecture.md). | ||
|
|
||
| ## Every option is a flag | ||
|
|
||
| - An agent runs the installer without a terminal, so it can only pass flags. Every question the | ||
| wizard asks gets a flag in the same change. The `USAGE` text in `src/index.tsx` and the flag table | ||
| in the README both list it. | ||
| - Without a terminal the installer asks nothing, so every question also needs a default. | ||
| - A flag that would only repeat a default does not exist, so there is no `--app` and no `--yes`. | ||
|
|
||
| ## Scaffold rules | ||
|
|
||
| - Each app owns its contract. `scaffold/daml-tooling/` holds no Daml, only the scripts that build | ||
| and deploy whatever `daml/daml.yaml` the app carries. | ||
| - A layer may add files and merge `scripts`, `dependencies` and `devDependencies` into the app's | ||
| manifest. It never redefines a key an earlier layer set. `scaffold` appends to `.gitignore` and | ||
| `README.md`, and merges `.env.example` by key, leaving out a block whose keys the file already | ||
| sets. Any other overwrite is a design error in `scaffold/`, and `scaffold` throws | ||
| `ScaffoldConflictError`. So does any other field in a layer's `package.json`, apart from the | ||
| layer's own `name`, `private`, `version` and `type`, because the merge would drop it. | ||
| - A layer's `README.md` is a section that gets appended, so it starts with a `##` heading and never | ||
| with a title. | ||
| - The root range rule has no exception in `scaffold/`: the tarball ships the folders as they are, so | ||
| nothing rewrites a `workspace:` range on the way out. | ||
| - A file that has to land as `.gitignore` or `pnpm-workspace.yaml` lives here as `_gitignore` or | ||
| `_pnpm-workspace.yaml`, and `scaffold` renames it back. npm drops a `.gitignore` from every | ||
| tarball, and a `pnpm-workspace.yaml` inside the monorepo makes pnpm treat the folder as a | ||
| workspace root of its own. | ||
| - The monorepo runs the `daml-tooling/` and `localnet/` scripts on `example-dapps/amulet-vesting` | ||
| instead of keeping copies. Each script finds the app's `daml/` and `.env` through | ||
| `CANTON_APP_DIR`, which defaults to its own project. A new script reads the app from there, never | ||
| from a path to its own folder. Their tests sit beside them, and `files` keeps the tests out | ||
| of the tarball. | ||
| - `node dist/index.js` run from this folder is not a test of the installer. Here `scaffold/` holds | ||
| `node_modules` and build output that `files` leaves out of the tarball, and the copy fails on | ||
| them. Run the packed package instead: `pnpm try`, or `src/testing/packedScaffold.ts` in a test. | ||
|
|
||
| ## Examples | ||
|
|
||
| An example is a complete app published on its own as `@bootnodedev/canton-example-<name>`, and the | ||
| installer never ships one inside its tarball. Adding one takes: | ||
|
|
||
| - the app in `example-dapps/<name>/`, with a `files` list naming what it publishes and | ||
| `publishConfig.access: "public"` | ||
| - its name, label and hint in `EXAMPLES` in `src/apps.ts` | ||
|
|
||
| `pnpm-workspace.yaml` already lists `example-dapps/*`. So the root `release` script publishes every | ||
| folder there, and the version bump and `check:versions` cover it too. | ||
|
|
||
| ## Dependencies | ||
|
|
||
| `tsdown` bundles Ink, React and every other import into `dist/index.js`, so the published package | ||
| has no dependencies to install. A new import goes in `devDependencies` for the same reason. | ||
| `react-devtools-core` is the one import left out of the bundle, because Ink only loads it when | ||
| `DEV=true`. | ||
|
|
||
| ## Demo recording | ||
|
|
||
| `demo.svg` in the README is an animated SVG of a real run. Record it again after any change to the | ||
| terminal UI: | ||
|
|
||
| ```shell | ||
| canton-create/scripts/record-demo.ts | ||
| ``` | ||
|
|
||
| The script packs the installer, runs it in a temporary directory, and overwrites `demo.svg`. The | ||
| install it starts needs network. Its comments explain the trimming and the frame merging. | ||
|
|
||
| - It runs on Bun, because it needs a pseudo-terminal. Node has none without `node-pty`, a native | ||
| module, and `Bun.spawn` opens one through its `terminal` option. | ||
| - [svg-term-cli](https://github.com/marionebl/svg-term-cli) does the conversion, through `pnpm dlx`. | ||
| It is not a dependency. `COLS` and `ROWS` set the window, so a change to either means changing | ||
| the size of the `<img>` in the README too. | ||
|
|
||
| ## Testing | ||
|
|
||
| `pnpm test` runs `vitest`, and the component tests render through `ink-testing-library`. It can drop | ||
| a key sent before the input handler mounts, so `src/components/App.test.tsx` sends each key through | ||
| `pressUntil`. The test then checks all the frames joined, because the last frame can be empty | ||
| once the app exits. |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.