blogwright 0.1.0

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 (63) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +12 -0
  3. package/agent/Dockerfile +20 -0
  4. package/agent/agent-manifest.json +3 -0
  5. package/agent/server.js +7935 -0
  6. package/dist/adapters/fetch-ping.d.ts +9 -0
  7. package/dist/adapters/fetch-ping.js +26 -0
  8. package/dist/adapters/fetch-ping.js.map +1 -0
  9. package/dist/adapters/process-vcs.d.ts +12 -0
  10. package/dist/adapters/process-vcs.js +49 -0
  11. package/dist/adapters/process-vcs.js.map +1 -0
  12. package/dist/agent-package.d.ts +19 -0
  13. package/dist/agent-package.js +49 -0
  14. package/dist/agent-package.js.map +1 -0
  15. package/dist/bin.d.ts +2 -0
  16. package/dist/bin.js +14 -0
  17. package/dist/bin.js.map +1 -0
  18. package/dist/cli.d.ts +6 -0
  19. package/dist/cli.js +249 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands.d.ts +31 -0
  22. package/dist/commands.js +269 -0
  23. package/dist/commands.js.map +1 -0
  24. package/dist/context.d.ts +50 -0
  25. package/dist/context.js +77 -0
  26. package/dist/context.js.map +1 -0
  27. package/dist/deploy.d.ts +57 -0
  28. package/dist/deploy.js +247 -0
  29. package/dist/deploy.js.map +1 -0
  30. package/dist/graph.d.ts +20 -0
  31. package/dist/graph.js +73 -0
  32. package/dist/graph.js.map +1 -0
  33. package/dist/init.d.ts +4 -0
  34. package/dist/init.js +92 -0
  35. package/dist/init.js.map +1 -0
  36. package/dist/logger.d.ts +18 -0
  37. package/dist/logger.js +34 -0
  38. package/dist/logger.js.map +1 -0
  39. package/dist/microvms.d.ts +15 -0
  40. package/dist/microvms.js +56 -0
  41. package/dist/microvms.js.map +1 -0
  42. package/dist/nodes.d.ts +34 -0
  43. package/dist/nodes.js +858 -0
  44. package/dist/nodes.js.map +1 -0
  45. package/dist/ports.d.ts +25 -0
  46. package/dist/ports.js +7 -0
  47. package/dist/ports.js.map +1 -0
  48. package/dist/render.d.ts +33 -0
  49. package/dist/render.js +81 -0
  50. package/dist/render.js.map +1 -0
  51. package/dist/repo.d.ts +25 -0
  52. package/dist/repo.js +75 -0
  53. package/dist/repo.js.map +1 -0
  54. package/dist/rkey.d.ts +6 -0
  55. package/dist/rkey.js +7 -0
  56. package/dist/rkey.js.map +1 -0
  57. package/dist/seo.d.ts +15 -0
  58. package/dist/seo.js +30 -0
  59. package/dist/seo.js.map +1 -0
  60. package/dist/test-support.d.ts +44 -0
  61. package/dist/test-support.js +120 -0
  62. package/dist/test-support.js.map +1 -0
  63. package/package.json +57 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Fetch adapter for the PingBuilder port: opens a connection to the builder
