@astrale-os/adapter-cloudflare 0.1.4 → 0.1.5
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/dist/assets-pack.d.ts +8 -0
- package/dist/assets-pack.d.ts.map +1 -0
- package/dist/assets-pack.js +30 -0
- package/dist/assets-pack.js.map +1 -0
- package/dist/astrale.d.ts.map +1 -1
- package/dist/astrale.js +30 -5
- package/dist/astrale.js.map +1 -1
- package/dist/params.d.ts +1 -1
- package/dist/params.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/assets-pack.ts +32 -0
- package/src/astrale.ts +30 -7
- package/src/params.ts +1 -1
- package/template/.agents/skills/astrale-domain/SKILL.md +29 -11
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pack a built client SPA (`dist-client/`) into the host box's asset-archive
|
|
3
|
+
* format: `gzip(JSON [{ path, contentBase64 }])` — the exact shape
|
|
4
|
+
* `downloadAssets` on the box consumes (kernel/host workerd service layout).
|
|
5
|
+
*/
|
|
6
|
+
/** Gzip the SPA dir into the box's asset archive. Returns null when empty. */
|
|
7
|
+
export declare function packAssets(distClientDir: string): Buffer | null;
|
|
8
|
+
//# sourceMappingURL=assets-pack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets-pack.d.ts","sourceRoot":"","sources":["../src/assets-pack.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqBH,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pack a built client SPA (`dist-client/`) into the host box's asset-archive
|
|
3
|
+
* format: `gzip(JSON [{ path, contentBase64 }])` — the exact shape
|
|
4
|
+
* `downloadAssets` on the box consumes (kernel/host workerd service layout).
|
|
5
|
+
*/
|
|
6
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
7
|
+
import { join, relative } from 'node:path';
|
|
8
|
+
import { gzipSync } from 'node:zlib';
|
|
9
|
+
function walk(dir, root, out) {
|
|
10
|
+
for (const name of readdirSync(dir)) {
|
|
11
|
+
const full = join(dir, name);
|
|
12
|
+
if (statSync(full).isDirectory())
|
|
13
|
+
walk(full, root, out);
|
|
14
|
+
else {
|
|
15
|
+
out.push({
|
|
16
|
+
path: relative(root, full).split('\\').join('/'),
|
|
17
|
+
contentBase64: readFileSync(full).toString('base64'),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Gzip the SPA dir into the box's asset archive. Returns null when empty. */
|
|
23
|
+
export function packAssets(distClientDir) {
|
|
24
|
+
const files = [];
|
|
25
|
+
walk(distClientDir, distClientDir, files);
|
|
26
|
+
if (files.length === 0)
|
|
27
|
+
return null;
|
|
28
|
+
return gzipSync(Buffer.from(JSON.stringify(files)));
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=assets-pack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets-pack.js","sourceRoot":"","sources":["../src/assets-pack.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAIpC,SAAS,IAAI,CAAC,GAAW,EAAE,IAAY,EAAE,GAAgB;IACvD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAC5B,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;aAClD,CAAC;YACJ,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;gBAChD,aAAa,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;aACrD,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,aAAqB;IAC9C,MAAM,KAAK,GAAgB,EAAE,CAAA;IAC7B,IAAI,CAAC,aAAa,EAAE,aAAa,EAAE,KAAK,CAAC,CAAA;IACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnC,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACrD,CAAC"}
|
package/dist/astrale.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astrale.d.ts","sourceRoot":"","sources":["../src/astrale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAQvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"astrale.d.ts","sourceRoot":"","sources":["../src/astrale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAQvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAY7C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,aAAa,CAAC,aAAa,CAAC,CAsHzF"}
|
package/dist/astrale.js
CHANGED
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
* serve no `/ui` yet) and no runtime secrets reach the service — the bundle
|
|
22
22
|
* must be self-contained (its signing identity is baked in by the codegen).
|
|
23
23
|
*/
|
|
24
|
-
import { defineAdapter } from '@astrale-os/devkit';
|
|
24
|
+
import { defineAdapter, loadDotenvFile } from '@astrale-os/devkit';
|
|
25
25
|
import { spawn } from 'node:child_process';
|
|
26
26
|
import { existsSync } from 'node:fs';
|
|
27
27
|
import { readFile } from 'node:fs/promises';
|
|
28
28
|
import { join } from 'node:path';
|
|
29
|
+
import { packAssets } from './assets-pack';
|
|
30
|
+
import { buildClient } from './client';
|
|
29
31
|
import { logTo, prepare } from './cloudflare';
|
|
30
32
|
import { runWranglerBundle, runWranglerDev } from './wrangler-cli';
|
|
31
33
|
const DEFAULT_PORT = 8787;
|
|
@@ -56,9 +58,14 @@ export function astrale(envs) {
|
|
|
56
58
|
throw new Error(`astrale adapter: this env has no "instance" — managed deploys need the target ` +
|
|
57
59
|
`instance slug (e.g. prod: { instance: '<your-instance-slug>' }).`);
|
|
58
60
|
}
|
|
61
|
+
// Build + pack the client SPA: managed services serve it under /ui (the
|
|
62
|
+
// platform stages the archive and the box downloads it at Service.init).
|
|
63
|
+
let assetsGz = null;
|
|
59
64
|
if (ctx.clientDir) {
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
await buildClient(ctx.clientDir, ctx.projectDir, log);
|
|
66
|
+
assetsGz = packAssets(join(ctx.projectDir, 'dist-client'));
|
|
67
|
+
if (assetsGz)
|
|
68
|
+
log(`packed client SPA (${assetsGz.length} bytes gz) — /ui ships managed`);
|
|
62
69
|
}
|
|
63
70
|
// 1. Codegen + bundle: the exact worker module a Cloudflare deploy would
|
|
64
71
|
// ship, produced locally with `wrangler deploy --dry-run` (no auth).
|
|
@@ -89,13 +96,31 @@ export function astrale(envs) {
|
|
|
89
96
|
log(`publishing ${name}@${version} (${bundle.length} bytes)…`);
|
|
90
97
|
await astraleCall(ctx.projectDir, params, adminUrl, {
|
|
91
98
|
path: `/admin/domains/${name}::release`,
|
|
92
|
-
data: {
|
|
99
|
+
data: {
|
|
100
|
+
version,
|
|
101
|
+
bundleBase64: bundle.toString('base64'),
|
|
102
|
+
makeCurrent: true,
|
|
103
|
+
...(assetsGz ? { assetsGzBase64: assetsGz.toString('base64') } : {}),
|
|
104
|
+
},
|
|
93
105
|
viaStdin: true,
|
|
94
106
|
});
|
|
107
|
+
// Author runtime secrets: read the env's dotenv locally, ship the map on
|
|
108
|
+
// the INSTALL call (never the release — secrets are per instance, never
|
|
109
|
+
// catalog-resident). Rides stdin so values never appear in argv.
|
|
110
|
+
let secrets;
|
|
111
|
+
if (params.secrets) {
|
|
112
|
+
secrets = loadDotenvFile(join(ctx.projectDir, params.secrets));
|
|
113
|
+
log(`shipping ${Object.keys(secrets).length} secret(s) from ${params.secrets}…`);
|
|
114
|
+
}
|
|
95
115
|
log(`installing on instance "${params.instance}"…`);
|
|
96
116
|
const installed = (await astraleCall(ctx.projectDir, params, adminUrl, {
|
|
97
117
|
path: `/admin/domains/${name}::install`,
|
|
98
|
-
data: {
|
|
118
|
+
data: {
|
|
119
|
+
instanceId: params.instance,
|
|
120
|
+
source: { kind: 'package' },
|
|
121
|
+
...(secrets ? { secrets } : {}),
|
|
122
|
+
},
|
|
123
|
+
viaStdin: true,
|
|
99
124
|
}));
|
|
100
125
|
if (installed.error || installed.state !== 'installed') {
|
|
101
126
|
throw new Error(`managed install failed: state=${installed.state ?? '?'} error=${installed.error ?? '?'}`);
|
package/dist/astrale.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astrale.js","sourceRoot":"","sources":["../src/astrale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"astrale.js","sourceRoot":"","sources":["../src/astrale.ts"],"names":[],"mappings":"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"}
|
package/dist/params.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export interface AstraleParams {
|
|
|
63
63
|
region?: string;
|
|
64
64
|
/** CLI identity (`--as`) for the publish calls. Default: the CLI's active identity. */
|
|
65
65
|
identity?: string;
|
|
66
|
-
/** Gitignored secrets file
|
|
66
|
+
/** Gitignored secrets file. `watch`: injected into local wrangler dev. `deploy`: shipped on the install call and applied to the managed service env (encrypted at rest platform-side; platform keys win precedence). */
|
|
67
67
|
secrets?: string;
|
|
68
68
|
/** Local dev port for `wrangler dev`. Default 8787. */
|
|
69
69
|
port?: number;
|
package/dist/params.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,
|
|
1
|
+
{"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../src/params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wNAAwN;IACxN,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC9B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/adapter-cloudflare",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Deploy an Astrale domain as a standalone Cloudflare Worker",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adapter",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"jose": "^6.1.3",
|
|
31
|
-
"@astrale-os/devkit": "^0.1.
|
|
31
|
+
"@astrale-os/devkit": "^0.1.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@astrale-os/ox": ">=0.1.0 <1.0.0",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pack a built client SPA (`dist-client/`) into the host box's asset-archive
|
|
3
|
+
* format: `gzip(JSON [{ path, contentBase64 }])` — the exact shape
|
|
4
|
+
* `downloadAssets` on the box consumes (kernel/host workerd service layout).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs'
|
|
8
|
+
import { join, relative } from 'node:path'
|
|
9
|
+
import { gzipSync } from 'node:zlib'
|
|
10
|
+
|
|
11
|
+
type AssetFile = { path: string; contentBase64: string }
|
|
12
|
+
|
|
13
|
+
function walk(dir: string, root: string, out: AssetFile[]): void {
|
|
14
|
+
for (const name of readdirSync(dir)) {
|
|
15
|
+
const full = join(dir, name)
|
|
16
|
+
if (statSync(full).isDirectory()) walk(full, root, out)
|
|
17
|
+
else {
|
|
18
|
+
out.push({
|
|
19
|
+
path: relative(root, full).split('\\').join('/'),
|
|
20
|
+
contentBase64: readFileSync(full).toString('base64'),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Gzip the SPA dir into the box's asset archive. Returns null when empty. */
|
|
27
|
+
export function packAssets(distClientDir: string): Buffer | null {
|
|
28
|
+
const files: AssetFile[] = []
|
|
29
|
+
walk(distClientDir, distClientDir, files)
|
|
30
|
+
if (files.length === 0) return null
|
|
31
|
+
return gzipSync(Buffer.from(JSON.stringify(files)))
|
|
32
|
+
}
|
package/src/astrale.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import type { DomainAdapter } from '@astrale-os/devkit'
|
|
26
26
|
|
|
27
|
-
import { defineAdapter } from '@astrale-os/devkit'
|
|
27
|
+
import { defineAdapter, loadDotenvFile } from '@astrale-os/devkit'
|
|
28
28
|
import { spawn } from 'node:child_process'
|
|
29
29
|
import { existsSync } from 'node:fs'
|
|
30
30
|
import { readFile } from 'node:fs/promises'
|
|
@@ -32,6 +32,8 @@ import { join } from 'node:path'
|
|
|
32
32
|
|
|
33
33
|
import type { AstraleParams } from './params'
|
|
34
34
|
|
|
35
|
+
import { packAssets } from './assets-pack'
|
|
36
|
+
import { buildClient } from './client'
|
|
35
37
|
import { logTo, prepare } from './cloudflare'
|
|
36
38
|
import { runWranglerBundle, runWranglerDev } from './wrangler-cli'
|
|
37
39
|
|
|
@@ -72,11 +74,13 @@ export function astrale(envs: Record<string, AstraleParams>): DomainAdapter<Astr
|
|
|
72
74
|
`instance slug (e.g. prod: { instance: '<your-instance-slug>' }).`,
|
|
73
75
|
)
|
|
74
76
|
}
|
|
77
|
+
// Build + pack the client SPA: managed services serve it under /ui (the
|
|
78
|
+
// platform stages the archive and the box downloads it at Service.init).
|
|
79
|
+
let assetsGz: Buffer | null = null
|
|
75
80
|
if (ctx.clientDir) {
|
|
76
|
-
log
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
)
|
|
81
|
+
await buildClient(ctx.clientDir, ctx.projectDir, log)
|
|
82
|
+
assetsGz = packAssets(join(ctx.projectDir, 'dist-client'))
|
|
83
|
+
if (assetsGz) log(`packed client SPA (${assetsGz.length} bytes gz) — /ui ships managed`)
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
// 1. Codegen + bundle: the exact worker module a Cloudflare deploy would
|
|
@@ -111,14 +115,33 @@ export function astrale(envs: Record<string, AstraleParams>): DomainAdapter<Astr
|
|
|
111
115
|
log(`publishing ${name}@${version} (${bundle.length} bytes)…`)
|
|
112
116
|
await astraleCall(ctx.projectDir, params, adminUrl, {
|
|
113
117
|
path: `/admin/domains/${name}::release`,
|
|
114
|
-
data: {
|
|
118
|
+
data: {
|
|
119
|
+
version,
|
|
120
|
+
bundleBase64: bundle.toString('base64'),
|
|
121
|
+
makeCurrent: true,
|
|
122
|
+
...(assetsGz ? { assetsGzBase64: assetsGz.toString('base64') } : {}),
|
|
123
|
+
},
|
|
115
124
|
viaStdin: true,
|
|
116
125
|
})
|
|
117
126
|
|
|
127
|
+
// Author runtime secrets: read the env's dotenv locally, ship the map on
|
|
128
|
+
// the INSTALL call (never the release — secrets are per instance, never
|
|
129
|
+
// catalog-resident). Rides stdin so values never appear in argv.
|
|
130
|
+
let secrets: Record<string, string> | undefined
|
|
131
|
+
if (params.secrets) {
|
|
132
|
+
secrets = loadDotenvFile(join(ctx.projectDir, params.secrets))
|
|
133
|
+
log(`shipping ${Object.keys(secrets).length} secret(s) from ${params.secrets}…`)
|
|
134
|
+
}
|
|
135
|
+
|
|
118
136
|
log(`installing on instance "${params.instance}"…`)
|
|
119
137
|
const installed = (await astraleCall(ctx.projectDir, params, adminUrl, {
|
|
120
138
|
path: `/admin/domains/${name}::install`,
|
|
121
|
-
data: {
|
|
139
|
+
data: {
|
|
140
|
+
instanceId: params.instance,
|
|
141
|
+
source: { kind: 'package' },
|
|
142
|
+
...(secrets ? { secrets } : {}),
|
|
143
|
+
},
|
|
144
|
+
viaStdin: true,
|
|
122
145
|
})) as { serviceSlug?: string; state?: string; error?: string | null }
|
|
123
146
|
|
|
124
147
|
if (installed.error || installed.state !== 'installed') {
|
package/src/params.ts
CHANGED
|
@@ -64,7 +64,7 @@ export interface AstraleParams {
|
|
|
64
64
|
region?: string
|
|
65
65
|
/** CLI identity (`--as`) for the publish calls. Default: the CLI's active identity. */
|
|
66
66
|
identity?: string
|
|
67
|
-
/** Gitignored secrets file
|
|
67
|
+
/** Gitignored secrets file. `watch`: injected into local wrangler dev. `deploy`: shipped on the install call and applied to the managed service env (encrypted at rest platform-side; platform keys win precedence). */
|
|
68
68
|
secrets?: string
|
|
69
69
|
/** Local dev port for `wrangler dev`. Default 8787. */
|
|
70
70
|
port?: number
|
|
@@ -22,6 +22,7 @@ an RPC layer; you declare a contract and implement handlers.
|
|
|
22
22
|
npx -y create-astrale-domain@latest my-domain --yes # scaffold
|
|
23
23
|
cd my-domain && pnpm install
|
|
24
24
|
pnpm dev # local wrangler dev (prints a URL; install it on an instance to test)
|
|
25
|
+
pnpm dev --port 8899 # when 8787 is taken (orphan wrangler etc.)
|
|
25
26
|
pnpm prod # deploy + (astrale adapter) auto-install on your instance
|
|
26
27
|
```
|
|
27
28
|
|
|
@@ -163,8 +164,8 @@ Secrets & config:
|
|
|
163
164
|
the adapter's `secrets: '.env.dev' / '.env.prod'` (cloudflare adapter) —
|
|
164
165
|
never committed, never defaulted. Fail fast for root-of-trust values; allow
|
|
165
166
|
multi-name fallbacks only for developer convenience, never silently in prod.
|
|
166
|
-
-
|
|
167
|
-
|
|
167
|
+
- Both adapters ship secrets from `secrets: '.env.<env>'` — cloudflare via
|
|
168
|
+
wrangler secrets, astrale (managed) via the encrypted per-install store.
|
|
168
169
|
|
|
169
170
|
Reliability rules (learned from the admin provisioning engine):
|
|
170
171
|
- **Order effects**: external call FIRST, graph write AFTER when possible — a
|
|
@@ -194,10 +195,16 @@ Anti-patterns (all observed in production code — don't):
|
|
|
194
195
|
## 5 · Views & standalone functions (webhooks)
|
|
195
196
|
|
|
196
197
|
- `defineView({ auth, mount: '/ui/contact', viewFor: selfOf(Contact) })` in
|
|
197
|
-
`views/` + register in `views/index.ts
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
`views/` + register in `views/index.ts` — the MAP KEY is the view's node
|
|
199
|
+
slug (`'ui-contact'` → `/<origin>/core/views/ui-contact`). Installs a View
|
|
200
|
+
node whose binding URL = `<serving url><mount>` (managed:
|
|
201
|
+
`https://<slug>.svc.<region>.astrale.ai/ui/contact`). The client/ SPA
|
|
202
|
+
serves `/ui/*` — BOTH adapters ship it (cloudflare via Workers Assets;
|
|
203
|
+
managed via the platform's per-version asset archive); the SPA must handle
|
|
204
|
+
any `/ui/<route>` via its fallback (the scaffold's vite config does).
|
|
205
|
+
- Discovery: clients/GUIs find a node's views via
|
|
206
|
+
`kernel.call('/kernel.astrale.ai/class.View/resolve', { node: <path> })` →
|
|
207
|
+
`[{ path, url, name, origin }]` — `url` is the mounted iframe target.
|
|
201
208
|
- `functions/` declares standalone callables (`defineRemoteFunction`) not
|
|
202
209
|
attached to a class — each serves at `POST <worker>/functions/<slug>` and
|
|
203
210
|
materializes a Function node under `/<origin>/core/functions/`. This is the
|
|
@@ -211,8 +218,9 @@ For `auth: 'public'` upstreams that can't carry a header (HMAC-signature
|
|
|
211
218
|
webhooks, Stripe-style): `kernel` is null, but `ctx.selfKernel()` gives a
|
|
212
219
|
session authenticated as THE FUNCTION'S OWN identity (its grants only) —
|
|
213
220
|
VERIFY THE UPSTREAM SIGNATURE FIRST, then act as yourself. Needs
|
|
214
|
-
`deps.
|
|
215
|
-
|
|
221
|
+
`deps.INSTANCE_KERNEL_URL` (managed deploys set it) and the function identity
|
|
222
|
+
granted exactly what it writes (e.g. EDIT on the target folder + USE on
|
|
223
|
+
createNode + USE on the class — narrow, never root).
|
|
216
224
|
|
|
217
225
|
**Webhook idempotency** (senders retry — design for replays): derive a
|
|
218
226
|
DETERMINISTIC node path from the sender's id (`/contacts/lead-<externalId>`),
|
|
@@ -245,8 +253,10 @@ Adapter choice in `astrale.config.ts`:
|
|
|
245
253
|
- `astrale({ dev: {...}, prod: { instance: '<slug>' } })` — managed: publishes
|
|
246
254
|
the bundle THROUGH the platform and installs it as a host-local service next
|
|
247
255
|
to your instance (`https://<name>-<hash>.svc.<region>.astrale.ai`). No CF
|
|
248
|
-
account; auth = your `astrale auth login` session.
|
|
249
|
-
|
|
256
|
+
account; auth = your `astrale auth login` session. Ships the client SPA
|
|
257
|
+
(`/ui` serves managed) and author secrets (`prod.secrets: '.env.prod'` —
|
|
258
|
+
encrypted at rest platform-side, re-applied on redeploys; omit = keep,
|
|
259
|
+
`{}` = clear; platform keys always win).
|
|
250
260
|
|
|
251
261
|
The first deploy generates `.astrale/identity.ts` — the domain's SIGNING
|
|
252
262
|
IDENTITY (its private key). Losing or regenerating it breaks reinstalls under
|
|
@@ -264,6 +274,12 @@ service URL stable).
|
|
|
264
274
|
|
|
265
275
|
Manual install of any served domain: `astrale instance install <url>`.
|
|
266
276
|
|
|
277
|
+
The managed catalog surface (what `pnpm prod` shells into) is callable
|
|
278
|
+
directly — useful for recovery and inspection:
|
|
279
|
+
`/admin/domains/<name>::install {instanceId, source:{kind:'package'}}` ·
|
|
280
|
+
`::uninstall {instanceId}` (the un-wedge recipe before a retry) ·
|
|
281
|
+
`::installations` · `::versions` — all on the admin instance (`-i admin`).
|
|
282
|
+
|
|
267
283
|
## 8 · Testing
|
|
268
284
|
|
|
269
285
|
- **Logic**: unit-test with fake ports (the DI in §4 exists for this) and a
|
|
@@ -286,10 +302,12 @@ Manual install of any served domain: `astrale instance install <url>`.
|
|
|
286
302
|
| `Delegation mint failed for <url>` | check `--debug` cause chain; worker→worker call machinery |
|
|
287
303
|
| postInstall `not within origin` | tree path used — switch to `/:origin:class.X:method` |
|
|
288
304
|
| install: `missing remote binding` | a callable lacks `binding.remoteUrl` — build via the adapter, not hand-rolled specs |
|
|
289
|
-
| managed `/ui` 404 | managed adapter ships no SPA assets yet |
|
|
290
305
|
| `ERR_PNPM_IGNORED_BUILDS` / approve-builds on `pnpm run` | template's pnpm-workspace.yaml needs `ignoredBuiltDependencies` + `verifyDepsBeforeRun: false` (recent scaffolds have it) |
|
|
291
306
|
| stale/broken package versions on scaffold | clear pnpm metadata cache; check template floors are current |
|
|
292
307
|
| TS: "Types of property '__brand' are incompatible" in untouched files | TWO copies of kernel-core/dsl in the tree (mixed link:/registry/override resolution) — unify versions, then `pnpm dedupe` |
|
|
308
|
+
| runtime 500: `MISSING_DEF: Def at path "…" is not registered` | SAME dual-copy disease at runtime (defineSchema wrote copy A, compile read copy B) — and on managed installs it presents as the service never turning ready / install stuck `installing`. Unify + dedupe. |
|
|
309
|
+
| managed install stuck at `installing` | check the SERVICE first: `curl <svc>/meta` (500 = the bundle itself is broken — run it locally with wrangler to see the real error); then `…::uninstall {instanceId}` and re-run the install |
|
|
310
|
+
| `Path not found: /admin/instances/<uuid>` on install | `instanceId` takes the instance SLUG, not the node UUID (`astrale instance status <slug>` shows both) |
|
|
293
311
|
| deploy: `Export named 'X' not found` from an @astrale-os module | a transitive dep resolved below its REAL floor — `pnpm add @astrale-os/<pkg>@<needed>` then `pnpm dedupe` |
|
|
294
312
|
|
|
295
313
|
Use `astrale call <path> --describe` for any callable's schema, `--debug` for
|