create-feltkit 0.3.12 → 0.3.13
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.
- package/README.md +4 -3
- package/package.json +4 -3
- package/template/README.md +21 -6
- package/template/feltkit/app.ts +2 -1
- package/template/feltkit/tasks.ts +4 -3
- package/template/package.json +1 -1
- package/template-managed/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://
|
|
4
|
-
<img src="https://
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/npm/@feltdb/feltkit/docs/assets/feltkit-logo-dark.png">
|
|
4
|
+
<img src="https://cdn.jsdelivr.net/npm/@feltdb/feltkit/docs/assets/feltkit-logo.png" alt="FeltKit" width="160">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -29,4 +29,5 @@ npm run managed:setup
|
|
|
29
29
|
|
|
30
30
|
The managed starter's README walks through setup, deployment and verification.
|
|
31
31
|
|
|
32
|
-
Documentation:
|
|
32
|
+
Documentation: shipped with the package. In a project, run `npx feltkit docs` (or read
|
|
33
|
+
`node_modules/@feltdb/feltkit/docs/`); online: <https://cdn.jsdelivr.net/npm/@feltdb/feltkit/docs/README.md>.
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-feltkit",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"description": "Create a FeltKit application: npm create feltkit@latest my-app (add -- --template managed for Managed FeltDB)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/rkendel1/
|
|
9
|
+
"url": "git+https://github.com/rkendel1/feltkit.git",
|
|
10
10
|
"directory": "packages/create"
|
|
11
11
|
},
|
|
12
12
|
"engines": {
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"build": "node sync-template.mjs",
|
|
34
34
|
"prepack": "node sync-template.mjs",
|
|
35
35
|
"test": "node --test test/*.test.mjs"
|
|
36
|
-
}
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://www.npmjs.com/package/create-feltkit"
|
|
37
38
|
}
|
package/template/README.md
CHANGED
|
@@ -92,13 +92,21 @@ Configure each one in **Studio → Services**: every service has its own screen,
|
|
|
92
92
|
operation there is authorized as the dev user you choose with **Act as**. From a function:
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
|
+
// Effects that announce this mutation's change: performed only if it commits (mutations only).
|
|
96
|
+
ctx.afterCommit.webhooks.emit("task.created", { id });
|
|
97
|
+
ctx.afterCommit.notifications.send({ recipient: "grace", type: "task.completed", title: "Done" });
|
|
98
|
+
ctx.afterCommit.jobs.enqueue("projects.clear-completed", {});
|
|
99
|
+
// Reads and stored files, right away:
|
|
95
100
|
await ctx.services.files.upload({ name: "notes.txt", content: text });
|
|
96
|
-
await ctx.services.notifications.send({ recipient: "grace", type: "task.completed", title: "Done" });
|
|
97
|
-
await ctx.services.webhooks?.emit("task.created", { id }); // mutations only
|
|
98
|
-
await ctx.services.jobs?.enqueue("projects.clear-completed", {}); // mutations only
|
|
99
101
|
const greeting = await ctx.services.configuration.get("GREETING");
|
|
100
102
|
```
|
|
101
103
|
|
|
104
|
+
Use `ctx.afterCommit` for anything that tells the world about the mutation's change. The same
|
|
105
|
+
calls on `ctx.services` (`ctx.services.webhooks.emit`, `…notifications.send`, `…jobs.enqueue`)
|
|
106
|
+
happen immediately and stay done even if the mutation then fails (a `CONFLICT` at commit), so
|
|
107
|
+
receivers would hear about a change that never happened. `npx feltkit outbox list` shows every
|
|
108
|
+
after-commit effect and its state.
|
|
109
|
+
|
|
102
110
|
The starter already uses them: creating and completing a task emits `task.created` and
|
|
103
111
|
`task.completed` to any registered webhook endpoint; completing someone else's task notifies
|
|
104
112
|
its creator; and the job `projects.clear-completed` runs `projects:clearCompleted`.
|
|
@@ -121,8 +129,12 @@ service off, remove it from `services`.
|
|
|
121
129
|
|
|
122
130
|
**Studio → Integrations → Connect an API** reads an OpenAPI document (JSON) or lets you
|
|
123
131
|
describe the operations yourself, then writes `feltkit/<name>.ts` and grants `<name>.*` to the
|
|
124
|
-
roles you choose. Each operation becomes
|
|
125
|
-
|
|
132
|
+
roles you choose. Each operation becomes an AppPort capability (`<name>.<operation>`) with its
|
|
133
|
+
permission, and every call is recorded. It is called through AppPort, not from a query or
|
|
134
|
+
mutation: by the agent (MCP tools, proposals), by other apps and scripts (`POST /appport`), and by
|
|
135
|
+
your frontend with an AppPort request carrying the session token. To act on the result inside
|
|
136
|
+
your app, name a mutation in the operation's `onOutcome`: it runs as the caller with the call's
|
|
137
|
+
record when the call finishes (success or failure). The API key is
|
|
126
138
|
stored in FeltKit's custody; in production set `<NAME>_URL` and `FELTKIT_CREDENTIAL_<NAME>`.
|
|
127
139
|
Then narrow each operation's `output` schema in that file to what the API returns.
|
|
128
140
|
|
|
@@ -360,4 +372,7 @@ operate this app.
|
|
|
360
372
|
- Errors carry a code (`FORBIDDEN`, `INVALID_ARGUMENT`, `NOT_FOUND`, …) and usually a hint with
|
|
361
373
|
the fix.
|
|
362
374
|
|
|
363
|
-
FeltKit documentation:
|
|
375
|
+
FeltKit documentation ships with the package: `npx feltkit docs` lists it (guarantees, transactions,
|
|
376
|
+
security, agents, path to production, backup) and `npx feltkit docs <name>` prints one. The same files
|
|
377
|
+
are in `node_modules/@feltdb/feltkit/docs/`, and online at
|
|
378
|
+
<https://cdn.jsdelivr.net/npm/@feltdb/feltkit/docs/README.md>.
|
package/template/feltkit/app.ts
CHANGED
|
@@ -19,7 +19,8 @@ export const app = feltkit({
|
|
|
19
19
|
// Viewers read. They can see agent tasks but not start or approve them.
|
|
20
20
|
viewer: ["projects.read", "tasks.read", "files.read", "notifications.read", "feltkit.agent.read"],
|
|
21
21
|
// Agents can read, complete tasks, and leave notes. They cannot create or delete.
|
|
22
|
-
|
|
22
|
+
// feltkit.agent.*: discover the app (feltkit_context), work tasks, propose actions; a person approves.
|
|
23
|
+
agent: ["projects.read", "tasks.read", "tasks.complete", "tasks.note", "files.read", "files.write", "notifications.send", "webhooks.emit", "webhooks.deliver", "feltkit.agent.*"],
|
|
23
24
|
// Admins configure the app in Studio → Services: the model (intelligence.*), stored
|
|
24
25
|
// credentials (credential.*), configuration, API keys, webhooks, jobs, and schedules.
|
|
25
26
|
// Credentials are stored by reference; the value never enters FeltDB.
|
|
@@ -42,7 +42,8 @@ export const create = app.mutation({
|
|
|
42
42
|
createdBy: ctx.auth.requirePrincipal().id,
|
|
43
43
|
});
|
|
44
44
|
// Delivered, signed, to every webhook endpoint registered for "task.created" (Studio → Services → Webhooks).
|
|
45
|
-
|
|
45
|
+
// ctx.afterCommit: only if this mutation commits (ctx.services.* effects happen even if it does not).
|
|
46
|
+
ctx.afterCommit.webhooks.emit("task.created", { id, projectId, title: title.trim() });
|
|
46
47
|
return id;
|
|
47
48
|
},
|
|
48
49
|
});
|
|
@@ -67,10 +68,10 @@ export const setDone = app.mutation({
|
|
|
67
68
|
const who = ctx.auth.requirePrincipal().id;
|
|
68
69
|
const task = await ctx.db.patch(tasks, id, done ? { done: true, completedAt: Date.now(), completedBy: who } : { done: false, completedAt: undefined, completedBy: undefined });
|
|
69
70
|
if (done) {
|
|
70
|
-
|
|
71
|
+
ctx.afterCommit.webhooks.emit("task.completed", { id: task.id, projectId: task.projectId, completedBy: who });
|
|
71
72
|
// Tell whoever created the task, when someone else completes it.
|
|
72
73
|
if (task.createdBy !== who) {
|
|
73
|
-
|
|
74
|
+
ctx.afterCommit.notifications.send({ recipient: task.createdBy, type: "task.completed", title: `${who} completed "${task.title}"`, data: { taskId: task.id }, idempotencyKey: `task.completed:${task.id}:${task.completedAt}` });
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
return { id: task.id, done: task.done };
|
package/template/package.json
CHANGED
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"deploy:fly": "node scripts/deploy-fly.mjs"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@feltdb/feltkit": "0.3.
|
|
23
|
+
"@feltdb/feltkit": "0.3.13"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@feltdb/core": ">=0.
|
|
26
|
+
"@feltdb/core": ">=0.21.0 <1.0.0",
|
|
27
27
|
"@types/node": "22.19.1",
|
|
28
28
|
"typescript": "5.9.3"
|
|
29
29
|
}
|