3
+ * MicroVM's proxy endpoint to wake the resumed agent's event loop. Errors never
4
+ * cross the port — the ping is best-effort by contract, and the agent's HTTP/1
5
+ * server may not even parse the request.
6
+ */
7
+ import type { PingBuilder } from '../ports.js';
8
+ /** Build the fetch-backed ping. `fetchImpl` is injectable for tests. */
9
+ export declare function createFetchPing(fetchImpl?: typeof fetch): PingBuilder;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Fetch adapter for the PingBuilder port: opens a connection to the builder
3
+ * MicroVM's proxy endpoint to wake the resumed agent's event loop. Errors never
4
+ * cross the port — the ping is best-effort by contract, and the agent's HTTP/1
5
+ * server may not even parse the request.
6
+ */
7
+ /** A nudge only needs the connection to land; never hold a poll cycle longer than this. */
8
+ const PING_TIMEOUT_MS = 2500;
9
+ /** Build the fetch-backed ping. `fetchImpl` is injectable for tests. */
10
+ export function createFetchPing(fetchImpl = fetch) {
11
+ return async (endpoint, token) => {
12
+ try {
13
+ const res = await fetchImpl(`https://${endpoint}/status`, {
14
+ headers: { 'X-aws-proxy-auth': token, 'X-aws-proxy-port': '8080' },
15
+ signal: AbortSignal.timeout(PING_TIMEOUT_MS),
16
+ });
17
+ // Release the connection — an unread body pins an undici socket per
18
+ // poll cycle until GC.
19
+ await res.body?.cancel();
20
+ }
21
+ catch {
22
+ /* expected — the point is the wake-up, not the response */
23
+ }
24
+ };
25
+ }
26
+ //# sourceMappingURL=fetch-ping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-ping.js","sourceRoot":"","sources":["../../src/adapters/fetch-ping.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,2FAA2F;AAC3F,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,wEAAwE;AACxE,MAAM,UAAU,eAAe,CAAC,YAA0B,KAAK;IAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,WAAW,QAAQ,SAAS,EAAE;gBACxD,OAAO,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE;gBAClE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC;aAC7C,CAAC,CAAC;YACH,oEAAoE;YACpE,uBAAuB;YACvB,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,2DAA2D;QAC7D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Process adapter for the Vcs port: shells out to jj/git. The only module
3
+ * outside the build-agent that may import node:child_process; failures are
4
+ * translated with the command and directory before they cross the port.
5
+ */
6
+ import type { Vcs } from '../ports.js';
7
+ /**
8
+ * Build the jj/git process adapter. The revision hash prefers jj's git commit
9
+ * id (jj auto-commits the working copy), falling back to git HEAD; listings
10
+ * honor .gitignore — tracked files plus untracked files that are not ignored.
11
+ */
12
+ export declare function createProcessVcs(): Vcs;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Process adapter for the Vcs port: shells out to jj/git. The only module
3
+ * outside the build-agent that may import node:child_process; failures are
4
+ * translated with the command and directory before they cross the port.
5
+ */
6
+ import { execFile } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ const run = promisify(execFile);
9
+ /** `git ls-files -z` output can exceed the 1 MiB default buffer on large repos. */
10
+ const MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
11
+ async function runVcsCommand(cwd, command, args) {
12
+ try {
13
+ const { stdout } = await run(command, args, { cwd, maxBuffer: MAX_OUTPUT_BYTES });
14
+ return stdout;
15
+ }
16
+ catch (err) {
17
+ throw new Error(`${command} ${args.join(' ')} failed in ${cwd}: ${err.message}`, {
18
+ cause: err,
19
+ });
20
+ }
21
+ }
22
+ /**
23
+ * Build the jj/git process adapter. The revision hash prefers jj's git commit
24
+ * id (jj auto-commits the working copy), falling back to git HEAD; listings
25
+ * honor .gitignore — tracked files plus untracked files that are not ignored.
26
+ */
27
+ export function createProcessVcs() {
28
+ return {
29
+ async revisionHash(cwd) {
30
+ try {
31
+ const jjArgs = ['log', '--no-graph', '-r', '@', '-T', 'commit_id.short()'];
32
+ const hash = (await runVcsCommand(cwd, 'jj', jjArgs)).trim();
33
+ if (hash)
34
+ return hash;
35
+ }
36
+ catch {
37
+ /* jj unavailable or not a jj repo — fall through to git */
38
+ }
39
+ return (await runVcsCommand(cwd, 'git', ['rev-parse', '--short', 'HEAD'])).trim();
40
+ },
41
+ async listFiles(cwd) {
42
+ // -z gives NUL-separated, un-quoted paths (correct for names with spaces/unicode).
43
+ const args = ['ls-files', '-z', '--cached', '--others', '--exclude-standard'];
44
+ const stdout = await runVcsCommand(cwd, 'git', args);
45
+ return stdout.split('\0').filter(Boolean);
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=process-vcs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-vcs.js","sourceRoot":"","sources":["../../src/adapters/process-vcs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEhC,mFAAmF;AACnF,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,KAAK,UAAU,aAAa,CAAC,GAAW,EAAE,OAAe,EAAE,IAAc;IACvE,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAClF,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE;YAC1F,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,KAAK,CAAC,YAAY,CAAC,GAAW;YAC5B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;gBAC3E,MAAM,IAAI,GAAG,CAAC,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7D,IAAI,IAAI;oBAAE,OAAO,IAAI,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,2DAA2D;YAC7D,CAAC;YACD,OAAO,CAAC,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpF,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,GAAW;YACzB,mFAAmF;YACnF,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,CAAC;YAC9E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACrD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Packages the build-agent artifacts (Dockerfile, bundled server.js,
3
+ * agent-manifest.json) into a reproducible zip and uploads it to S3. Reads the
4
+ * artifacts through the FileSystem port from the composition-root-resolved
5
+ * `ctx.agentDir`; this module touches no Node API directly.
6
+ */
7
+ import type { OpsContext } from './context.js';
8
+ /**
9
+ * Package the build-agent (Dockerfile + bundled server) into a zip and upload it to
10
+ * `build/agent/agent-<hash>.zip`. `<hash>` is the reproducible source hash stamped
11
+ * into agent-manifest.json when the agent was bundled — a hash of the agent's
12
+ * *source*, not the bundle, because bundle bytes vary by build platform/toolchain
13
+ * while source bytes are identical everywhere. The MicroVM image is then built from
14
+ * this artifact and keyed by the same hash, so identical source never rebuilds.
15
+ */
16
+ export declare function packageAndUploadAgent(ctx: OpsContext): Promise<{
17
+ key: string;
18
+ hash: string;
19
+ }>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Packages the build-agent artifacts (Dockerfile, bundled server.js,
3
+ * agent-manifest.json) into a reproducible zip and uploads it to S3. Reads the
4
+ * artifacts through the FileSystem port from the composition-root-resolved
5
+ * `ctx.agentDir`; this module touches no Node API directly.
6
+ */
7
+ import { zipSync } from 'fflate';
8
+ const IMAGE_PACKAGE_JSON = JSON.stringify({
9
+ name: 'site-builder',
10
+ private: true,
11
+ type: 'module',
12
+ });
13
+ /**
14
+ * Package the build-agent (Dockerfile + bundled server) into a zip and upload it to
15
+ * `build/agent/agent-<hash>.zip`. `<hash>` is the reproducible source hash stamped
16
+ * into agent-manifest.json when the agent was bundled — a hash of the agent's
17
+ * *source*, not the bundle, because bundle bytes vary by build platform/toolchain
18
+ * while source bytes are identical everywhere. The MicroVM image is then built from
19
+ * this artifact and keyed by the same hash, so identical source never rebuilds.
20
+ */
21
+ export async function packageAndUploadAgent(ctx) {
22
+ const dir = ctx.agentDir;
23
+ const { fs } = ctx.ports;
24
+ let dockerfile;
25
+ let server;
26
+ let manifest;
27
+ try {
28
+ dockerfile = await fs.readBytes(`${dir}/Dockerfile`);
29
+ server = await fs.readBytes(`${dir}/server.js`);
30
+ manifest = JSON.parse(await fs.readText(`${dir}/agent-manifest.json`));
31
+ }
32
+ catch {
33
+ throw new Error(`build-agent artifacts not found in ${dir}. Run "pnpm --filter blogwright build" first.`);
34
+ }
35
+ const hash = manifest.hash;
36
+ if (!hash || !/^[0-9a-f]{12}$/.test(hash)) {
37
+ throw new Error(`agent-manifest.json in ${dir} has no valid hash — rebuild the agent`);
38
+ }
39
+ const entries = {
40
+ Dockerfile: dockerfile,
41
+ 'server.js': server,
42
+ 'package.json': new TextEncoder().encode(IMAGE_PACKAGE_JSON),
43
+ };
44
+ const zip = zipSync(entries, { level: 6, mtime: new Date('1980-01-01T00:00:00Z') });
45
+ const key = `build/agent/agent-${hash}.zip`;
46
+ await ctx.clients.s3.putObject(ctx.names.bucket, key, zip, 'application/zip');
47
+ return { key, hash };
48
+ }
49
+ //# sourceMappingURL=agent-package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-package.js","sourceRoot":"","sources":["../src/agent-package.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAiB,MAAM,QAAQ,CAAC;AAIhD,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,CAAC;IACxC,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,QAAQ;CACf,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAe;IAEf,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;IACzB,MAAM,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC;IACzB,IAAI,UAAsB,CAAC;IAC3B,IAAI,MAAkB,CAAC;IACvB,IAAI,QAA2B,CAAC;IAChC,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;QACrD,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC;QAChD,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,GAAG,sBAAsB,CAAC,CAAC,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,sCAAsC,GAAG,+CAA+C,CACzF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,wCAAwC,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,OAAO,GAAa;QACxB,UAAU,EAAE,UAAU;QACtB,WAAW,EAAE,MAAM;QACnB,cAAc,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC;KAC7D,CAAC;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IACpF,MAAM,GAAG,GAAG,qBAAqB,IAAI,MAAM,CAAC;IAE5C,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAC9E,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC"}
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { createNodeTerminal } from 'blogwright-core';
3
+ import { main } from './cli.js';
4
+ import { createLogger } from './logger.js';
5
+ const makeTerminal = (opts) => createNodeTerminal(opts);
6
+ main(process.argv.slice(2), makeTerminal)
7
+ .then((code) => {
8
+ process.exitCode = code;
9
+ })
10
+ .catch((err) => {
11
+ createLogger(makeTerminal({ plain: true })).error(err instanceof Error ? err.message : String(err));
12
+ process.exitCode = 1;
13
+ });
14
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,YAAY,GAAG,CAAC,IAAwB,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAE5E,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;KACtC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC1B,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtB,YAAY,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAC/C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { type Terminal } from 'blogwright-core';
2
+ /** Builds the Terminal after flag parsing, so --plain shapes the whole session. */
3
+ export type TerminalFactory = (opts: {
4
+ plain: boolean;
5
+ }) => Terminal;
6
+ export declare function main(argv: string[], makeTerminal: TerminalFactory): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,249 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { createNodeFileSystem } from 'blogwright-core';
3
+ import * as pds from 'blogwright-pds';
4
+ import * as commands from './commands.js';
5
+ import { createContext } from './context.js';
6
+ import { initSite } from './init.js';
7
+ import { createLogger } from './logger.js';
8
+ const USAGE = `blogwright — full operations for a blog site on AWS (S3 + CloudFront, MicroVM builds)
9
+
10
+ Usage:
11
+ blogwright <command> [env] [options]
12
+
13
+ Commands:
14
+ init First-run wizard: writes config/production.jsonc
15
+ bootstrap [env] Create/reconcile the infrastructure graph
16
+ deploy [env] Zip the repo, build in a MicroVM, publish to site/
17
+ rollback <hash> [env] Re-deploy an existing build by hash
18
+ delete [env] Empty the live site/ prefix
19
+ destroy [env] --yes Tear down all infrastructure
20
+ history [env] List deployment history
21
+ logs <hash> [env] Show CloudWatch build logs for a hash
22
+ status [env] Show planned graph vs. live state
23
+
24
+ preview bootstrap Provision the shared preview stack
25
+ preview deploy <id> Build + publish a PR preview (id like pr-42)
26
+ preview destroy <id> Remove one PR preview
27
+ preview list List active previews
28
+ preview teardown --yes Tear down the whole preview stack
29
+
30
+ pds keygen Generate the OAuth client key: private JWK into
31
+ Secrets Manager, public documents into public/oauth/
32
+ (commit + release those before pds login)
33
+ pds login --identifier <handle-or-did>
34
+ Interactive OAuth bootstrap: prints an authorize URL,
35
+ then expects the pasted /oauth/callback redirect URL;
36
+ the session is stored in Secrets Manager and refreshed
37
+ automatically on every sync
38
+ pds secret status Show secret metadata (never the value)
39
+ pds secret delete --yes Delete the secret (logs out and discards the key)
40
+ pds init Create/update the standard.site publication record and
41
+ write the site verification files (commit them)
42
+ pds sync Reconcile site.standard.document records with the
43
+ content collection (production only; also runs after
44
+ every successful production deploy)
45
+
46
+ Options:
47
+ --env <name> Environment (default: production; also accepted positionally)
48
+ --domain <fqdn> Custom domain (ACM cert + CloudFront alias)
49
+ --config <path> Path to a JSONC config file
50
+ --endpoint <url> AWS endpoint override (e.g. http://localhost:4566 for floci)
51
+ --id <preview> Preview id for preview deploy/destroy (also accepted positionally)
52
+ --plain Minimal machine-friendly output (no colour, no live status,
53
+ no prompts) — for CI systems and agents; also automatic when
54
+ output is piped. NO_COLOR disables colour only.
55
+ --yes Confirm destructive operations
56
+ --help Show this help
57
+ `;
58
+ const HASH_COMMANDS = new Set(['rollback', 'logs']);
59
+ const KNOWN_COMMANDS = new Set([
60
+ 'bootstrap',
61
+ 'deploy',
62
+ 'rollback',
63
+ 'delete',
64
+ 'destroy',
65
+ 'history',
66
+ 'logs',
67
+ 'status',
68
+ ]);
69
+ export async function main(argv, makeTerminal) {
70
+ const { values, positionals } = parseArgs({
71
+ args: argv,
72
+ allowPositionals: true,
73
+ options: {
74
+ env: { type: 'string' },
75
+ domain: { type: 'string' },
76
+ config: { type: 'string' },
77
+ endpoint: { type: 'string' },
78
+ hash: { type: 'string' },
79
+ id: { type: 'string' },
80
+ identifier: { type: 'string' },
81
+ plain: { type: 'boolean', default: false },
82
+ yes: { type: 'boolean', default: false },
83
+ help: { type: 'boolean', default: false },
84
+ },
85
+ });
86
+ const terminal = makeTerminal({ plain: values.plain });
87
+ const logger = createLogger(terminal);
88
+ const command = positionals[0];
89
+ if (!command || values.help) {
90
+ logger.info(USAGE);
91
+ // Asking for help is success; invoking with no command at all is not.
92
+ return values.help || command ? 0 : 1;
93
+ }
94
+ if (command === 'init') {
95
+ // Runs before any context exists — there is no config to load yet.
96
+ return initSite(createNodeFileSystem(), terminal, logger);
97
+ }
98
+ if (command === 'preview') {
99
+ return runPreview(positionals, values, terminal, logger);
100
+ }
101
+ if (command === 'pds') {
102
+ return runPds(positionals, values, terminal, logger);
103
+ }
104
+ if (!KNOWN_COMMANDS.has(command)) {
105
+ logger.error(`unknown command: ${command}`);
106
+ logger.info(USAGE);
107
+ return 1;
108
+ }
109
+ // Positional layout: rollback/logs take <hash> first, then optional env.
110
+ let hash;
111
+ let envPositional;
112
+ if (HASH_COMMANDS.has(command)) {
113
+ hash = values.hash ?? positionals[1];
114
+ envPositional = positionals[2];
115
+ }
116
+ else {
117
+ envPositional = positionals[1];
118
+ }
119
+ const env = values.env ?? envPositional ?? 'production';
120
+ const ctx = await createContext({
121
+ env,
122
+ configPath: values.config,
123
+ domain: values.domain,
124
+ endpointOverride: values.endpoint,
125
+ ports: { terminal },
126
+ });
127
+ switch (command) {
128
+ case 'bootstrap':
129
+ await commands.bootstrap(ctx);
130
+ break;
131
+ case 'deploy':
132
+ await commands.deploy(ctx);
133
+ break;
134
+ case 'rollback':
135
+ if (!hash)
136
+ throw new Error('rollback requires a <hash>');
137
+ await commands.rollback(ctx, hash);
138
+ break;
139
+ case 'delete':
140
+ await commands.deleteSite(ctx);
141
+ break;
142
+ case 'destroy':
143
+ await commands.destroy(ctx, { yes: values.yes });
144
+ break;
145
+ case 'history':
146
+ await commands.history(ctx);
147
+ break;
148
+ case 'logs':
149
+ if (!hash)
150
+ throw new Error('logs requires a <hash>');
151
+ await commands.logs(ctx, hash);
152
+ break;
153
+ case 'status':
154
+ await commands.status(ctx);
155
+ break;
156
+ default:
157
+ logger.error(`unknown command: ${command}`);
158
+ logger.info(USAGE);
159
+ return 1;
160
+ }
161
+ return 0;
162
+ }
163
+ /** Handle `blogwright pds <action> [env]` (and `pds secret <action> [env]`). */
164
+ async function runPds(positionals, values, terminal, logger) {
165
+ // `pds secret set production` — the secret sub-action shifts positionals by one.
166
+ const secret = positionals[1] === 'secret';
167
+ const action = secret ? `secret ${positionals[2] ?? ''}`.trim() : positionals[1];
168
+ const envPositional = positionals[secret ? 3 : 2];
169
+ const known = new Set(['keygen', 'login', 'init', 'sync', 'secret status', 'secret delete']);
170
+ if (!action || !known.has(action)) {
171
+ logger.error(`unknown pds action: ${action ?? '(none)'}`);
172
+ logger.info(USAGE);
173
+ return 1;
174
+ }
175
+ const ctx = await createContext({
176
+ env: values.env ?? envPositional ?? 'production',
177
+ configPath: values.config,
178
+ domain: values.domain,
179
+ endpointOverride: values.endpoint,
180
+ ports: { terminal },
181
+ });
182
+ switch (action) {
183
+ case 'keygen':
184
+ await pds.keygen(ctx);
185
+ break;
186
+ case 'login':
187
+ await pds.login(ctx, { identifier: values.identifier });
188
+ break;
189
+ case 'secret status':
190
+ await pds.secretStatus(ctx);
191
+ break;
192
+ case 'secret delete':
193
+ await pds.secretDelete(ctx, { yes: values.yes });
194
+ break;
195
+ case 'init':
196
+ await pds.init(ctx);
197
+ break;
198
+ case 'sync':
199
+ await pds.sync(ctx);
200
+ break;
201
+ }
202
+ return 0;
203
+ }
204
+ /** Handle `blogwright preview <action> [id]` (always the shared `preview` stack). */
205
+ const PREVIEW_ACTIONS = new Set(['bootstrap', 'deploy', 'destroy', 'list', 'teardown']);
206
+ async function runPreview(positionals, values, terminal, logger) {
207
+ const action = positionals[1];
208
+ const id = values.id ?? positionals[2];
209
+ if (!action || !PREVIEW_ACTIONS.has(action)) {
210
+ logger.error(`unknown preview action: ${action ?? '(none)'}`);
211
+ logger.info(USAGE);
212
+ return 1;
213
+ }
214
+ const ctx = await createContext({
215
+ env: 'preview',
216
+ preview: true,
217
+ configPath: values.config,
218
+ domain: values.domain,
219
+ endpointOverride: values.endpoint,
220
+ ports: { terminal },
221
+ });
222
+ switch (action) {
223
+ case 'bootstrap':
224
+ await commands.previewBootstrap(ctx);
225
+ break;
226
+ case 'deploy':
227
+ if (!id)
228
+ throw new Error('preview deploy requires an <id> (e.g. pr-42)');
229
+ await commands.previewDeploy(ctx, id);
230
+ break;
231
+ case 'destroy':
232
+ if (!id)
233
+ throw new Error('preview destroy requires an <id>');
234
+ await commands.previewDestroy(ctx, id);
235
+ break;
236
+ case 'list':
237
+ await commands.previewList(ctx);
238
+ break;
239
+ case 'teardown':
240
+ await commands.previewTeardown(ctx, { yes: values.yes });
241
+ break;
242
+ default:
243
+ logger.error(`unknown preview action: ${action ?? '(none)'}`);
244
+ logger.info(USAGE);
245
+ return 1;
246
+ }
247
+ return 0;
248
+ }
249
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAiB,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAExD,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDb,CAAC;AAEF,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AACpD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,WAAW;IACX,QAAQ;IACR,UAAU;IACV,QAAQ;IACR,SAAS;IACT,SAAS;IACT,MAAM;IACN,QAAQ;CACT,CAAC,CAAC;AAKH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc,EAAE,YAA6B;IACtE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;QACxC,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,IAAI;QACtB,OAAO,EAAE;YACP,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACvB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC1B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC1B,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC5B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACxB,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACtB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC9B,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;YAC1C,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;YACxC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;SAC1C;KACF,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,sEAAsE;QACtE,OAAO,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,mEAAmE;QACnE,OAAO,QAAQ,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,yEAAyE;IACzE,IAAI,IAAwB,CAAC;IAC7B,IAAI,aAAiC,CAAC;IACtC,IAAI,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QACrC,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,aAAa,IAAI,YAAY,CAAC;IAExD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC;QAC9B,GAAG;QACH,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,gBAAgB,EAAE,MAAM,CAAC,QAAQ;QACjC,KAAK,EAAE,EAAE,QAAQ,EAAE;KACpB,CAAC,CAAC;IAEH,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,WAAW;YACd,MAAM,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,MAAM;QACR,KAAK,UAAU;YACb,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YACzD,MAAM,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACjD,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM;QACR,KAAK,MAAM;YACT,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACrD,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3B,MAAM;QACR;YACE,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAWD,gFAAgF;AAChF,KAAK,UAAU,MAAM,CACnB,WAAqB,EACrB,MAAiB,EACjB,QAAkB,EAClB,MAAc;IAEd,iFAAiF;IACjF,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;IAC7F,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,uBAAuB,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC;QAC9B,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,aAAa,IAAI,YAAY;QAChD,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,gBAAgB,EAAE,MAAM,CAAC,QAAQ;QACjC,KAAK,EAAE,EAAE,QAAQ,EAAE;KACpB,CAAC,CAAC;IAEH,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,OAAO;YACV,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YACxD,MAAM;QACR,KAAK,eAAe;YAClB,MAAM,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM;QACR,KAAK,eAAe;YAClB,MAAM,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACjD,MAAM;QACR,KAAK,MAAM;YACT,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM;IACV,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAUD,qFAAqF;AACrF,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAExF,KAAK,UAAU,UAAU,CACvB,WAAqB,EACrB,MAAqB,EACrB,QAAkB,EAClB,MAAc;IAEd,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,2BAA2B,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC;QAC9B,GAAG,EAAE,SAAS;QACd,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,gBAAgB,EAAE,MAAM,CAAC,QAAQ;QACjC,KAAK,EAAE,EAAE,QAAQ,EAAE;KACpB,CAAC,CAAC;IAEH,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW;YACd,MAAM,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,QAAQ;YACX,IAAI,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YACzE,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACtC,MAAM;QACR,KAAK,SAAS;YACZ,IAAI,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAC7D,MAAM,QAAQ,CAAC,cAAc,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM;QACR,KAAK,UAAU;YACb,MAAM,QAAQ,CAAC,eAAe,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACzD,MAAM;QACR;YACE,MAAM,CAAC,KAAK,CAAC,2BAA2B,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;YAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { OpsContext } from './context.js';
2
+ /** Create the full infrastructure graph. */
3
+ export declare function bootstrap(ctx: OpsContext): Promise<void>;
4
+ /** Destroy the full infrastructure graph. */
5
+ export declare function destroy(ctx: OpsContext, opts: {
6
+ yes: boolean;
7
+ }): Promise<void>;
8
+ /** Zip the repo, upload it, run the builder MicroVM, and invalidate the cache. */
9
+ export declare function deploy(ctx: OpsContext): Promise<void>;
10
+ /** Re-run the builder against an existing source zip for the given hash. */
11
+ export declare function rollback(ctx: OpsContext, hash: string): Promise<void>;
12
+ /** Provision the shared preview stack (one CloudFront distribution + host router + OIDC role). */
13
+ export declare function previewBootstrap(ctx: OpsContext): Promise<void>;
14
+ /** Build the current repo and publish it to this PR's preview prefix. Prints the URL. */
15
+ export declare function previewDeploy(ctx: OpsContext, id: string): Promise<string>;
16
+ /** Remove one PR's preview (delete its prefix). No invalidation — previews aren't cached. */
17
+ export declare function previewDestroy(ctx: OpsContext, id: string): Promise<void>;
18
+ /** List active previews (by prefix). */
19
+ export declare function previewList(ctx: OpsContext): Promise<void>;
20
+ /** Tear down the entire shared preview stack. */
21
+ export declare function previewTeardown(ctx: OpsContext, opts: {
22
+ yes: boolean;
23
+ }): Promise<void>;
24
+ /** Empty the live site/ prefix (leaves infra and build history intact). */
25
+ export declare function deleteSite(ctx: OpsContext): Promise<void>;
26
+ /** List deployment history from build manifests. */
27
+ export declare function history(ctx: OpsContext): Promise<void>;
28
+ /** Show CloudWatch build logs for a given hash. */
29
+ export declare function logs(ctx: OpsContext, hash: string): Promise<void>;
30
+ /** Show the planned graph against live state (drift view). */
31
+ export declare function status(ctx: OpsContext): Promise<void>;