Skip to content

Cell ​

尚未翻译

本页目前只有英文版,下面是英文原文。

This project uses Cell 4.1.0: TypeScript with dependency injection, MVC controllers on Express, and the cell toolchain (Vite). This guide matches the installed version; npx cell agent sync rewrites it after an upgrade.

Layout ​

  • src/node/ is the backend, src/browser/ the frontend, src/common/ code for both. src/<node|browser>/module.ts is the DI module of its side: it imports every file that has components and ends with export default autoBind();. A file it does not import is not loaded.
  • cell.yml holds the application configuration, with backend: and frontend: sections; cell.<mode>.yml adds to it per mode (development in cell dev, production in cell build, test in tests, more with -m <mode>).
  • cell.config.ts (optional) configures the toolchain only: preset, modules, build, vite, hooks. Application configuration never goes there.

Writing code ​

  • Services: @Component() on the class, @Autowired(Type) on a property to inject. For an interface, export a Symbol with the same name and bind the class with @Component(Symbol).
  • Configuration: @Value('cell.key') reads cell.yml. ${env.NAME ?: 'default'} in values is evaluated at startup (quote such values in YAML). CELL_BACKEND__SERVER__PORT=8080 overrides cell.server.port of an existing key.
  • HTTP: @Controller('path') with @Get(), @Post(), @Put(':id'), @Delete(':id') from @celljs/mvc/lib/node; parameters @Param('id'), @Query('q'), @Body(). Returned objects are JSON; add @Text() for text. To validate a body, type the @Body() parameter with a class that has class-validator decorators: invalid bodies get 400.
  • Frontend and backend: @Rpc(Symbol) on the backend class, RpcUtil.get<T>(Symbol) (@celljs/rpc/lib/common) in the frontend.

Verify ​

  • npx cell check --json checks types, configuration, decorator settings and DI bindings. Every issue has code, file, line and a hint. Run it after each change.

  • Tests run with bun test; createTestApp() from @celljs/cli starts the application in the test process:

    ts
    const app = await createTestApp({ root: join(__dirname, '..') });
    const res = await app.fetch('/todos', { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{}' });
    const service = app.get(TodoService);
    await app.close();
  • npx cell dev runs the application and reloads it on save; npx cell build builds into .cell/output (--single: one file, --compile: one executable); npx cell preview runs the build.

  • npx cell deploy --preset <cloudflare|fc|scf|lambda|vercel> --dry-run builds and shows what a deployment would change, without credentials. Platform options go in cell.config.ts under the preset's name (fc: { region: 'cn-shanghai' }); credentials come from environment variables. Leave the real cell deploy to the user unless asked.

Find out ​

  • npx cell info --json: components, DI modules, entries, preset, hooks, output.
  • npx cell config get <key> --why: a merged configuration value and the files and variables that set it.
  • npx cell docs <words>: the docs of the installed Cell packages.
  • npx cell mcp serves these as MCP tools. While cell dev runs, http://127.0.0.1:<port>/_cell/mcp has get_errors, list_routes, list_bindings, get_config, recent_requests and logs of the running application.
  • Errors read [CELL_CODE] message, then fix: and a docs link: do what the fix says.