@celsoft/platform 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
1
  export declare const GENERATED_DIR = ".platform";
2
2
  export declare const generatedPath: (appDir: string, file: string) => string;
3
3
  export declare function generate(appDir: string): Promise<string[]>;
4
+ export declare const AGENTS_BLOCK = "<!-- @celsoft/platform:start -->\n## @celsoft/platform\n\nThis app is built on @celsoft/platform. Before changing it, read the skills the installed version\nships, starting with `node_modules/@celsoft/platform/skills/celsoft-platform/SKILL.md`; every\nskill is a `SKILL.md` under `node_modules/@celsoft/platform/skills/`. They match the installed\nversion, so read them again after an upgrade. This block is rewritten on install; edit outside it.\n<!-- @celsoft/platform:end -->";
5
+ export declare function writeAgentsBlock(appDir: string): Promise<boolean>;
package/dist/generate.js CHANGED
@@ -29,7 +29,35 @@ export async function generate(appDir) {
29
29
  ].join("\n");
30
30
  const file = generatedPath(appDir, "client.ts");
31
31
  await writeFile(file, client);
32
- return [relative(appDir, file)];
32
+ return [relative(appDir, file), ...((await writeAgentsBlock(appDir)) ? ["AGENTS.md"] : [])];
33
+ }
34
+ const BLOCK_START = "<!-- @celsoft/platform:start -->";
35
+ const BLOCK_END = "<!-- @celsoft/platform:end -->";
36
+ // Points the app's agents at the skills the installed package ships, read from node_modules, so
37
+ // they always match the installed version. Only this block of AGENTS.md is the platform's.
38
+ export const AGENTS_BLOCK = `${BLOCK_START}
39
+ ## @celsoft/platform
40
+
41
+ This app is built on @celsoft/platform. Before changing it, read the skills the installed version
42
+ ships, starting with \`node_modules/@celsoft/platform/skills/celsoft-platform/SKILL.md\`; every
43
+ skill is a \`SKILL.md\` under \`node_modules/@celsoft/platform/skills/\`. They match the installed
44
+ version, so read them again after an upgrade. This block is rewritten on install; edit outside it.
45
+ ${BLOCK_END}`;
46
+ // True when AGENTS.md changed.
47
+ export async function writeAgentsBlock(appDir) {
48
+ const file = join(appDir, "AGENTS.md");
49
+ const text = await readFile(file, "utf8").catch(() => "");
50
+ const start = text.indexOf(BLOCK_START);
51
+ const end = text.indexOf(BLOCK_END);
52
+ const next = start >= 0 && end > start
53
+ ? text.slice(0, start) + AGENTS_BLOCK + text.slice(end + BLOCK_END.length)
54
+ : text
55
+ ? `${text.replace(/\n*$/, "")}\n\n${AGENTS_BLOCK}\n`
56
+ : `${AGENTS_BLOCK}\n`;
57
+ if (next === text)
58
+ return false;
59
+ await writeFile(file, next);
60
+ return true;
33
61
  }
34
62
  // Bundles the Worker for Node with its packages left as imports, then reads the endpoints its
35
63
  // default export declares; nothing it would do on a request runs.
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celsoft/platform",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Deploy apps to Cloudflare Workers with Neon Postgres, prod on push and a preview per pull request",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,7 +25,8 @@
25
25
  },
26
26
  "files": [
27
27
  "dist",
28
- "schema.json"
28
+ "schema.json",
29
+ "skills"
29
30
  ],
