@astrale-os/adapter-cloudflare 0.1.7 → 0.1.9

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 (72) hide show
  1. package/dist/assets-pack.d.ts +1 -1
  2. package/dist/assets-pack.js +1 -1
  3. package/dist/build.d.ts +15 -0
  4. package/dist/build.d.ts.map +1 -0
  5. package/dist/build.js +15 -0
  6. package/dist/build.js.map +1 -0
  7. package/dist/client.d.ts +9 -0
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +10 -1
  10. package/dist/client.js.map +1 -1
  11. package/dist/cloudflare.d.ts +15 -3
  12. package/dist/cloudflare.d.ts.map +1 -1
  13. package/dist/cloudflare.js +73 -21
  14. package/dist/cloudflare.js.map +1 -1
  15. package/dist/codegen/worker.d.ts +26 -6
  16. package/dist/codegen/worker.d.ts.map +1 -1
  17. package/dist/codegen/worker.js +70 -54
  18. package/dist/codegen/worker.js.map +1 -1
  19. package/dist/codegen/wrangler.d.ts +11 -2
  20. package/dist/codegen/wrangler.d.ts.map +1 -1
  21. package/dist/codegen/wrangler.js +11 -5
  22. package/dist/codegen/wrangler.js.map +1 -1
  23. package/dist/index.d.ts +6 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +5 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/params.d.ts +30 -30
  28. package/dist/params.d.ts.map +1 -1
  29. package/dist/parse-output.d.ts +1 -1
  30. package/dist/parse-output.js +1 -1
  31. package/package.json +6 -2
  32. package/src/assets-pack.ts +1 -1
  33. package/src/build.ts +15 -0
  34. package/src/client.ts +11 -1
  35. package/src/cloudflare.ts +77 -23
  36. package/src/codegen/worker.ts +79 -59
  37. package/src/codegen/wrangler.ts +15 -5
  38. package/src/index.ts +6 -3
  39. package/src/params.ts +32 -31
  40. package/src/parse-output.ts +1 -1
  41. package/template/.agents/skills/astrale-cli/SKILL.md +25 -11
  42. package/template/.agents/skills/astrale-domain/SKILL.md +60 -32
  43. package/template/.env.example +8 -0
  44. package/template/README.md +26 -10
  45. package/template/astrale.config.ts +22 -29
  46. package/template/client/README.md +2 -2
  47. package/template/client/src/styles.css +4 -1
  48. package/template/client/tsconfig.json +1 -1
  49. package/template/client/vite.config.ts +3 -3
  50. package/template/client/vitest.config.ts +1 -1
  51. package/template/core/keys.ts +28 -0
  52. package/template/{methods → core}/note.ts +42 -25
  53. package/template/deps.ts +25 -0
  54. package/template/domain.ts +33 -0
  55. package/template/env.ts +11 -0
  56. package/template/integrations/summary/heuristic.ts +25 -0
  57. package/template/integrations/summary/http.ts +69 -0
  58. package/template/integrations/summary/port.ts +21 -0
  59. package/template/integrations/summary/registry.ts +52 -0
  60. package/template/package.json +2 -3
  61. package/template/runtime/index.ts +62 -0
  62. package/template/schema/index.ts +2 -0
  63. package/template/schema/note.ts +5 -2
  64. package/template/tsconfig.json +13 -2
  65. package/template/views/note.ts +1 -1
  66. package/dist/astrale.d.ts +0 -27
  67. package/dist/astrale.d.ts.map +0 -1
  68. package/dist/astrale.js +0 -212
  69. package/dist/astrale.js.map +0 -1
  70. package/src/astrale.ts +0 -244
  71. package/template/methods/index.ts +0 -66
  72. package/template/schema/compiled.ts +0 -14
