@ekairos/domain 1.22.34-beta.development.0 → 1.22.35
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 +260 -106
- package/SKILL.md +56 -0
- package/dist/cli/bin.d.ts +9 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +609 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/client-runtime.d.ts +25 -0
- package/dist/cli/client-runtime.d.ts.map +1 -0
- package/dist/cli/client-runtime.js +60 -0
- package/dist/cli/client-runtime.js.map +1 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +44 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/create-app.d.ts +66 -0
- package/dist/cli/create-app.d.ts.map +1 -0
- package/dist/cli/create-app.js +2948 -0
- package/dist/cli/create-app.js.map +1 -0
- package/dist/cli/http.d.ts +28 -0
- package/dist/cli/http.d.ts.map +1 -0
- package/dist/cli/http.js +113 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/server.d.ts +3 -0
- package/dist/cli/server.d.ts.map +1 -0
- package/dist/cli/server.js +440 -0
- package/dist/cli/server.js.map +1 -0
- package/dist/cli/types.d.ts +61 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/ui.d.ts +3 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +138 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/context.test-runner.js +3 -1
- package/dist/context.test-runner.js.map +1 -1
- package/dist/domain-doc.d.ts +2 -0
- package/dist/domain-doc.d.ts.map +1 -1
- package/dist/domain-doc.js +14 -0
- package/dist/domain-doc.js.map +1 -1
- package/dist/index.d.ts +228 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +397 -118
- package/dist/index.js.map +1 -1
- package/dist/next.d.ts +21 -21
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +213 -345
- package/dist/next.js.map +1 -1
- package/dist/polyfills/dom-events.d.ts +2 -0
- package/dist/polyfills/dom-events.d.ts.map +1 -0
- package/dist/polyfills/dom-events.js +92 -0
- package/dist/polyfills/dom-events.js.map +1 -0
- package/dist/runtime-handle.d.ts +45 -0
- package/dist/runtime-handle.d.ts.map +1 -0
- package/dist/runtime-handle.js +84 -0
- package/dist/runtime-handle.js.map +1 -0
- package/dist/runtime-step.d.ts.map +1 -1
- package/dist/runtime-step.js +2 -0
- package/dist/runtime-step.js.map +1 -1
- package/dist/runtime.d.ts +9 -8
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +80 -24
- package/dist/runtime.js.map +1 -1
- package/package.json +44 -7
package/README.md
CHANGED
|
@@ -1,173 +1,327 @@
|
|
|
1
1
|
# @ekairos/domain
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Build one app graph from many bounded contexts.
|
|
4
|
+
Read it through InstantDB.
|
|
5
|
+
Write through step-safe domain actions.
|
|
6
|
+
Operate it through a CLI.
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
## What you get
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
- Composed domain graphs with `domain(...).withSchema(...)`
|
|
11
|
+
- Explicit runtimes with `EkairosRuntime`
|
|
12
|
+
- Step-safe write boundaries with `defineAction(...)`
|
|
13
|
+
- Workflow-ready action execution with `executeRuntimeAction(...)`
|
|
14
|
+
- A companion CLI through `@ekairos/cli` for `create-app`, `inspect`, `action`, and `query`
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
- Runtime resolution.
|
|
12
|
-
- Typed domain actions.
|
|
13
|
-
- AI-ready domain context.
|
|
16
|
+
## Start Fast
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Scaffold a Next app that already exposes the Ekairos domain endpoint:
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
```bash
|
|
21
|
+
ekairos create-app my-app --next
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Run the full supply-chain demo cycle:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ekairos create-app --demo
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If you already have an Instant platform token, provision the app and write `.env.local` in one pass:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ekairos create-app my-app --next --instantToken=$INSTANT_PERSONAL_ACCESS_TOKEN
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then run it and inspect it:
|
|
18
37
|
|
|
19
38
|
```bash
|
|
20
|
-
|
|
21
|
-
|
|
39
|
+
ekairos domain inspect --baseUrl=http://localhost:3000 --admin --pretty
|
|
40
|
+
ekairos domain "supplyChain.order.launch" "{ reference: 'PO-7842', supplierName: 'Marula Components', sku: 'DRV-2048' }" --baseUrl=http://localhost:3000 --admin --pretty
|
|
41
|
+
ekairos domain query "{ procurement_order: { supplier: {}, stockItems: {}, shipments: { inspections: {} } } }" --baseUrl=http://localhost:3000 --admin --pretty
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Next.js Route
|
|
45
|
+
|
|
46
|
+
New Next.js apps expose the domain adapter explicitly:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// src/app/api/ekairos/domain/route.ts
|
|
50
|
+
import { createRuntimeRouteHandler } from "@ekairos/domain/next";
|
|
51
|
+
import { createRuntime } from "@/runtime";
|
|
52
|
+
|
|
53
|
+
export const { GET, POST } = createRuntimeRouteHandler({
|
|
54
|
+
createRuntime,
|
|
55
|
+
});
|
|
22
56
|
```
|
|
23
57
|
|
|
24
|
-
|
|
58
|
+
This replaces the old `withRuntime(...)` pattern.
|
|
59
|
+
There is no Next config patching and no generated `.well-known` domain route in new apps.
|
|
60
|
+
|
|
61
|
+
Your `next.config.ts` should stay focused on Workflow:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import type { NextConfig } from "next";
|
|
65
|
+
import { withWorkflow } from "workflow/next";
|
|
66
|
+
|
|
67
|
+
const nextConfig: NextConfig = {
|
|
68
|
+
transpilePackages: ["@ekairos/domain"],
|
|
69
|
+
};
|
|
25
70
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- `@ekairos/domain/next`
|
|
71
|
+
export default withWorkflow(nextConfig) as NextConfig;
|
|
72
|
+
```
|
|
29
73
|
|
|
30
|
-
|
|
74
|
+
The CLI uses `/api/ekairos/domain`.
|
|
31
75
|
|
|
32
|
-
|
|
76
|
+
## Core Pattern
|
|
33
77
|
|
|
34
78
|
```ts
|
|
35
|
-
import { domain } from "@ekairos/domain";
|
|
79
|
+
import { defineAction, domain } from "@ekairos/domain";
|
|
80
|
+
import { EkairosRuntime } from "@ekairos/domain/runtime-handle";
|
|
81
|
+
import { executeRuntimeAction } from "@ekairos/domain/runtime";
|
|
82
|
+
import { init } from "@instantdb/admin";
|
|
36
83
|
import { i } from "@instantdb/core";
|
|
37
84
|
|
|
38
|
-
|
|
85
|
+
const baseDomain = domain("tasks").withSchema({
|
|
39
86
|
entities: {
|
|
40
|
-
|
|
41
|
-
title: i.string(),
|
|
87
|
+
tasks: i.entity({
|
|
88
|
+
title: i.string().indexed(),
|
|
42
89
|
status: i.string().indexed(),
|
|
43
|
-
createdAt: i.date().indexed(),
|
|
44
90
|
}),
|
|
45
91
|
},
|
|
46
92
|
links: {},
|
|
47
93
|
rooms: {},
|
|
48
94
|
});
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### 2. Add typed actions
|
|
52
95
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
{ db: any }
|
|
61
|
-
>({
|
|
62
|
-
name: "management.task.create",
|
|
63
|
-
description: "Create a management task",
|
|
64
|
-
async execute({ env, input, runtime }) {
|
|
65
|
-
const title = String(input.title ?? "").trim();
|
|
66
|
-
if (!title) throw new Error("title_required");
|
|
67
|
-
|
|
68
|
-
// use runtime.db here
|
|
69
|
-
return { ok: true, taskId: `task_${env.orgId}` };
|
|
96
|
+
export const createTaskAction = defineAction({
|
|
97
|
+
name: "tasks.create",
|
|
98
|
+
async execute({ runtime, input }) {
|
|
99
|
+
"use step";
|
|
100
|
+
const scoped = await runtime.use(appDomain);
|
|
101
|
+
// transact...
|
|
102
|
+
return { ok: true };
|
|
70
103
|
},
|
|
71
104
|
});
|
|
72
105
|
|
|
73
|
-
export const appDomain =
|
|
106
|
+
export const appDomain = baseDomain.withActions({
|
|
107
|
+
createTask: createTaskAction,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Raw definitions stay available for reflection and adapters:
|
|
111
|
+
appDomain.actions.createTask;
|
|
112
|
+
|
|
113
|
+
export class AppRuntime extends EkairosRuntime<{
|
|
114
|
+
appId?: string;
|
|
115
|
+
adminToken?: string;
|
|
116
|
+
}, typeof appDomain, any> {
|
|
117
|
+
protected getDomain() {
|
|
118
|
+
return appDomain;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
protected async resolveDb(env: { appId?: string; adminToken?: string }) {
|
|
122
|
+
return init({
|
|
123
|
+
appId: env.appId!,
|
|
124
|
+
adminToken: env.adminToken!,
|
|
125
|
+
schema: appDomain.instantSchema(),
|
|
126
|
+
useDateObjects: true,
|
|
127
|
+
} as any);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createRuntime(env = {}) {
|
|
132
|
+
return new AppRuntime(env);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function runWorkflow() {
|
|
136
|
+
"use workflow";
|
|
137
|
+
const runtime = createRuntime({
|
|
138
|
+
appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID,
|
|
139
|
+
adminToken: process.env.INSTANT_ADMIN_TOKEN,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return await executeRuntimeAction({
|
|
143
|
+
runtime,
|
|
144
|
+
action: createTaskAction,
|
|
145
|
+
input: { title: "Ship it" },
|
|
146
|
+
});
|
|
147
|
+
}
|
|
74
148
|
```
|
|
75
149
|
|
|
76
|
-
|
|
150
|
+
## Rules Of Thumb
|
|
151
|
+
|
|
152
|
+
- Read directly from the composed schema when no invariant is involved.
|
|
153
|
+
- Put every meaningful write behind an action.
|
|
154
|
+
- Keep action bodies `"use step"`.
|
|
155
|
+
- Keep workflow orchestration above actions.
|
|
156
|
+
- Use `DOMAIN.md` plus `domain.contextString()` when an AI agent needs the model explained.
|
|
157
|
+
|
|
158
|
+
## Public And Full Domains
|
|
159
|
+
|
|
160
|
+
Use normal domain composition to split browser-visible schema from server/runtime
|
|
161
|
+
capabilities. The public domain is a smaller domain. The full domain imports and
|
|
162
|
+
extends it.
|
|
77
163
|
|
|
78
164
|
```ts
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
165
|
+
// @acme/sandbox/public
|
|
166
|
+
export const sandboxDomain = domain("sandbox").withSchema({
|
|
167
|
+
entities: {
|
|
168
|
+
sandbox_sandboxes: i.entity({
|
|
169
|
+
provider: i.string().indexed(),
|
|
170
|
+
status: i.string().indexed(),
|
|
171
|
+
createdAt: i.number().indexed(),
|
|
172
|
+
}),
|
|
87
173
|
},
|
|
174
|
+
links: {},
|
|
175
|
+
rooms: {},
|
|
88
176
|
});
|
|
89
177
|
```
|
|
90
178
|
|
|
91
|
-
|
|
179
|
+
```ts
|
|
180
|
+
// @acme/sandbox
|
|
181
|
+
import { sandboxDomain as publicSandboxDomain } from "@acme/sandbox/public";
|
|
182
|
+
|
|
183
|
+
export const sandboxDomain = domain("sandbox")
|
|
184
|
+
.includes(publicSandboxDomain)
|
|
185
|
+
.withSchema({
|
|
186
|
+
entities: {
|
|
187
|
+
sandbox_processes: i.entity({
|
|
188
|
+
kind: i.string().indexed(),
|
|
189
|
+
status: i.string().indexed(),
|
|
190
|
+
command: i.string(),
|
|
191
|
+
startedAt: i.number().indexed(),
|
|
192
|
+
}),
|
|
193
|
+
},
|
|
194
|
+
links: {
|
|
195
|
+
sandboxProcessSandbox: {
|
|
196
|
+
forward: { on: "sandbox_processes", has: "one", label: "sandbox" },
|
|
197
|
+
reverse: { on: "sandbox_sandboxes", has: "many", label: "processes" },
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
rooms: {},
|
|
201
|
+
})
|
|
202
|
+
.withActions({
|
|
203
|
+
runCommand: defineAction({
|
|
204
|
+
name: "sandbox.runCommand",
|
|
205
|
+
async execute({ runtime, input }) {
|
|
206
|
+
"use step";
|
|
207
|
+
// server/provider work
|
|
208
|
+
},
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Client schema composition imports public domains:
|
|
92
214
|
|
|
93
215
|
```ts
|
|
94
|
-
import {
|
|
216
|
+
import { sandboxDomain } from "@acme/sandbox/public";
|
|
95
217
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
input: { title: "Ship domain action runtime" },
|
|
100
|
-
});
|
|
101
|
-
```
|
|
218
|
+
export const appDomain = domain("app")
|
|
219
|
+
.includes(sandboxDomain)
|
|
220
|
+
.withSchema({ entities: {}, links: {}, rooms: {} });
|
|
102
221
|
|
|
103
|
-
|
|
222
|
+
export default appDomain.instantSchema();
|
|
223
|
+
```
|
|
104
224
|
|
|
105
|
-
|
|
225
|
+
Server runtime imports full domains:
|
|
106
226
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- Runtime is resolved per action domain.
|
|
110
|
-
- Nested action calls are supported with cycle protection.
|
|
227
|
+
```ts
|
|
228
|
+
import { sandboxDomain } from "@acme/sandbox";
|
|
111
229
|
|
|
112
|
-
|
|
230
|
+
const sandbox = await runtime.use(sandboxDomain);
|
|
231
|
+
await sandbox.actions.runCommand({ sandboxId, command: "pnpm", args: ["test"] });
|
|
232
|
+
```
|
|
113
233
|
|
|
114
|
-
|
|
234
|
+
This pattern controls schema visibility only. It is not an authorization model:
|
|
235
|
+
configure Instant permissions for actual data access.
|
|
115
236
|
|
|
116
|
-
|
|
237
|
+
## CLI Input Quality Of Life
|
|
117
238
|
|
|
118
|
-
|
|
119
|
-
- `domain.contextString()` returns a prompt-friendly string.
|
|
239
|
+
The CLI accepts JSON5, `@file`, and stdin:
|
|
120
240
|
|
|
121
|
-
|
|
241
|
+
```bash
|
|
242
|
+
ekairos domain query "{ tasks: { $: { limit: 5 } } }" --admin
|
|
243
|
+
ekairos domain query @query.json5 --admin
|
|
244
|
+
cat query.json5 | ekairos domain query - --admin
|
|
245
|
+
```
|
|
122
246
|
|
|
123
|
-
|
|
247
|
+
Add `--meta` when you need to know whether a query used the local client runtime path or the server route.
|
|
124
248
|
|
|
125
|
-
|
|
249
|
+
## Tests
|
|
126
250
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
251
|
+
```bash
|
|
252
|
+
pnpm --filter @ekairos/domain test
|
|
253
|
+
pnpm --filter @ekairos/domain test:cli
|
|
254
|
+
pnpm --filter @ekairos/domain test:workflow
|
|
255
|
+
```
|
|
130
256
|
|
|
131
|
-
|
|
257
|
+
## Type And DX Notes
|
|
132
258
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
259
|
+
`@ekairos/domain` intentionally encapsulates InstantDB at the domain boundary, but
|
|
260
|
+
the schema returned by a domain must remain usable anywhere an InstantDB schema is
|
|
261
|
+
expected.
|
|
136
262
|
|
|
137
|
-
|
|
263
|
+
Use `instantSchema()` when provisioning or passing a runtime schema to InstantDB:
|
|
138
264
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
265
|
+
```ts
|
|
266
|
+
const db = init({
|
|
267
|
+
appId,
|
|
268
|
+
adminToken,
|
|
269
|
+
schema: appDomain.instantSchema(),
|
|
270
|
+
});
|
|
271
|
+
```
|
|
144
272
|
|
|
145
|
-
|
|
273
|
+
Use `DomainInstantSchema<typeof domain>` when you need the schema type for
|
|
274
|
+
`db.query`, `InstaQLParams`, `InstaQLResult`, or service constructors:
|
|
146
275
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
276
|
+
```ts
|
|
277
|
+
import type { DomainInstantSchema } from "@ekairos/domain";
|
|
278
|
+
import type { InstantAdminDatabase } from "@instantdb/admin";
|
|
279
|
+
|
|
280
|
+
type AppSchema = DomainInstantSchema<typeof appDomain>;
|
|
281
|
+
|
|
282
|
+
function createService(db: InstantAdminDatabase<AppSchema, true>) {
|
|
283
|
+
return db.query({
|
|
284
|
+
tasks: {
|
|
285
|
+
owner: {},
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
```
|
|
151
290
|
|
|
152
|
-
|
|
291
|
+
Prefer exported domain values without widening their type:
|
|
153
292
|
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
|
|
293
|
+
```ts
|
|
294
|
+
export const tasksDomain = domain("tasks").withSchema({
|
|
295
|
+
entities: { tasks: i.entity({ title: i.string() }) },
|
|
296
|
+
links: {},
|
|
297
|
+
rooms: {},
|
|
298
|
+
});
|
|
157
299
|
```
|
|
158
300
|
|
|
159
|
-
|
|
301
|
+
Avoid annotating exported domains as plain `DomainSchemaResult` unless you need to
|
|
302
|
+
hide their concrete shape. That annotation widens the domain name and schema, so
|
|
303
|
+
TypeScript loses some compile-time checks for `runtime.use(...)`, `RuntimeForDomain`,
|
|
304
|
+
and composed queries.
|
|
160
305
|
|
|
161
|
-
```
|
|
162
|
-
|
|
306
|
+
```ts
|
|
307
|
+
// Avoid for runtime/domain composition:
|
|
308
|
+
export const tasksDomain: DomainSchemaResult = domain("tasks").withSchema(...);
|
|
163
309
|
```
|
|
164
310
|
|
|
165
|
-
|
|
311
|
+
Type tests under `src/__type_tests__` are intentionally split by use case:
|
|
166
312
|
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
313
|
+
- `domain.schema-*.typecheck.ts`: schema extraction, entity/link visibility, and query shape.
|
|
314
|
+
- `domain.includes-*.typecheck.ts`: composed entities, transitive links, and traversal direction.
|
|
315
|
+
- `domain.instaql-fetch.typecheck.ts`: namespaces, associations, deferred query shapes, and `queryOnce`.
|
|
316
|
+
- `domain.instaql-filters.typecheck.ts`: dotted relation filters and advanced where operators.
|
|
317
|
+
- `domain.instaql-options.typecheck.ts`: pagination, ordering, selected fields, and page info.
|
|
318
|
+
- `domain.instantdb-*.typecheck.ts`: InstantDB query, entity, and result helpers.
|
|
319
|
+
- `domain.query-negative-*.typecheck.ts`: invalid entities and relation labels stay rejected.
|
|
320
|
+
- `domain.dx-*.typecheck.ts`: public helper aliases, literal names, and schema helpers.
|
|
321
|
+
- `runtime.domain-names-*.typecheck.ts`: `RuntimeForDomain` validates name plus schema.
|
|
322
|
+
- `workflow-output-*.typecheck.ts`: workflow serde output contracts.
|
|
170
323
|
|
|
171
|
-
|
|
324
|
+
When a type regression appears, add one small file or one focused case to the
|
|
325
|
+
matching file. Avoid broad "kitchen sink" type tests; they make IntelliSense and
|
|
326
|
+
compiler failures hard to read.
|
|
172
327
|
|
|
173
|
-
MIT
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Skill: ekairos-domain
|
|
2
|
+
|
|
3
|
+
Use this skill when creating, editing, reviewing, or operating Ekairos domain code.
|
|
4
|
+
|
|
5
|
+
## Core Contract
|
|
6
|
+
|
|
7
|
+
- Model knowledge boundaries as domains first. A domain owns one coherent concept.
|
|
8
|
+
- Domain names are camelCase, for example `supplierNetwork`, `procurement`, `qualityControl`.
|
|
9
|
+
- Entity names must follow `<domainName>_<entityName>`, for example `supplierNetwork_supplier`.
|
|
10
|
+
- Put writes behind `defineDomainAction(...)`.
|
|
11
|
+
- Keep action bodies step-safe:
|
|
12
|
+
`async execute({ runtime, input }) { "use step"; const scoped = await runtime.use(appDomain); ... }`
|
|
13
|
+
- Prefer typed action calls in app-owned code:
|
|
14
|
+
`const scoped = await runtime.use(appDomain); await scoped.actions.launchOrder(input);`
|
|
15
|
+
- Use string action names only for dynamic runtime/HTTP/CLI execution.
|
|
16
|
+
- Use explicit runtime classes that extend `EkairosRuntime`.
|
|
17
|
+
- New Next.js apps expose `/api/ekairos/domain` through `createRuntimeRouteHandler({ createRuntime })`.
|
|
18
|
+
- Do not use or reintroduce `withRuntime(...)`.
|
|
19
|
+
|
|
20
|
+
## Domain Design Workflow
|
|
21
|
+
|
|
22
|
+
1. Identify the knowledge domains before writing schema.
|
|
23
|
+
2. Name every entity with its owning domain prefix.
|
|
24
|
+
3. Use `domain(...).includes(...)` only when one domain needs another domain's entities or links.
|
|
25
|
+
4. Keep root app domains thin. The root should usually include domains and register actions.
|
|
26
|
+
5. Write actions around business use cases, not CRUD verbs.
|
|
27
|
+
6. Verify the graph with a nested query that crosses at least two domains.
|
|
28
|
+
|
|
29
|
+
## Schema Rules
|
|
30
|
+
|
|
31
|
+
- Prefer operational names over abstract names.
|
|
32
|
+
- Avoid generic `app_*` entities in new examples unless the domain itself is `app`.
|
|
33
|
+
- Do not duplicate entity names across domains.
|
|
34
|
+
- Links should describe the business relationship, not implementation plumbing.
|
|
35
|
+
- Use optional attributes when migrating an existing app with data.
|
|
36
|
+
|
|
37
|
+
## Runtime And Actions
|
|
38
|
+
|
|
39
|
+
- Dynamic endpoints may call `executeRuntimeAction({ action: "domain.action", input })`.
|
|
40
|
+
- Workflows and app code should use typed scoped actions.
|
|
41
|
+
- Action outputs should return durable ids needed by callers.
|
|
42
|
+
- Keep actions idempotent where possible when they will be used by smoke tests or agents.
|
|
43
|
+
|
|
44
|
+
## Verification
|
|
45
|
+
|
|
46
|
+
For a generated or edited app:
|
|
47
|
+
|
|
48
|
+
1. Run `pnpm typecheck`.
|
|
49
|
+
2. Start the app locally.
|
|
50
|
+
3. Verify `GET /api/ekairos/domain`.
|
|
51
|
+
4. Execute at least one domain action.
|
|
52
|
+
5. Query the linked graph produced by that action.
|
|
53
|
+
|
|
54
|
+
## Related Skills
|
|
55
|
+
|
|
56
|
+
- CLI/application workflow skill: `../cli/SKILL.md`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { stdout as output } from "node:process";
|
|
3
|
+
type CliContext = {
|
|
4
|
+
stdout: Pick<typeof output, "write">;
|
|
5
|
+
stderr: Pick<typeof output, "write">;
|
|
6
|
+
};
|
|
7
|
+
export declare function runCli(argv: string[], ctx?: CliContext): Promise<0 | 1>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=bin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../../src/cli/bin.ts"],"names":[],"mappings":";AAGA,OAAO,EAAkB,MAAM,IAAI,MAAM,EAAE,MAAM,cAAc,CAAA;AAkB/D,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,MAAM,EAAE,IAAI,CAAC,OAAO,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAgqBD,wBAAsB,MAAM,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,UAA+C,kBAuDrD"}
|