30
31
  "scripts": {
31
32
  "prepare": "tsc -b && node dist/write-schema.js"
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: celsoft-platform
3
+ description: "MUST READ before changing an app built on @celsoft/platform: its endpoints, tables and migrations, pages, auth, files, email, live rooms, MCP tools, platform.jsonc, deploys or previews. Matches the installed version of the package."
4
+ ---
5
+
6
+ # Working on a @celsoft/platform app
7
+
8
+ The app runs on Cloudflare Workers with a Neon Postgres database. The platform owns the Worker,
9
+ the cloud resources and the deploys; the app writes its endpoints, tables and pages. Run every
10
+ command as `npx @celsoft/platform <command>` from the app's folder.
11
+
12
+ ## Files
13
+
14
+ | File | Who writes it | Rule |
15
+ | --- | --- | --- |
16
+ | `platform.jsonc` | The app | What the app turns on; validated on every run |
17
+ | `src/worker.ts` | The app | `export default defineApp(handler, { schema, endpoints, live })` |
18
+ | `src/schema.ts` | The app | Drizzle tables; `id()` and `timestamps()` from `@celsoft/platform/schema` |
19
+ | Frontend (`frontend` in `platform.jsonc`) | The app | Static files, or a `build` script's output |
20
+ | `drizzle/` | `db generate` | Commit; never edit |
21
+ | `.github/workflows/platform.yml` | `init` | Commit; never edit |
22
+ | `.platform/` | The platform | Gitignored; regenerated on install, `dev` and deploy; never edit |
23
+
24
+ ## Endpoints
25
+
26
+ Every type is a Zod schema. Declare each API or MCP function in `defineApp`'s `endpoints`:
27
+
28
+ ```ts
29
+ import { defineApp, endpoint, EndpointError } from "@celsoft/platform";
30
+ import { z } from "zod";
31
+
32
+ export default defineApp(undefined, {
33
+ schema,
34
+ endpoints: {
35
+ getNote: endpoint(
36
+ {
37
+ serve: ["api", "mcp"], // the API by default; "mcp" makes it an MCP tool
38
+ method: "GET",
39
+ path: "/api/notes/:id", // under /api/; :name must be an input field
40
+ description: "Read one note", // the MCP tool's description
41
+ input: z.object({ id: z.uuid() }),
42
+ output: z.object({ id: z.uuid(), body: z.string() }),
43
+ },
44
+ async ({ id }, app) => {
45
+ const user = await app.requireUser();
46
+ const [note] = await app.db.select().from(notes).where(and(eq(notes.id, id), eq(notes.userId, user.id)));
47
+ if (!note) throw new EndpointError(404, "not found");
48
+ return note;
49
+ },
50
+ ),
51
+ },
52
+ });
53
+ ```
54
+
55
+ 1. **Inputs:** path parameters, the query and a JSON body merge into one input object; URL strings are converted to the schema's types.
56
+ 2. **Checks:** bad input is a 400; an output that does not match its schema is a 500, logged.
57
+ 3. **Errors:** throw `EndpointError(status, message)`; a thrown `Response`, as `requireUser()` throws, keeps its status.
58
+ 4. **Access:** every `/api/` path needs a signed-in user except under `/api/public/`; MCP calls always carry one.
59
+ 5. **Frontend calls:** a bundled frontend imports `call` from `.platform/client` and calls `call("getNote", { id })`, typed from the endpoints.
60
+ 6. **Hand-written routes:** the `handler` (first argument, or `undefined`) takes every request no endpoint answers, for uploads, downloads and streaming.
61
+
62
+ ## `app`
63
+
64
+ Each request gets `app`: `db` (Drizzle, typed with `schema`), `auth`, `session()`, `requireUser()`,
65
+ `files` (R2, folders), `email` (`app.email.send(...)`), `live` (`app.live.publish(room, message)`),
66
+ `env` and `waitUntil`. Each is created on first use.
67
+
68
+ ## Tables and migrations
69
+
70
+ 1. **Change** `src/schema.ts`, then run `npx @celsoft/platform db generate`; read and commit the SQL in `drizzle/`.
71
+ 2. **Deploy** applies new migrations; it stops before any change when the schema has changes with no generated migration.
72
+ 3. **Auth tables** come from the platform; reference users with `user.id` from `@celsoft/platform/schema`.
73
+ 4. **Ids** are `uuid` filled by Postgres's `uuidv7()`; never supply them.
74
+
75
+ ## Features in `platform.jsonc`
76
+
77
+ 1. **`database`:** a Neon project id; prod, each preview and `dev` get their own branch.
78
+ 2. **`email`:** sending from `noreply@<hostname>` through Resend; previews and `dev` capture email instead of sending.
79
+ 3. **`auth`:** sign-up and sign-in at `/login`, `/signup`, `/forgot`, `/reset`; `{ "organizations": true }` adds teams. Needs `database` and `email`.
80
+ 4. **`files`:** `app.files` in an R2 bucket; previews share one bucket under their PR's folder.
81
+ 5. **`live`:** rooms over WebSockets; `live: { message: schema, canJoin, canSend, onMessage }` in `defineApp`; browsers use `live()` from `@celsoft/platform/live`. Joining and sending are refused unless `canJoin` and `canSend` say yes.
82
+ 6. **`mcp`:** serves endpoints with `serve` including `"mcp"` at `/mcp` to AI clients that sign in with OAuth. Needs `auth`.
83
+
84
+ ## Commands
85
+
86
+ | Command | What it does |
87
+ | --- | --- |
88
+ | `dev` | Runs the app locally on its own `dev` database branch; starts the `dev` script beside it, with `plugins: [platform()]` from `@celsoft/platform/vite` |
89
+ | `db generate` | Writes migrations for schema changes |
90
+ | `generate` | Rewrites `.platform/`; also runs on install |
91
+ | `deploy` / `preview <pr>` | Deploy prod or a PR's preview; CI runs these on push and on pull requests |
92
+ | `previews` | Lists the previews that exist |
93
+ | `owner reset <email>` | Makes that account the owner and sets its password |
94
+ | `--dry-run` | On any command, shows what would change |
95
+
96
+ ## Rules
97
+
98
+ 1. **Never edit generated files:** `drizzle/`, the workflow and `.platform/`; regenerate them instead.
99
+ 2. **Never read or print** `.env.secrets`; it holds the deploy tokens.
100
+ 3. **Resource names are reserved:** anything in the Cloudflare account named after the app, or the app followed by `--`, belongs to the platform.
101
+ 4. **Failures stop the run:** a failed build, migration or check leaves the running version in place; fix the cause rather than working around it.