package/dist/astrale.js DELETED
@@ -1,212 +0,0 @@
1
- /**
2
- * `astrale(envs)` — the Astrale-managed deployment adapter.
3
- *
4
- * Ships the domain THROUGH the platform instead of to the author's own cloud
5
- * account: `deploy` builds the same single-module workerd bundle the Cloudflare
6
- * adapter ships (shared codegen + `wrangler deploy --dry-run`), then publishes
7
- * it via the admin domain's catalog — `DomainPublished.register` →
8
- * `::release { bundleBase64 }` (the worker stages the bytes in the platform
9
- * registry) → `::install { instanceId, source: { kind: 'package' } }`, which
10
- * deploys it as a host-local Service next to the target instance and installs
11
- * the domain on it. No Cloudflare account, no wrangler auth — the only
12
- * credential is the author's Astrale identity, supplied by the `astrale` CLI
13
- * session this adapter shells out to (the same trust source as
14
- * `astrale instance install`).
15
- *
16
- * `watch` is identical to the Cloudflare adapter's local dev (wrangler dev on
17
- * localhost) — managed deploys change WHERE the worker runs, not how you
18
- * iterate locally.
19
- *
20
- * Managed deploys ship the client SPA (served under `/ui` by the box) and
21
- * runtime secrets (dotenv map on the install call, encrypted at rest
22
- * platform-side; platform-managed env keys always win precedence).
23
- */
24
- import { defineAdapter, loadDotenvFile } from '@astrale-os/devkit';
25
- import { spawn } from 'node:child_process';
26
- import { existsSync } from 'node:fs';
27
- import { readFile } from 'node:fs/promises';
28
- import { join } from 'node:path';
29
- import { packAssets } from './assets-pack';
30
- import { buildClient } from './client';
31
- import { logTo, prepare } from './cloudflare';
32
- import { runWranglerBundle, runWranglerDev } from './wrangler-cli';
33
- const DEFAULT_PORT = 8787;
34
- const DEFAULT_ADMIN_URL = 'https://admin.eu.astrale.ai/api';
35
- const DEFAULT_REGION = 'eu';
36
- const ADMIN_ORIGIN = 'admin.astrale.ai';
37
- export function astrale(envs) {
38
- return defineAdapter({
39
- name: 'astrale',
40
- envs,
41
- // Local dev is unchanged: wrangler dev on localhost. Managed deploys change
42
- // WHERE the worker ships, not the inner loop.
43
- async watch(params, ctx) {
44
- const { configPath } = await prepare({
45
- ...(params.vars ? { vars: params.vars } : {}),
46
- ...(params.host ? { host: params.host } : {}),
47
- port: params.port ?? DEFAULT_PORT,
48
- }, ctx, 'dev');
49
- const handle = await runWranglerDev({
50
- projectDir: ctx.projectDir,
51
- configPath,
52
- port: params.port ?? DEFAULT_PORT,
53
- remote: false,
54
- autoPickPort: params.port === undefined,
55
- ...(params.host ? { ip: '0.0.0.0' } : {}),
56
- onReload: ctx.onReload,
57
- onLog: logTo(),
58
- });
59
- return { url: params.host ?? handle.url, stop: handle.stop };
60
- },
61
- async deploy(params, ctx) {
62
- const log = logTo();
63
- if (!params.instance) {
64
- throw new Error(`astrale adapter: this env has no "instance" — managed deploys need the target ` +
65
- `instance slug (e.g. prod: { instance: '<your-instance-slug>' }).`);
66
- }
67
- // Build + pack the client SPA: managed services serve it under /ui (the
68
- // platform stages the archive and the box downloads it at Service.init).
69
- let assetsGz = null;
70
- if (ctx.clientDir) {
71
- await buildClient(ctx.clientDir, ctx.projectDir, log);
72
- assetsGz = packAssets(join(ctx.projectDir, 'dist-client'));
73
- if (assetsGz)
74
- log(`packed client SPA (${assetsGz.length} bytes gz) — /ui ships managed`);
75
- }
76
- // 1. Codegen + bundle: the exact worker module a Cloudflare deploy would
77
- // ship, produced locally with `wrangler deploy --dry-run` (no auth).
78
- // `clientDir` is stripped: managed packages don't ship SPA assets yet,
79
- // and leaving it in would put a dangling `assets.directory` (the
80
- // unbuilt dist-client) into the generated config.
81
- const { clientDir: _omitted, ...bundleCtx } = ctx;
82
- const { configPath } = await prepare({}, bundleCtx, 'dev');
83
- const outDir = join(ctx.projectDir, '.astrale', 'dist-managed');
84
- const bundlePath = await runWranglerBundle({
85
- projectDir: ctx.projectDir,
86
- configPath,
87
- outDir,
88
- onLog: log,
89
- });
90
- const bundle = await readFile(bundlePath);
91
- // 2. Publish through the platform, authenticated by the author's astrale
92
- // CLI session. The release payload rides STDIN — a bundle is megabytes
93
- // of base64, far past argv limits.
94
- const name = params.name ?? packageNameFor(ctx.domain.origin);
95
- const adminUrl = params.adminUrl ?? DEFAULT_ADMIN_URL;
96
- const version = `0.0.0-managed.${Date.now()}`;
97
- log(`registering "${name}" (${ctx.domain.origin}) in the platform catalog…`);
98
- await astraleCall(ctx.projectDir, params, adminUrl, {
99
- path: `/${ADMIN_ORIGIN}/class.DomainPublished/register`,
100
- data: { origin: ctx.domain.origin, name },
101
- });
102
- log(`publishing ${name}@${version} (${bundle.length} bytes)…`);
103
- await astraleCall(ctx.projectDir, params, adminUrl, {
104
- path: `/admin/domains/${name}::release`,
105
- data: {
106
- version,
107
- bundleBase64: bundle.toString('base64'),
108
- makeCurrent: true,
109
- ...(assetsGz ? { assetsGzBase64: assetsGz.toString('base64') } : {}),
110
- },
111
- viaStdin: true,
112
- });
113
- // Author runtime secrets: read the env's dotenv locally, ship the map on
114
- // the INSTALL call (never the release — secrets are per instance, never
115
- // catalog-resident). Rides stdin so values never appear in argv.
116
- let secrets;
117
- if (params.secrets) {
118
- secrets = loadDotenvFile(join(ctx.projectDir, params.secrets));
119
- log(`shipping ${Object.keys(secrets).length} secret(s) from ${params.secrets}…`);
120
- }
121
- log(`installing on instance "${params.instance}"…`);
122
- const installed = (await astraleCall(ctx.projectDir, params, adminUrl, {
123
- path: `/admin/domains/${name}::install`,
124
- data: {
125
- instanceId: params.instance,
126
- source: { kind: 'package' },
127
- ...(secrets ? { secrets } : {}),
128
- },
129
- viaStdin: true,
130
- }));
131
- if (installed.error || installed.state !== 'installed') {
132
- throw new Error(`managed install failed: state=${installed.state ?? '?'} error=${installed.error ?? '?'}`);
133
- }
134
- if (!installed.serviceSlug) {
135
- throw new Error('managed install returned no serviceSlug — cannot derive the service URL');
136
- }
137
- const region = params.region ?? DEFAULT_REGION;
138
- const url = `https://${installed.serviceSlug}.svc.${region}.astrale.ai`;
139
- return {
140
- url,
141
- // Managed deploys already installed on the instance — override the
142
- // devkit's default "install on an instance" footer with the truth.
143
- nextSteps: ` installed on "${params.instance}" — call it:\n` +
144
- ` astrale call "/${ctx.domain.origin}/..." -i ${params.instance}`,
145
- };
146
- },
147
- secretsFile(params) {
148
- return params.secrets;
149
- },
150
- });
151
- }
152
- /** Catalog package name from the origin: first DNS label (e.g. `my-notes.example.dev` → `my-notes`). */
153
- function packageNameFor(origin) {
154
- const label = origin.split('.')[0] ?? origin;
155
- return label.toLowerCase().replace(/[^a-z0-9-]+/g, '-');
156
- }
157
- /**
158
- * Invoke the user's `astrale` CLI for one platform call and parse its JSON
159
- * output. The CLI owns identity (IdP session, audience scoping, delegation
160
- * minting) — reimplementing that here would fork the trust path.
161
- */
162
- async function astraleCall(projectDir, params, adminUrl, call) {
163
- // Saga-sized timeout: a COLD managed install (fresh service on the host)
164
- // runs runtime staging + serve probes and regularly exceeds the CLI's 30s
165
- // default — which doesn't just fail the client, it can kill the saga
166
- // mid-flight. Same budget as `astrale instance create`.
167
- const args = ['call', call.path, '--url', adminUrl, '--json', '--timeout', '240000'];
168
- if (params.identity)
169
- args.push('--as', params.identity);
170
- const payload = JSON.stringify(call.data);
171
- if (!call.viaStdin)
172
- args.push('--data', payload);
173
- const { code, out } = await new Promise((resolve, reject) => {
174
- const child = spawn(astraleBin(projectDir), args, {
175
- cwd: projectDir,
176
- stdio: [call.viaStdin ? 'pipe' : 'ignore', 'pipe', 'pipe'],
177
- });
178
- let out = '';
179
- child.stdout?.on('data', (b) => (out += b.toString()));
180
- child.stderr?.on('data', (b) => (out += b.toString()));
181
- child.on('exit', (c) => resolve({ code: c ?? 1, out }));
182
- child.on('error', reject);
183
- if (call.viaStdin) {
184
- child.stdin?.write(payload);
185
- child.stdin?.end();
186
- }
187
- });
188
- if (code !== 0) {
189
- // Only suggest re-login for AUTH-shaped failures — a timeout or audience
190
- // error pointed at "auth login" sends users chasing the wrong fix.
191
- const authShaped = /AUTH_ERROR|expired|not signed in|credential/i.test(out);
192
- throw new Error(`astrale call ${call.path} failed (exit ${code}): ${out.trim().slice(0, 500)}` +
193
- (authShaped ? `\nIs the astrale CLI installed and signed in? (astrale auth login)` : ''));
194
- }
195
- try {
196
- return JSON.parse(out);
197
- }
198
- catch {
199
- throw new Error(`astrale call ${call.path}: could not parse CLI output: ${out.slice(0, 300)}`);
200
- }
201
- }
202
- /** The user's astrale CLI: ~/.astrale/bin/astrale when present, else PATH. */
203
- function astraleBin(_projectDir) {
204
- const home = process.env.HOME;
205
- if (home) {
206
- const installed = join(home, '.astrale', 'bin', 'astrale');
207
- if (existsSync(installed))
208
- return installed;
209
- }
210
- return 'astrale';
211
- }
212
- //# sourceMappingURL=astrale.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"astrale.js","sourceRoot":"","sources":["../src/astrale.ts"],"names":[],"mappings":"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"}
package/src/astrale.ts DELETED
@@ -1,244 +0,0 @@
1
- /**
2
- * `astrale(envs)` — the Astrale-managed deployment adapter.
3
- *
4
- * Ships the domain THROUGH the platform instead of to the author's own cloud
5
- * account: `deploy` builds the same single-module workerd bundle the Cloudflare
6
- * adapter ships (shared codegen + `wrangler deploy --dry-run`), then publishes
7
- * it via the admin domain's catalog — `DomainPublished.register` →
8
- * `::release { bundleBase64 }` (the worker stages the bytes in the platform
9
- * registry) → `::install { instanceId, source: { kind: 'package' } }`, which
10
- * deploys it as a host-local Service next to the target instance and installs
11
- * the domain on it. No Cloudflare account, no wrangler auth — the only
12
- * credential is the author's Astrale identity, supplied by the `astrale` CLI
13
- * session this adapter shells out to (the same trust source as
14
- * `astrale instance install`).
15
- *
16
- * `watch` is identical to the Cloudflare adapter's local dev (wrangler dev on
17
- * localhost) — managed deploys change WHERE the worker runs, not how you
18
- * iterate locally.
19
- *
20
- * Managed deploys ship the client SPA (served under `/ui` by the box) and
21
- * runtime secrets (dotenv map on the install call, encrypted at rest
22
- * platform-side; platform-managed env keys always win precedence).
23
- */
24
-
25
- import type { DomainAdapter } from '@astrale-os/devkit'
26
-
27
- import { defineAdapter, loadDotenvFile } from '@astrale-os/devkit'
28
- import { spawn } from 'node:child_process'
29
- import { existsSync } from 'node:fs'
30
- import { readFile } from 'node:fs/promises'
31
- import { join } from 'node:path'
32
-
33
- import type { AstraleParams } from './params'
34
-
35
- import { packAssets } from './assets-pack'
36
- import { buildClient } from './client'
37
- import { logTo, prepare } from './cloudflare'
38
- import { runWranglerBundle, runWranglerDev } from './wrangler-cli'
39
-
40
- const DEFAULT_PORT = 8787
41
- const DEFAULT_ADMIN_URL = 'https://admin.eu.astrale.ai/api'
42
- const DEFAULT_REGION = 'eu'
43
- const ADMIN_ORIGIN = 'admin.astrale.ai'
44
-
45
- export function astrale(envs: Record<string, AstraleParams>): DomainAdapter<AstraleParams> {
46
- return defineAdapter<AstraleParams>({
47
- name: 'astrale',
48
- envs,
49
-
50
- // Local dev is unchanged: wrangler dev on localhost. Managed deploys change
51
- // WHERE the worker ships, not the inner loop.
52
- async watch(params, ctx) {
53
- const { configPath } = await prepare(
54
- {
55
- ...(params.vars ? { vars: params.vars } : {}),
56
- ...(params.host ? { host: params.host } : {}),
57
- port: params.port ?? DEFAULT_PORT,
58
- },
59
- ctx,
60
- 'dev',
61
- )
62
- const handle = await runWranglerDev({
63
- projectDir: ctx.projectDir,
64
- configPath,
65
- port: params.port ?? DEFAULT_PORT,
66
- remote: false,
67
- autoPickPort: params.port === undefined,
68
- ...(params.host ? { ip: '0.0.0.0' } : {}),
69
- onReload: ctx.onReload,
70
- onLog: logTo(),
71
- })
72
- return { url: params.host ?? handle.url, stop: handle.stop }
73
- },
74
-
75
- async deploy(params, ctx) {
76
- const log = logTo()
77
- if (!params.instance) {
78
- throw new Error(
79
- `astrale adapter: this env has no "instance" — managed deploys need the target ` +
80
- `instance slug (e.g. prod: { instance: '<your-instance-slug>' }).`,
81
- )
82
- }
83
- // Build + pack the client SPA: managed services serve it under /ui (the
84
- // platform stages the archive and the box downloads it at Service.init).
85
- let assetsGz: Buffer | null = null
86
- if (ctx.clientDir) {
87
- await buildClient(ctx.clientDir, ctx.projectDir, log)
88
- assetsGz = packAssets(join(ctx.projectDir, 'dist-client'))
89
- if (assetsGz) log(`packed client SPA (${assetsGz.length} bytes gz) — /ui ships managed`)
90
- }
91
-
92
- // 1. Codegen + bundle: the exact worker module a Cloudflare deploy would
93
- // ship, produced locally with `wrangler deploy --dry-run` (no auth).
94
- // `clientDir` is stripped: managed packages don't ship SPA assets yet,
95
- // and leaving it in would put a dangling `assets.directory` (the
96
- // unbuilt dist-client) into the generated config.
97
- const { clientDir: _omitted, ...bundleCtx } = ctx
98
- const { configPath } = await prepare({}, bundleCtx, 'dev')
99
- const outDir = join(ctx.projectDir, '.astrale', 'dist-managed')
100
- const bundlePath = await runWranglerBundle({
101
- projectDir: ctx.projectDir,
102
- configPath,
103
- outDir,
104
- onLog: log,
105
- })
106
- const bundle = await readFile(bundlePath)
107
-
108
- // 2. Publish through the platform, authenticated by the author's astrale
109
- // CLI session. The release payload rides STDIN — a bundle is megabytes
110
- // of base64, far past argv limits.
111
- const name = params.name ?? packageNameFor(ctx.domain.origin)
112
- const adminUrl = params.adminUrl ?? DEFAULT_ADMIN_URL
113
- const version = `0.0.0-managed.${Date.now()}`
114
-
115
- log(`registering "${name}" (${ctx.domain.origin}) in the platform catalog…`)
116
- await astraleCall(ctx.projectDir, params, adminUrl, {
117
- path: `/${ADMIN_ORIGIN}/class.DomainPublished/register`,
118
- data: { origin: ctx.domain.origin, name },
119
- })
120
-
121
- log(`publishing ${name}@${version} (${bundle.length} bytes)…`)
122
- await astraleCall(ctx.projectDir, params, adminUrl, {
123
- path: `/admin/domains/${name}::release`,
124
- data: {
125
- version,
126
- bundleBase64: bundle.toString('base64'),
127
- makeCurrent: true,
128
- ...(assetsGz ? { assetsGzBase64: assetsGz.toString('base64') } : {}),
129
- },
130
- viaStdin: true,
131
- })
132
-
133
- // Author runtime secrets: read the env's dotenv locally, ship the map on
134
- // the INSTALL call (never the release — secrets are per instance, never
135
- // catalog-resident). Rides stdin so values never appear in argv.
136
- let secrets: Record<string, string> | undefined
137
- if (params.secrets) {
138
- secrets = loadDotenvFile(join(ctx.projectDir, params.secrets))
139
- log(`shipping ${Object.keys(secrets).length} secret(s) from ${params.secrets}…`)
140
- }
141
-
142
- log(`installing on instance "${params.instance}"…`)
143
- const installed = (await astraleCall(ctx.projectDir, params, adminUrl, {
144
- path: `/admin/domains/${name}::install`,
145
- data: {
146
- instanceId: params.instance,
147
- source: { kind: 'package' },
148
- ...(secrets ? { secrets } : {}),
149
- },
150
- viaStdin: true,
151
- })) as { serviceSlug?: string; state?: string; error?: string | null }
152
-
153
- if (installed.error || installed.state !== 'installed') {
154
- throw new Error(
155
- `managed install failed: state=${installed.state ?? '?'} error=${installed.error ?? '?'}`,
156
- )
157
- }
158
- if (!installed.serviceSlug) {
159
- throw new Error('managed install returned no serviceSlug — cannot derive the service URL')
160
- }
161
- const region = params.region ?? DEFAULT_REGION
162
- const url = `https://${installed.serviceSlug}.svc.${region}.astrale.ai`
163
- return {
164
- url,
165
- // Managed deploys already installed on the instance — override the
166
- // devkit's default "install on an instance" footer with the truth.
167
- nextSteps:
168
- ` installed on "${params.instance}" — call it:\n` +
169
- ` astrale call "/${ctx.domain.origin}/..." -i ${params.instance}`,
170
- }
171
- },
172
-
173
- secretsFile(params) {
174
- return params.secrets
175
- },
176
- })
177
- }
178
-
179
- /** Catalog package name from the origin: first DNS label (e.g. `my-notes.example.dev` → `my-notes`). */
180
- function packageNameFor(origin: string): string {
181
- const label = origin.split('.')[0] ?? origin
182
- return label.toLowerCase().replace(/[^a-z0-9-]+/g, '-')
183
- }
184
-
185
- /**
186
- * Invoke the user's `astrale` CLI for one platform call and parse its JSON
187
- * output. The CLI owns identity (IdP session, audience scoping, delegation
188
- * minting) — reimplementing that here would fork the trust path.
189
- */
190
- async function astraleCall(
191
- projectDir: string,
192
- params: AstraleParams,
193
- adminUrl: string,
194
- call: { path: string; data: unknown; viaStdin?: boolean },
195
- ): Promise<unknown> {
196
- // Saga-sized timeout: a COLD managed install (fresh service on the host)
197
- // runs runtime staging + serve probes and regularly exceeds the CLI's 30s
198
- // default — which doesn't just fail the client, it can kill the saga
199
- // mid-flight. Same budget as `astrale instance create`.
200
- const args = ['call', call.path, '--url', adminUrl, '--json', '--timeout', '240000']
201
- if (params.identity) args.push('--as', params.identity)
202
- const payload = JSON.stringify(call.data)
203
- if (!call.viaStdin) args.push('--data', payload)
204
-
205
- const { code, out } = await new Promise<{ code: number; out: string }>((resolve, reject) => {
206
- const child = spawn(astraleBin(projectDir), args, {
207
- cwd: projectDir,
208
- stdio: [call.viaStdin ? 'pipe' : 'ignore', 'pipe', 'pipe'],
209
- })
210
- let out = ''
211
- child.stdout?.on('data', (b: Buffer) => (out += b.toString()))
212
- child.stderr?.on('data', (b: Buffer) => (out += b.toString()))
213
- child.on('exit', (c) => resolve({ code: c ?? 1, out }))
214
- child.on('error', reject)
215
- if (call.viaStdin) {
216
- child.stdin?.write(payload)
217
- child.stdin?.end()
218
- }
219
- })
220
- if (code !== 0) {
221
- // Only suggest re-login for AUTH-shaped failures — a timeout or audience
222
- // error pointed at "auth login" sends users chasing the wrong fix.
223
- const authShaped = /AUTH_ERROR|expired|not signed in|credential/i.test(out)
224
- throw new Error(
225
- `astrale call ${call.path} failed (exit ${code}): ${out.trim().slice(0, 500)}` +
226
- (authShaped ? `\nIs the astrale CLI installed and signed in? (astrale auth login)` : ''),
227
- )
228
- }
229
- try {
230
- return JSON.parse(out)
231
- } catch {
232
- throw new Error(`astrale call ${call.path}: could not parse CLI output: ${out.slice(0, 300)}`)
233
- }
234
- }
235
-
236
- /** The user's astrale CLI: ~/.astrale/bin/astrale when present, else PATH. */
237
- function astraleBin(_projectDir: string): string {
238
- const home = process.env.HOME
239
- if (home) {
240
- const installed = join(home, '.astrale', 'bin', 'astrale')
241
- if (existsSync(installed)) return installed
242
- }
243
- return 'astrale'
244
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Worker method wiring — the `methods` the codegen'd worker entry mounts. Thin
3
- * adapters around the shared logic in `./note`: the only thing that lives here
4
- * is the SDK typing and the `kernel` null-guard.
5
- *
6
- * - `createNote` is interface-hosted (static) → `remoteInterfaceMethods`.
7
- * - `reference` is class-hosted (instance) → `remoteMethod` +
8
- * `remoteClassMethods`.
9
- * - `seed` is class-hosted (static) — the `postInstall` bootstrap.
10
- *
11
- * SDK-level `authorize` is an additive throw-to-deny check (returns void). For
12
- * finer worker checks see `assertPerm` / `requireOwnership` from
13
- * `@astrale-os/sdk`.
14
- */
15
- import {
16
- remoteClassMethods,
17
- remoteInterfaceMethods,
18
- remoteMethod,
19
- type SchemaMethodsImpl,
20
- } from '@astrale-os/sdk'
21
-
22
- import type { Env } from '../env'
23
-
24
- import { schema } from '../schema'
25
- import {
26
- createNote as createNoteLogic,
27
- reference as referenceLogic,
28
- seed as seedLogic,
29
- } from './note'
30
-
31
- const method = remoteMethod<Env>()
32
- const interfaceMethods = remoteInterfaceMethods<Env>()
33
- const classMethods = remoteClassMethods<Env>()
34
-
35
- const NoteOpsMethods = interfaceMethods(schema, 'NoteOps', {
36
- createNote: {
37
- authorize: async () => undefined,
38
- execute: ({ kernel, params }) => {
39
- if (!kernel) throw new Error('createNote requires a kernel credential')
40
- return createNoteLogic(kernel, params)
41
- },
42
- },
43
- })
44
-
45
- const reference = method(schema, 'Note', 'reference', {
46
- authorize: async () => undefined,
47
- execute: ({ kernel, self, params }) => {
48
- if (!kernel) throw new Error('reference requires a kernel credential')
49
- return referenceLogic(kernel, self.path.raw, params)
50
- },
51
- })
52
-
53
- const seed = method(schema, 'Note', 'seed', {
54
- authorize: async () => undefined,
55
- execute: ({ kernel }) => {
56
- if (!kernel) throw new Error('seed requires a kernel credential')
57
- return seedLogic(kernel)
58
- },
59
- })
60
-
61
- const NoteMethods = classMethods(schema, 'Note', { reference, seed })
62
-
63
- export const methods: SchemaMethodsImpl<typeof schema, Env> = {
64
- interface: { NoteOps: NoteOpsMethods },
65
- class: { Note: NoteMethods },
66
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Compiled view of the schema — resolved class/interface paths + prop keys.
3
- * `compileDomain` is pure (no env), so this is safe to import from the worker
4
- * and from build tooling alike.
5
- *
6
- * - `D.Note.path.class.raw` → the Note ClassPath, graph-facing form
7
- * - `D.references.path.class.raw` → the references edge ClassPath
8
- * - `D.Note.title.key` → the qualified prop key for `title`
9
- */
10
- import { compileDomain, type Domain } from '@astrale-os/kernel-core/domain'
11
-
12
- import { schema } from './index'
13
-
14
- export const D: Domain<typeof schema> = compileDomain(schema)