跳到主要内容

快速入门

快速入门

几分钟内你就会得到一个小而完整的工作区:一个模型、它的集合,以及一个带一个页面的应用,并完成检查与构建。同一份源码可以用 bolt dev 在本地运行,用 bolt start 在你自己的服务器上运行,也可以在 Colony 的工作区工作室中运行。

tasks/
├── package.json
├── tsconfig.json
└── src/
    ├── +workspace.ts
    ├── data/
    │   ├── model/+tasks.model.ts
    │   └── collection/tasks/+collection.ts
    └── app/tasks/
        ├── +app.ts
        └── +board.page.svelte

1. 创建包

{
  "name": "tasks",
  "private": true,
  "type": "module",
  "scripts": { "check": "bolt check", "build": "bolt build", "dev": "bolt dev", "test": "bolt test" },
  "dependencies": {
    "@norbital-ai/bolt": "0.0.1",
    "@norbital-ai/ui": "0.0.1",
    "effect": "4.0.0-rc.112",
    "svelte": "^5.57.1",
    "vite": "^8.2.2"
  },
  "devDependencies": {
    "@norbital-ai/bolt-server": "0.0.1",
    "@effect/vitest": "4.0.0-rc.112",
    "@sveltejs/vite-plugin-svelte": "^7.3.1",
    "svelte-check": "^4.7.6",
    "typescript": "6.0.3",
    "vitest": "4.1.11"
  }
}
{ "extends": "./.norbital/tsconfig.json" }

工作区是一个依赖 @norbital-ai/bolt 与 @norbital-ai/ui 的包。它的 tsconfig.json 继承生成的 .norbital/tsconfig.json。没有 vite.config.ts,也没有 SvelteKit 配置:构建由编译器负责。

2. 声明工作区

// src/+workspace.ts
import { workspace } from '@norbital-ai/bolt';

export default workspace({ tz: 'Asia/Singapore', locale: 'en-SG', apps: ['tasks'] });

src/+workspace.ts 是唯一必需的文件。它设定所有日期与数字所使用的时区和区域设置,以及应用在启动器中的顺序。

3. 定义模型

// src/data/model/+tasks.model.ts
import { model } from '@norbital-ai/bolt';

export default model({
  description: 'Work the team has to do.',
  icon: 'lucide:list-todo',
  label: 'title',
  fields: {
    title: { kind: 'text' },
    status: {
      kind: 'state',
      initial: 'open',
      states: { open: { to: ['done'] }, done: { to: ['open'], edit: 'none' } }
    },
    due_on: { kind: 'date', optional: true }
  },
  search: { text: ['title'] }
});

模型就是存储。文件夹名 tasks 就是模型名;fields 是带类型的字面量,label 是记录标题,而 state 字段是唯一的锁:每个状态列出它可以转到哪里,以及处于该状态时还能编辑什么。

4. 以集合公开它

// src/data/collection/tasks/+collection.ts
import { collection } from '@norbital-ai/bolt';

export default collection('tasks', {
  read: { fields: 'all' },
  create: { input: { columns: ['title', 'due_on'] } },
  update: { input: { columns: ['title', 'status', 'due_on'] } },
  delete: {}
});

没有集合的模型对外不可见。集合规定任何调用方最多能读取什么(read.fields),以及创建与更新接受哪些字段。声明 delete 即公开删除;未声明的操作就不存在。

5. 添加应用与页面

// src/app/tasks/+app.ts
import { app } from '@norbital-ai/bolt';

export default app('tasks', {
  title: 'Tasks',
  description: 'Everything the team is working on.',
  icon: 'lucide:list-todo',
  pages: { board: { title: 'Board', icon: 'lucide:kanban' } }
});

+app.ts 为应用命名,并按导航顺序列出它的页面;文件夹中的每个 +<page>.page.svelte 都需要一个条目。这里的标题是字面量;一旦工作区有了 src/i18n/,它们就改为消息目录键。

<!-- src/app/tasks/+board.page.svelte -->
<script lang="ts">
  import { Board } from '@norbital-ai/ui';
  import { AppShell } from '@norbital-ai/ui/layout';
</script>

<AppShell icon="lucide:list-todo" title="Tasks" description="Everything the team is working on.">
  <Board of="tasks" by="status" card={['title', 'due_on']} />
</AppShell>

页面就是一个 Svelte 组件。Board of="tasks" 实时读取该集合,按状态字段分组,并提供“新建”以及每位查看者可执行的状态转移。

6. 检查、运行与构建

pnpm install
pnpm exec bolt check   # layout, names, schema, tsc, svelte-check and doctor, every error at once
pnpm exec bolt dev     # the workspace on a local PGlite, reloading on save
pnpm exec bolt build   # .norbital/artifact/: the one artifact every host runs

bolt check 运行每一个阶段——布局、名称、打包、数据库结构、tsc、svelte-check 与 doctor——并一次报告所有错误;没有警告。bolt dev 在本地 PGlite 数据库上运行工作区,并在保存时重新加载。bolt build 写出所有宿主都运行的制品。

谁能看到它
创建工作区的成员是管理员,不受授权限制。其他人只有在其某个策略的 capabilities.apps 中列出该应用时才能看到它,并且只能通过授权访问集合:参见策略。

下一步

你现在拥有了一个可构建的工作区。从这里开始: