@astrale-os/adapter-cloudflare 0.4.4 → 0.4.6

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.
Files changed (46) hide show
  1. package/dist/codegen/wrangler.js +1 -1
  2. package/package.json +4 -3
  3. package/src/codegen/wrangler.ts +1 -1
  4. package/template/CLAUDE.md +8 -21
  5. package/template/README.md +30 -107
  6. package/template/client/__tests__/app.test.tsx +6 -57
  7. package/template/client/components.json +25 -0
  8. package/template/client/index.html +1 -1
  9. package/template/client/package.json +10 -2
  10. package/template/client/src/app.tsx +42 -33
  11. package/template/client/src/components/ui/cn.ts +6 -0
  12. package/template/client/src/styles.css +71 -502
  13. package/template/client/vite.config.ts +2 -18
  14. package/template/client/vitest.config.ts +0 -6
  15. package/template/core/README.md +5 -21
  16. package/template/deps.ts +2 -20
  17. package/template/domain.ts +0 -26
  18. package/template/env.ts +1 -17
  19. package/template/icons.ts +4 -25
  20. package/template/integrations/README.md +5 -20
  21. package/template/package.json +7 -5
  22. package/template/pnpm-workspace.yaml +2 -0
  23. package/template/runtime/index.ts +0 -27
  24. package/template/schema/index.ts +0 -20
  25. package/template/simulation/README.md +12 -0
  26. package/template/tsconfig.json +2 -3
  27. package/template/vitest.config.ts +7 -0
  28. package/template/.domain-studio/comments.json +0 -4
  29. package/template/client/README.md +0 -104
  30. package/template/client/__tests__/harness.ts +0 -230
  31. package/template/client/__tests__/shell.test.ts +0 -46
  32. package/template/client/src/shell/client.ts +0 -67
  33. package/template/client/src/shell/index.ts +0 -21
  34. package/template/client/src/shell/invoke.ts +0 -35
  35. package/template/client/src/shell/transformers.ts +0 -75
  36. package/template/client/src/shell/use-async.ts +0 -59
  37. package/template/client/src/shell/use-capability.ts +0 -59
  38. package/template/client/src/shell/use-node.ts +0 -81
  39. package/template/client/src/shell/use-shell.ts +0 -91
  40. package/template/client/src/shell/view-router.tsx +0 -97
  41. package/template/client/src/ui/format.ts +0 -24
  42. package/template/client/src/ui/index.ts +0 -10
  43. package/template/client/src/ui/surface.tsx +0 -56
  44. package/template/client/src/ui/value.tsx +0 -32
  45. package/template/functions/index.ts +0 -22
  46. package/template/views/index.ts +0 -19
@@ -1,509 +1,78 @@
1
- :root {
2
- --bg: #fafafa;
3
- --fg: #171717;
4
- --muted: #737373;
5
- --border: #e5e5e5;
6
- --border-strong: #d4d4d8;
7
- --card: #ffffff;
8
- --surface: #f4f4f5;
9
- --surface-strong: #eceff3;
10
- --accent: #2563eb;
11
- --accent-soft: rgba(37, 99, 235, 0.1);
12
- --warn-bg: #fffbeb;
13
- --warn-border: #fde68a;
14
- --warn-fg: #92400e;
15
- --err: #dc2626;
16
- --err-soft: rgba(220, 38, 38, 0.1);
17
- --up: #16a34a;
18
- --degraded: #d97706;
19
- --down: #dc2626;
20
- --unknown: #737373;
21
- --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
22
- }
23
-
24
- * {
25
- box-sizing: border-box;
26
- }
27
-
28
- body {
29
- margin: 0;
30
- background: var(--bg);
31
- color: var(--fg);
32
- font:
33
- 14px/1.6 system-ui,
34
- -apple-system,
35
- sans-serif;
36
- -webkit-font-smoothing: antialiased;
37
- }
38
-
39
- #root {
40
- min-height: 100vh;
41
- }
42
-
43
- .wrap {
44
- max-width: 64rem;
45
- margin: 0 auto;
46
- padding: 1.5rem;
47
- }
48
-
49
- .card {
50
- background: var(--card);
51
- border: 1px solid var(--border);
52
- border-radius: 0.5rem;
53
- padding: 1.25rem 1.5rem;
54
- box-shadow: 0 16px 40px rgba(24, 24, 27, 0.06);
55
- }
56
-
57
- .title {
58
- font-size: 1.4rem;
59
- font-weight: 600;
60
- margin: 0;
61
- }
62
-
63
- .subline {
64
- font-family: var(--mono);
65
- font-size: 0.72rem;
66
- color: var(--muted);
67
- margin: 0.25rem 0 1rem;
68
- word-break: break-all;
69
- }
70
-
71
- .body {
72
- white-space: pre-wrap;
73
- margin: 0 0 1rem;
74
- }
75
-
76
- /* ─── Banners ───────────────────────────────────────────────────────────── */
77
-
78
- .banner {
79
- border: 1px solid var(--warn-border);
80
- background: var(--warn-bg);
81
- color: var(--warn-fg);
82
- border-radius: 0.5rem;
83
- padding: 0.6rem 0.85rem;
84
- font-size: 0.8rem;
85
- margin-bottom: 1rem;
86
- }
87
-
88
- .banner-error {
89
- border-color: var(--err);
90
- background: var(--err-soft);
91
- color: var(--err);
92
- word-break: break-word;
93
- }
94
-
95
- /* ─── Panel ─────────────────────────────────────────────────────────────── */
96
-
97
- .panel {
98
- background: transparent;
99
- border: 0;
100
- border-radius: 0;
101
- padding: 0;
102
- }
103
-
104
- .panel-danger {
105
- border-color: color-mix(in srgb, var(--err) 45%, var(--border));
106
- }
107
-
108
- .panel-head {
109
- display: flex;
110
- align-items: center;
111
- justify-content: space-between;
112
- gap: 0.75rem;
113
- margin-bottom: 1rem;
114
- }
115
-
116
- .panel-title {
117
- font-size: 1.35rem;
118
- font-weight: 650;
119
- margin: 0;
120
- }
121
-
122
- .panel-danger .panel-title {
123
- color: var(--err);
124
- }
125
-
126
- .panel-actions {
127
- display: inline-flex;
128
- align-items: center;
129
- gap: 0.5rem;
130
- }
131
-
132
- /* ─── Key/value ─────────────────────────────────────────────────────────── */
133
-
134
- .kv {
135
- border: 1px solid var(--border);
136
- border-radius: 0.5rem;
137
- overflow: hidden;
138
- font-family: var(--mono);
139
- font-size: 0.72rem;
140
- }
141
-
142
- .kv-row {
143
- display: grid;
144
- grid-template-columns: 9rem 1fr;
145
- gap: 0.75rem;
146
- padding: 0.4rem 0.7rem;
147
- border-top: 1px solid var(--border);
148
- }
149
-
150
- .kv-row:first-child {
151
- border-top: 0;
152
- }
153
-
154
- .kv-key {
155
- color: var(--muted);
156
- }
157
-
158
- .kv-val {
159
- word-break: break-all;
160
- min-width: 0;
161
- }
162
-
163
- .muted {
164
- color: var(--muted);
165
- }
166
-
167
- .mono {
168
- font-family: var(--mono);
169
- font-size: 0.78rem;
170
- }
171
-
172
- .link {
173
- color: var(--accent);
174
- text-decoration: none;
175
- }
176
-
177
- .link:hover {
178
- text-decoration: underline;
179
- }
180
-
181
- /* ─── Status dashboard + badge ──────────────────────────────────────────── */
182
-
183
- .status-dashboard {
184
- display: grid;
185
- gap: 1rem;
186
- }
187
-
188
- .status-overview {
189
- display: grid;
190
- grid-template-columns: minmax(0, 1fr) minmax(16rem, 0.65fr);
191
- gap: 1rem;
192
- align-items: stretch;
193
- padding: 1rem;
194
- background: var(--surface);
195
- border: 1px solid var(--border);
196
- border-radius: 0.5rem;
197
- }
198
-
199
- .status-label {
200
- font-family: var(--mono);
201
- font-size: 0.7rem;
202
- color: var(--muted);
203
- margin: 0 0 0.55rem;
204
- text-transform: uppercase;
205
- letter-spacing: 0.06em;
206
- }
207
-
208
- .summary-grid {
209
- display: grid;
210
- grid-template-columns: repeat(3, minmax(0, 1fr));
211
- border: 1px solid var(--border);
212
- border-radius: 0.5rem;
213
- overflow: hidden;
214
- background: var(--card);
215
- }
216
-
217
- .summary-cell {
218
- min-width: 0;
219
- padding: 0.7rem 0.8rem;
220
- border-left: 1px solid var(--border);
221
- }
222
-
223
- .summary-cell:first-child {
224
- border-left: 0;
225
- }
226
-
227
- .summary-value {
228
- display: block;
229
- font-size: 1.25rem;
230
- line-height: 1.1;
231
- font-weight: 750;
232
- }
233
-
234
- .summary-label {
235
- display: block;
236
- color: var(--muted);
237
- font-size: 0.72rem;
238
- margin-top: 0.15rem;
239
- }
240
-
241
- .status-meta {
242
- display: grid;
243
- grid-template-columns: max-content minmax(0, 1fr) max-content max-content;
244
- gap: 0.45rem 0.75rem;
245
- align-items: center;
246
- color: var(--muted);
247
- font-size: 0.76rem;
248
- }
249
-
250
- .status-meta > span:nth-child(odd) {
251
- font-family: var(--mono);
252
- }
253
-
254
- .status-badge {
255
- display: inline-block;
256
- font-weight: 700;
257
- font-size: 1rem;
258
- letter-spacing: 0.04em;
259
- padding: 0.3rem 0.85rem;
260
- border-radius: 0.5rem;
261
- color: #ffffff;
262
- }
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+ @import 'shadcn/tailwind.css';
4
+ @import '@fontsource-variable/instrument-sans';
5
+ @import '@fontsource/ibm-plex-mono/400.css';
263
6
 
264
- .status-up {
265
- background: var(--up);
266
- }
267
-
268
- .status-degraded {
269
- background: var(--degraded);
270
- }
271
-
272
- .status-down {
273
- background: var(--down);
274
- }
275
-
276
- .status-unknown {
277
- background: var(--unknown);
278
- }
279
-
280
- .monitor-section {
281
- border-top: 1px solid var(--border);
282
- padding-top: 1rem;
283
- }
284
-
285
- .monitor-section-head {
286
- display: flex;
287
- align-items: center;
288
- justify-content: space-between;
289
- gap: 0.75rem;
290
- margin-bottom: 0.45rem;
291
- }
292
-
293
- .monitor-section-head h3 {
294
- font-size: 0.95rem;
295
- margin: 0;
296
- }
297
-
298
- .refreshing {
299
- font-family: var(--mono);
300
- font-size: 0.7rem;
301
- color: var(--accent);
302
- background: var(--accent-soft);
303
- border-radius: 0.35rem;
304
- padding: 0.15rem 0.4rem;
305
- }
306
-
307
- .monitor-list {
308
- border: 1px solid var(--border);
309
- border-radius: 0.5rem;
310
- overflow: hidden;
311
- }
312
-
313
- .monitor-row {
314
- display: grid;
315
- grid-template-columns: 8.5rem minmax(0, 1fr) minmax(17rem, 0.8fr);
316
- gap: 1rem;
317
- align-items: center;
318
- padding: 0.85rem 0.95rem;
319
- border-top: 1px solid var(--border);
320
- background: var(--card);
321
- }
322
-
323
- .monitor-row:first-child {
324
- border-top: 0;
325
- }
326
-
327
- .monitor-status {
328
- display: flex;
329
- flex-direction: column;
330
- align-items: flex-start;
331
- gap: 0.4rem;
332
- }
333
-
334
- .monitor-row .status-badge {
335
- font-size: 0.72rem;
336
- padding: 0.2rem 0.5rem;
337
- border-radius: 0.35rem;
338
- }
339
-
340
- .weight {
341
- font-family: var(--mono);
342
- font-size: 0.68rem;
343
- color: var(--muted);
344
- background: var(--surface);
345
- border-radius: 0.35rem;
346
- padding: 0.15rem 0.4rem;
347
- }
348
-
349
- .weight-critical {
350
- color: var(--err);
351
- background: var(--err-soft);
352
- }
353
-
354
- .monitor-main {
355
- min-width: 0;
356
- }
357
-
358
- .monitor-main h4 {
359
- margin: 0 0 0.12rem;
360
- font-size: 0.95rem;
361
- }
362
-
363
- .monitor-metrics {
364
- display: grid;
365
- grid-template-columns: repeat(3, minmax(0, 1fr));
366
- gap: 0.5rem;
367
- margin: 0;
368
- }
369
-
370
- .monitor-metrics div {
371
- min-width: 0;
372
- padding: 0.45rem 0.55rem;
373
- background: var(--surface);
374
- border-radius: 0.4rem;
375
- }
376
-
377
- .monitor-metrics dt {
378
- color: var(--muted);
379
- font-size: 0.68rem;
380
- margin-bottom: 0.1rem;
381
- }
7
+ @custom-variant dark (&:is(.dark *));
382
8
 
383
- .monitor-metrics dd {
384
- margin: 0;
385
- font-family: var(--mono);
386
- font-size: 0.75rem;
387
- word-break: break-word;
388
- }
389
-
390
- /* ─── Buttons ───────────────────────────────────────────────────────────── */
391
-
392
- .check-btn {
393
- font: inherit;
394
- font-weight: 600;
395
- color: #ffffff;
396
- background: var(--accent);
397
- border: 0;
398
- border-radius: 0.5rem;
399
- padding: 0.4rem 0.85rem;
400
- cursor: pointer;
401
- }
402
-
403
- .check-btn:hover:not(:disabled) {
404
- opacity: 0.9;
405
- }
406
-
407
- .check-btn:disabled {
408
- opacity: 0.55;
409
- cursor: default;
410
- }
411
-
412
- /* ─── Empty state ───────────────────────────────────────────────────────── */
413
-
414
- .empty {
415
- border: 1px dashed var(--border-strong);
416
- border-radius: 0.6rem;
417
- padding: 1.4rem 1.2rem;
418
- text-align: center;
419
- display: flex;
420
- flex-direction: column;
421
- gap: 0.6rem;
422
- align-items: center;
423
- }
424
-
425
- .empty-text {
426
- margin: 0;
427
- color: var(--muted);
428
- font-size: 0.85rem;
429
- }
430
-
431
- .empty-hint {
432
- font-family: var(--mono);
433
- font-size: 0.72rem;
434
- color: var(--muted);
435
- background: var(--bg);
436
- border: 1px solid var(--border);
437
- border-radius: 0.4rem;
438
- padding: 0.3rem 0.6rem;
439
- word-break: break-all;
440
- }
441
-
442
- /* ─── Loading ───────────────────────────────────────────────────────────── */
443
-
444
- .loading-line {
445
- display: flex;
446
- align-items: center;
447
- gap: 0.5rem;
448
- margin: 0;
449
- }
450
-
451
- .spinner {
452
- width: 0.85rem;
453
- height: 0.85rem;
454
- border-radius: 50%;
455
- border: 2px solid var(--border-strong);
456
- border-top-color: var(--accent);
457
- animation: spin 0.8s linear infinite;
458
- }
459
-
460
- @keyframes spin {
461
- to {
462
- transform: rotate(360deg);
463
- }
464
- }
465
-
466
- @media (max-width: 760px) {
467
- .wrap {
468
- padding: 0.75rem;
469
- }
470
-
471
- .card {
472
- padding: 1rem;
473
- }
474
-
475
- .panel-head,
476
- .status-overview,
477
- .monitor-row {
478
- grid-template-columns: 1fr;
479
- }
480
-
481
- .panel-head,
482
- .monitor-section-head {
483
- align-items: flex-start;
9
+ :root {
10
+ color-scheme: dark;
11
+ --background: oklch(0.145 0.008 65);
12
+ --foreground: oklch(0.93 0.012 78);
13
+ --card: oklch(0.18 0.009 65);
14
+ --card-foreground: var(--foreground);
15
+ --popover: oklch(0.19 0.009 65);
16
+ --popover-foreground: var(--foreground);
17
+ --primary: oklch(0.76 0.12 75);
18
+ --primary-foreground: oklch(0.17 0.01 65);
19
+ --secondary: oklch(0.23 0.01 65);
20
+ --secondary-foreground: var(--foreground);
21
+ --muted: oklch(0.22 0.008 65);
22
+ --muted-foreground: oklch(0.66 0.012 75);
23
+ --accent: oklch(0.25 0.012 65);
24
+ --accent-foreground: var(--foreground);
25
+ --destructive: oklch(0.65 0.18 25);
26
+ --border: oklch(0.285 0.01 65);
27
+ --input: oklch(0.29 0.01 65);
28
+ --ring: var(--primary);
29
+ --radius: 0.625rem;
30
+ --font-sans: 'Instrument Sans Variable', sans-serif;
31
+ --font-mono: 'IBM Plex Mono', monospace;
32
+ }
33
+
34
+ @theme inline {
35
+ --font-sans: var(--font-sans);
36
+ --font-mono: var(--font-mono);
37
+ --color-ring: var(--ring);
38
+ --color-input: var(--input);
39
+ --color-border: var(--border);
40
+ --color-destructive: var(--destructive);
41
+ --color-accent-foreground: var(--accent-foreground);
42
+ --color-accent: var(--accent);
43
+ --color-muted-foreground: var(--muted-foreground);
44
+ --color-muted: var(--muted);
45
+ --color-secondary-foreground: var(--secondary-foreground);
46
+ --color-secondary: var(--secondary);
47
+ --color-primary-foreground: var(--primary-foreground);
48
+ --color-primary: var(--primary);
49
+ --color-popover-foreground: var(--popover-foreground);
50
+ --color-popover: var(--popover);
51
+ --color-card-foreground: var(--card-foreground);
52
+ --color-card: var(--card);
53
+ --color-foreground: var(--foreground);
54
+ --color-background: var(--background);
55
+ --radius-sm: calc(var(--radius) - 4px);
56
+ --radius-md: calc(var(--radius) - 2px);
57
+ --radius-lg: var(--radius);
58
+ --radius-xl: calc(var(--radius) + 4px);
59
+ }
60
+
61
+ @layer base {
62
+ * {
63
+ @apply border-border outline-ring/50;
484
64
  }
485
-
486
- .status-meta {
487
- grid-template-columns: max-content minmax(0, 1fr);
65
+ html,
66
+ body,
67
+ #root {
68
+ min-height: 100%;
488
69
  }
489
-
490
- .monitor-metrics {
491
- grid-template-columns: repeat(3, minmax(0, 1fr));
70
+ body {
71
+ @apply bg-background text-foreground font-sans antialiased;
72
+ margin: 0;
492
73
  }
493
- }
494
-
495
- @media (max-width: 460px) {
496
- .summary-grid,
497
- .monitor-metrics {
498
- grid-template-columns: 1fr;
499
- }
500
-
501
- .summary-cell {
502
- border-left: 0;
503
- border-top: 1px solid var(--border);
504
- }
505
-
506
- .summary-cell:first-child {
507
- border-top: 0;
74
+ code,
75
+ kbd {
76
+ @apply font-mono;
508
77
  }
509
78
  }
@@ -1,27 +1,11 @@
1
+ import tailwindcss from '@tailwindcss/vite'
1
2
  import viteReact from '@vitejs/plugin-react'
2
3
  import { fileURLToPath } from 'node:url'
3
4
  import { defineConfig } from 'vite'
4
5
 
5
- /**
6
- * Client SPA for the domain's Views. Built into `../.dist/`, served by the
7
- * generated worker via its `ASSETS` binding (`.astrale/`).
8
- *
9
- * `base: '/ui/'` + `outDir: '../.dist'`: Vite emits asset refs as
10
- * `/ui/assets/<hash>.js`; the worker strips the `/ui` prefix before delegating
11
- * to `ASSETS`, so files resolve from the directory root. `index.html` is the
12
- * SPA fallback for `/ui/<anything>` — `src/app.tsx` routes on the mount path.
13
- *
14
- * Consumes `@astrale-os/shell` for the child handshake + the real kernel client:
15
- * `src/shell/use-shell.ts` boots `createShell({ mode: 'sandboxed' })` and the
16
- * feature hooks call kernel methods through `shell.kernel` (token refresh, codec
17
- * negotiation, redirect following, delegation — all handled by the SDK).
18
- *
19
- * `@` is aliased to `src/` (mirrors tsconfig `paths`) so feature code imports
20
- * `@/shell`, `@/ui`, `@/status`.
21
- */
22
6
  export default defineConfig({
23
7
  base: '/ui/',
24
- plugins: [viteReact()],
8
+ plugins: [viteReact(), tailwindcss()],
25
9
  resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } },
26
10
  build: {
27
11
  outDir: '../.dist',
@@ -2,12 +2,6 @@ import viteReact from '@vitejs/plugin-react'
2
2
  import { fileURLToPath } from 'node:url'
3
3
  import { defineConfig } from 'vitest/config'
4
4
 
5
- /**
6
- * Vitest config for the client SPA. A DOM env (`happy-dom`) backs the React
7
- * render + the shell handshake the tests exercise. Kept separate from
8
- * `vite.config.ts` (which sets the `/ui/` base + `../.dist` build) so tests
9
- * don't inherit the SPA build options.
10
- */
11
5
  export default defineConfig({
12
6
  plugins: [viteReact()],
13
7
  resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } },
@@ -1,23 +1,7 @@
1
- # core/ — pure domain logic
1
+ # Core
2
2
 
3
- This folder holds the **pure, transport-agnostic logic** for each bounded
4
- context — no I/O, no `fetch`, no clock/RNG, no kernel session. Just functions
5
- over plain data that `runtime/` handlers call. Being pure makes it the easy part
6
- to unit-test.
3
+ Pure, deterministic domain logic only. Organize it by bounded context and keep kernel calls, network
4
+ I/O, clocks, randomness, and environment access in `runtime/` or `integrations/`.
7
5
 
8
- A context usually gets its own subfolder:
9
-
10
- ```
11
- core/<context>/
12
- keys.ts compiled-schema accessors (class paths, prop keys) — the ONE
13
- place graph-facing strings come from; read them off `D` from
14
- `schema/`, never hand-write them
15
- logic.ts the pure rules (validation, computation, state transitions)
16
- index.ts re-export the context's surface
17
- ```
18
-
19
- Keep the impure bits (network calls, kernel reads/writes, entropy) out of here —
20
- those live behind a port in `integrations/` and in the `runtime/` handlers.
21
-
22
- Delete this README once you add your first context. Load the `astrale-domain`
23
- skill for the modeling patterns.
6
+ Paths, domain errors, defaults, validation, and projections belong with the bounded context that owns
7
+ them. Delete this file after adding the first context.
package/template/deps.ts CHANGED
@@ -1,27 +1,9 @@
1
1
  import type { Env } from './env'
2
2
 
3
- /**
4
- * env → handler dependency container — the ONE place the worker env becomes the
5
- * typed `ctx.deps` every method reads. `defineDomain({ deps })` mounts it; the
6
- * generated worker imports it. Runs ONCE per cold isolate (NOT per request), so
7
- * it's where ports/clients are wired once instead of being re-derived in every
8
- * handler.
9
- *
10
- * It starts as a PASSTHROUGH — handlers get the raw `Env` as `ctx.deps`.
11
- * Transform here the moment a handler should depend on a PORT (built from
12
- * `integrations/`) instead of raw config — that's the whole point of this seam:
13
- *
14
- * import { buildExampleRegistry, type ExampleRegistry } from './integrations/example/registry'
15
- * export interface Deps extends ExampleRegistry {}
16
- * export function deps(env: Env): Deps {
17
- * return buildExampleRegistry(env)
18
- * }
19
- */
20
-
21
- /** Typed dependency container handed to every method as `ctx.deps`. */
3
+ /** Typed dependencies available to runtime methods, functions, and views. */
22
4
  export interface Deps extends Env {}
23
5
 
24
- /** Map the worker env to the handler deps (the seam `defineDomain({ deps })` mounts). */
6
+ /** Build long-lived ports and adapters here when the first integration is added. */
25
7
  export function deps(env: Env): Deps {
26
8
  return env
27
9
  }