@m-kopa/launchpad-cli 0.23.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.
- package/CHANGELOG.md +854 -0
- package/README.md +109 -0
- package/dist/auth/browser.d.ts +18 -0
- package/dist/auth/browser.d.ts.map +1 -0
- package/dist/auth/callback-server.d.ts +24 -0
- package/dist/auth/callback-server.d.ts.map +1 -0
- package/dist/auth/discovery.d.ts +25 -0
- package/dist/auth/discovery.d.ts.map +1 -0
- package/dist/auth/flow.d.ts +39 -0
- package/dist/auth/flow.d.ts.map +1 -0
- package/dist/auth/jwt.d.ts +27 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/pkce.d.ts +26 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/registration.d.ts +8 -0
- package/dist/auth/registration.d.ts.map +1 -0
- package/dist/auth/session.d.ts +54 -0
- package/dist/auth/session.d.ts.map +1 -0
- package/dist/auth/token.d.ts +37 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/bundle/cron-bundle.d.ts +77 -0
- package/dist/bundle/cron-bundle.d.ts.map +1 -0
- package/dist/bundle/cwd-walker.d.ts +43 -0
- package/dist/bundle/cwd-walker.d.ts.map +1 -0
- package/dist/bundle/orchestrate.d.ts +51 -0
- package/dist/bundle/orchestrate.d.ts.map +1 -0
- package/dist/bundle/upload.d.ts +66 -0
- package/dist/bundle/upload.d.ts.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +9757 -0
- package/dist/clone/git-init.d.ts +18 -0
- package/dist/clone/git-init.d.ts.map +1 -0
- package/dist/clone/tar-extract.d.ts +59 -0
- package/dist/clone/tar-extract.d.ts.map +1 -0
- package/dist/commands/apps.d.ts +14 -0
- package/dist/commands/apps.d.ts.map +1 -0
- package/dist/commands/channel-auth.d.ts +31 -0
- package/dist/commands/channel-auth.d.ts.map +1 -0
- package/dist/commands/clone.d.ts +3 -0
- package/dist/commands/clone.d.ts.map +1 -0
- package/dist/commands/create.d.ts +27 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/deploy-flags.d.ts +75 -0
- package/dist/commands/deploy-flags.d.ts.map +1 -0
- package/dist/commands/deploy-modes.d.ts +59 -0
- package/dist/commands/deploy-modes.d.ts.map +1 -0
- package/dist/commands/deploy.d.ts +29 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/destroy.d.ts +14 -0
- package/dist/commands/destroy.d.ts.map +1 -0
- package/dist/commands/envvars.d.ts +28 -0
- package/dist/commands/envvars.d.ts.map +1 -0
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/groups-whoami.d.ts +3 -0
- package/dist/commands/groups-whoami.d.ts.map +1 -0
- package/dist/commands/groups.d.ts +3 -0
- package/dist/commands/groups.d.ts.map +1 -0
- package/dist/commands/init.d.ts +44 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logs.d.ts +16 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/merge.d.ts +29 -0
- package/dist/commands/merge.d.ts.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/pull.d.ts +12 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/review.d.ts +22 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/rollback.d.ts +3 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/secrets-template.d.ts +3 -0
- package/dist/commands/secrets-template.d.ts.map +1 -0
- package/dist/commands/secrets.d.ts +3 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/skills.d.ts +13 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/status.d.ts +54 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/update.d.ts +114 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/deploy/apply.d.ts +29 -0
- package/dist/deploy/apply.d.ts.map +1 -0
- package/dist/deploy/dry-run.d.ts +13 -0
- package/dist/deploy/dry-run.d.ts.map +1 -0
- package/dist/deploy/git-files.d.ts +33 -0
- package/dist/deploy/git-files.d.ts.map +1 -0
- package/dist/deploy/group-pin.d.ts +66 -0
- package/dist/deploy/group-pin.d.ts.map +1 -0
- package/dist/deploy/manifest-state.d.ts +20 -0
- package/dist/deploy/manifest-state.d.ts.map +1 -0
- package/dist/deploy/manifest-status.d.ts +11 -0
- package/dist/deploy/manifest-status.d.ts.map +1 -0
- package/dist/deploy/resolve.d.ts +53 -0
- package/dist/deploy/resolve.d.ts.map +1 -0
- package/dist/deploy/rollback.d.ts +23 -0
- package/dist/deploy/rollback.d.ts.map +1 -0
- package/dist/deploy/runner.d.ts +29 -0
- package/dist/deploy/runner.d.ts.map +1 -0
- package/dist/deploy/stage-exit-codes.d.ts +41 -0
- package/dist/deploy/stage-exit-codes.d.ts.map +1 -0
- package/dist/deploy/status-polling.d.ts +37 -0
- package/dist/deploy/status-polling.d.ts.map +1 -0
- package/dist/deploy/tar-pack.d.ts +22 -0
- package/dist/deploy/tar-pack.d.ts.map +1 -0
- package/dist/detect/index.d.ts +53 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/dispatcher.d.ts +30 -0
- package/dist/dispatcher.d.ts.map +1 -0
- package/dist/groups/client.d.ts +62 -0
- package/dist/groups/client.d.ts.map +1 -0
- package/dist/http/api-client.d.ts +33 -0
- package/dist/http/api-client.d.ts.map +1 -0
- package/dist/http/errors.d.ts +31 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/manifest/load.d.ts +38 -0
- package/dist/manifest/load.d.ts.map +1 -0
- package/dist/manifest/schema.d.ts +3 -0
- package/dist/manifest/schema.d.ts.map +1 -0
- package/dist/postinstall.d.ts +3 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +37 -0
- package/dist/secrets/env-parse.d.ts +19 -0
- package/dist/secrets/env-parse.d.ts.map +1 -0
- package/dist/secrets/push.d.ts +13 -0
- package/dist/secrets/push.d.ts.map +1 -0
- package/dist/secrets/set.d.ts +19 -0
- package/dist/secrets/set.d.ts.map +1 -0
- package/dist/secrets/status.d.ts +19 -0
- package/dist/secrets/status.d.ts.map +1 -0
- package/dist/types/api.d.ts +112 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/update-notifier.d.ts +69 -0
- package/dist/update-notifier.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +62 -0
- package/skills/README.md +100 -0
- package/skills/_partials/shell-contract.md +42 -0
- package/skills/launchpad-content-pr/SKILL.md +255 -0
- package/skills/launchpad-deploy/SKILL.md +415 -0
- package/skills/launchpad-deploy-status/SKILL.md +231 -0
- package/skills/launchpad-destroy/SKILL.md +317 -0
- package/skills/launchpad-onboard/SKILL.md +179 -0
- package/skills/launchpad-status/SKILL.md +263 -0
- package/skills/marquee-share/README.md +155 -0
- package/skills/marquee-share/SKILL.md +94 -0
- package/skills/marquee-share/SYNC.md +27 -0
- package/skills/marquee-share/dist/cli.js +896 -0
- package/skills/marquee-share/eslint.config.mjs +71 -0
- package/skills/marquee-share/install.sh +103 -0
- package/skills/marquee-share/package-lock.json +3946 -0
- package/skills/marquee-share/package.json +30 -0
- package/skills/marquee-share/src/auth/PROVENANCE.md +103 -0
- package/skills/marquee-share/src/auth/browser.ts +75 -0
- package/skills/marquee-share/src/auth/callback-server.ts +171 -0
- package/skills/marquee-share/src/auth/discovery.ts +171 -0
- package/skills/marquee-share/src/auth/flow.ts +262 -0
- package/skills/marquee-share/src/auth/index.ts +171 -0
- package/skills/marquee-share/src/auth/jwt.ts +77 -0
- package/skills/marquee-share/src/auth/pkce.ts +79 -0
- package/skills/marquee-share/src/auth/registration.ts +87 -0
- package/skills/marquee-share/src/auth/session.ts +205 -0
- package/skills/marquee-share/src/auth/token.ts +162 -0
- package/skills/marquee-share/src/cli.ts +246 -0
- package/skills/marquee-share/src/config.ts +101 -0
- package/skills/marquee-share/src/render/template.ts +171 -0
- package/skills/marquee-share/src/upload/index.ts +11 -0
- package/skills/marquee-share/src/upload/upload.ts +191 -0
- package/skills/marquee-share/tests/cli.test.ts +281 -0
- package/skills/marquee-share/tests/config.test.ts +119 -0
- package/skills/marquee-share/tests/flow.test.ts +356 -0
- package/skills/marquee-share/tests/no-token-leak.test.ts +240 -0
- package/skills/marquee-share/tests/pkce.test.ts +121 -0
- package/skills/marquee-share/tests/session.test.ts +173 -0
- package/skills/marquee-share/tests/template.test.ts +170 -0
- package/skills/marquee-share/tests/upload.test.ts +311 -0
- package/skills/marquee-share/tsconfig.json +23 -0
- package/skills/marquee-share/vitest.config.ts +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# `@m-kopa/launchpad-cli`
|
|
2
|
+
|
|
3
|
+
The user-facing CLI for Launchpad. Talks to the portal-bot endpoints
|
|
4
|
+
shipped under SCOPE-M-760 / T4 (`/apps/<slug>/source-bundle`,
|
|
5
|
+
`/apps/<slug>/deploy-pr`, `/apps/<slug>/review/<prNumber>`,
|
|
6
|
+
`/apps/<slug>/merge/<prNumber>`).
|
|
7
|
+
|
|
8
|
+
## Status
|
|
9
|
+
|
|
10
|
+
**Released**, published to **public npm**. The CLI delivers the full
|
|
11
|
+
SCOPE-M-760 command surface plus follow-on commands; every release is
|
|
12
|
+
documented in `CHANGELOG.md`.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm i -g @m-kopa/launchpad-cli # or: bun add -g / pnpm add -g
|
|
16
|
+
launchpad login # authenticate against the M-KOPA SSO
|
|
17
|
+
launchpad skills install # install the Claude Code slash-commands
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`@m-kopa/launchpad-cli` is published to **public npmjs** — `npm i -g
|
|
21
|
+
@m-kopa/launchpad-cli` works on any machine with **no `~/.npmrc` setup,
|
|
22
|
+
no auth token, and no antivirus block** (a registry install carries no
|
|
23
|
+
embedded payload, unlike the legacy self-contained installer). Once
|
|
24
|
+
installed, `launchpad update` keeps it current. Access to *apps* is still
|
|
25
|
+
gated by M-KOPA SSO at `launchpad login`; only the install is public.
|
|
26
|
+
|
|
27
|
+
| Command | What it does |
|
|
28
|
+
| ------- | ------------ |
|
|
29
|
+
| `login` / `logout` | Start / clear a Cloudflare Access OAuth session |
|
|
30
|
+
| `whoami` | Show the current session identity + per-app role |
|
|
31
|
+
| `apps` | List the apps the caller can access |
|
|
32
|
+
| `create` | File a new app from the terminal (mirrors the portal wizard) |
|
|
33
|
+
| `clone <slug>` | Fetch an app's source into a local git repo |
|
|
34
|
+
| `deploy` | Package the working tree + open/update a review PR |
|
|
35
|
+
| `review` | Show a PR's review state + findings |
|
|
36
|
+
| `merge` | Squash-merge a review-passed PR |
|
|
37
|
+
| `envvars` | List / set / remove Pages environment variables |
|
|
38
|
+
| `logs` | Show recent deployment history |
|
|
39
|
+
| `skills` | Install / update the Claude Code skill bundle |
|
|
40
|
+
| `update` | Self-update the CLI to the latest published release |
|
|
41
|
+
|
|
42
|
+
Run `launchpad --help` for the list, or `launchpad <command> --help` for
|
|
43
|
+
per-command usage.
|
|
44
|
+
|
|
45
|
+
## Auth
|
|
46
|
+
|
|
47
|
+
The CLI uses Cloudflare Access **Managed OAuth (PKCE)** — see
|
|
48
|
+
`.planning/research/cf-access-cli-auth.md` for the full flow. `launchpad
|
|
49
|
+
login` opens a browser, completes the PKCE handshake, and stores the
|
|
50
|
+
session at `~/.launchpad/session.json` (mode `0600`). Subsequent commands
|
|
51
|
+
refresh the access token silently until the grant session expires, at
|
|
52
|
+
which point the CLI prompts a re-login.
|
|
53
|
+
|
|
54
|
+
## Local dev
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
cd packages/launchpad-cli
|
|
58
|
+
bun install
|
|
59
|
+
bun run typecheck
|
|
60
|
+
bun run lint
|
|
61
|
+
bun run test
|
|
62
|
+
bun run build
|
|
63
|
+
node dist/cli.js --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Skills bundle
|
|
67
|
+
|
|
68
|
+
The CLI ships a bundle of Claude Code skills under `skills/`, copied
|
|
69
|
+
into a user's `~/.claude/skills/` by `launchpad skills install`. A public
|
|
70
|
+
npm `npm i -g @m-kopa/launchpad-cli` install needs one explicit
|
|
71
|
+
`launchpad skills install` afterward; the legacy platform installer
|
|
72
|
+
(https://get.launchpad.m-kopa.us) runs that step automatically. See
|
|
73
|
+
`docs/runbooks/launchpad-skills-bundle.md` for both channels.
|
|
74
|
+
|
|
75
|
+
| Skill | Source |
|
|
76
|
+
| ----- | ------ |
|
|
77
|
+
| `launchpad-onboard` | this repo |
|
|
78
|
+
| `launchpad-deploy` | this repo |
|
|
79
|
+
| `launchpad-deploy-status` | this repo |
|
|
80
|
+
| `launchpad-content-pr` | this repo |
|
|
81
|
+
| `marquee-share` | **`M-KOPA/marquee`** (vendored — see below) |
|
|
82
|
+
|
|
83
|
+
### The `marquee-share` skill (cross-repo, vendored)
|
|
84
|
+
|
|
85
|
+
`marquee-share` is **not** authored here. Its canonical source is the
|
|
86
|
+
`M-KOPA/marquee` repository, under `skill/`. It is *vendored* into
|
|
87
|
+
`skills/marquee-share/` so the CLI can install a working skill straight
|
|
88
|
+
from the published npm package — the CLI cannot reach another repo at
|
|
89
|
+
install time.
|
|
90
|
+
|
|
91
|
+
The vendored copy must never be hand-edited; it would silently drift
|
|
92
|
+
from the canonical source. The single supported way to refresh it is
|
|
93
|
+
the sync script:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
packages/launchpad-cli/scripts/sync-marquee-share-skill.sh <marquee-checkout> [git-ref]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Run this at marquee-share **release time**, review the diff, and
|
|
100
|
+
commit. The script records the source commit in
|
|
101
|
+
`skills/marquee-share/SYNC.md`. `--check` reports the currently pinned
|
|
102
|
+
commit. This keeps the bundle a deliberate, reviewed mirror rather
|
|
103
|
+
than a hand-maintained second copy.
|
|
104
|
+
|
|
105
|
+
## Versioning
|
|
106
|
+
|
|
107
|
+
Pre-1.0 consumer-pinning policy (per ADR 0005): consumers must pin
|
|
108
|
+
exact versions until v1.0.0. Caret ranges are forbidden. Each
|
|
109
|
+
minor-version bump may carry breaking changes.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export declare class BrowserOpenError extends Error {
|
|
3
|
+
readonly code: "browser_open_error";
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Open `url` in the user's default browser. Resolves once the
|
|
7
|
+
* spawn succeeds; the OS opener is fire-and-forget after that.
|
|
8
|
+
*
|
|
9
|
+
* `platform` is injected for tests so the dispatch table is
|
|
10
|
+
* exercised without actually opening a browser. The default reads
|
|
11
|
+
* `process.platform`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function openBrowser(url: string, platform?: NodeJS.Platform, spawner?: typeof spawn): Promise<void>;
|
|
14
|
+
export declare function chooseOpener(platform: NodeJS.Platform, url: string): {
|
|
15
|
+
command: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/auth/browser.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;CAC/C;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,GAAG,EAAE,MAAM,GACV;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAoCrC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface CallbackResult {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly state: string;
|
|
4
|
+
}
|
|
5
|
+
export interface CallbackServer {
|
|
6
|
+
readonly port: number;
|
|
7
|
+
/** Resolves when the user's browser hits /callback with a valid
|
|
8
|
+
* code + matching state. Rejects on `cancel()`. */
|
|
9
|
+
readonly result: Promise<CallbackResult>;
|
|
10
|
+
/** Tear down the listener. Idempotent. */
|
|
11
|
+
readonly close: () => Promise<void>;
|
|
12
|
+
/** Reject the pending `result` and close. */
|
|
13
|
+
readonly cancel: (reason: string) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare class CallbackError extends Error {
|
|
16
|
+
readonly code: "callback_error";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Bind a fresh callback server. `expectedState` is the value the
|
|
20
|
+
* authorization URL will carry in `state`; the server rejects any
|
|
21
|
+
* request whose `state` differs.
|
|
22
|
+
*/
|
|
23
|
+
export declare function bindCallbackServer(expectedState: string): Promise<CallbackServer>;
|
|
24
|
+
//# sourceMappingURL=callback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../../src/auth/callback-server.ts"],"names":[],"mappings":"AA2BA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;wDACoD;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;CAC3C;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,CAAC,CAoCzB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface OAuthEndpoints {
|
|
2
|
+
readonly authorizationEndpoint: string;
|
|
3
|
+
readonly tokenEndpoint: string;
|
|
4
|
+
readonly registrationEndpoint: string;
|
|
5
|
+
/**
|
|
6
|
+
* The protected resource's canonical URL (per RFC 8707 OAuth 2.0
|
|
7
|
+
* Resource Indicators). Cf Access REQUIRES this parameter on the
|
|
8
|
+
* authorization request — omitting it returns
|
|
9
|
+
* `error=invalid_target, error_description="No resource parameter
|
|
10
|
+
* found"`. Sourced from the protected-resource metadata's
|
|
11
|
+
* `resource` field; falls back to `botUrl` if the metadata omits
|
|
12
|
+
* it (older Cf deployments may not).
|
|
13
|
+
*/
|
|
14
|
+
readonly resource: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class DiscoveryError extends Error {
|
|
17
|
+
readonly code: "discovery_error";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Walk the two-step discovery and return the endpoints. `botUrl`
|
|
21
|
+
* is the base of the protected Worker (no trailing slash). The
|
|
22
|
+
* fetcher is injected so tests don't need a network.
|
|
23
|
+
*/
|
|
24
|
+
export declare function discoverOauthEndpoints(botUrl: string, fetcher?: typeof fetch): Promise<OAuthEndpoints>;
|
|
25
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/auth/discovery.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;CAC5C;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,cAAc,CAAC,CA0EzB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type CliSession } from "./session.js";
|
|
2
|
+
export declare class LoginRequiredError extends Error {
|
|
3
|
+
readonly code: "login_required";
|
|
4
|
+
}
|
|
5
|
+
/** Refresh-window buffer: refresh `refreshSkewMs` before expiry
|
|
6
|
+
* so a request fired right at the edge doesn't hit a 401. */
|
|
7
|
+
export declare const REFRESH_SKEW_MS = 30000;
|
|
8
|
+
export interface LoginOptions {
|
|
9
|
+
readonly botUrl: string;
|
|
10
|
+
readonly sessionPath: string;
|
|
11
|
+
/** Receives the auth URL once the localhost server is bound +
|
|
12
|
+
* the browser opener is about to fire. The CLI verb prints it
|
|
13
|
+
* to stdout so a headless dev can copy-paste. */
|
|
14
|
+
readonly onAuthUrl?: (url: string) => void;
|
|
15
|
+
/** Injection points for tests. */
|
|
16
|
+
readonly fetcher?: typeof fetch;
|
|
17
|
+
readonly browserOpener?: (url: string) => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Run the full PKCE flow and persist the session. Returns the
|
|
21
|
+
* resulting session for the caller (so the verb can print
|
|
22
|
+
* confirmation diagnostics).
|
|
23
|
+
*/
|
|
24
|
+
export declare function login(opts: LoginOptions): Promise<CliSession>;
|
|
25
|
+
/**
|
|
26
|
+
* Read the session and return a still-valid access token. If the
|
|
27
|
+
* persisted access token is past (or near) expiry, silently
|
|
28
|
+
* refresh and persist the new pair before returning. If the
|
|
29
|
+
* refresh fails because the grant has expired, throws
|
|
30
|
+
* `LoginRequiredError`.
|
|
31
|
+
*
|
|
32
|
+
* `now` is injected for tests so we can simulate expiry without
|
|
33
|
+
* mocking the system clock.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getValidAccessToken(sessionPath: string, fetcher?: typeof fetch, now?: () => number): Promise<{
|
|
36
|
+
accessToken: string;
|
|
37
|
+
session: CliSession;
|
|
38
|
+
}>;
|
|
39
|
+
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAwCA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,cAAc,CAAC;AAGtB,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAG,gBAAgB,CAAU;CAC3C;AAED;8DAC8D;AAC9D,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;sDAEkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CA8DnE;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAO,KAAa,EAC7B,GAAG,GAAE,MAAM,MAAiB,GAC3B,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC,CAiDvD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface JwtPayload {
|
|
2
|
+
/** Cf Access user-scoped JWT subject — Entra UUID. */
|
|
3
|
+
readonly sub?: string;
|
|
4
|
+
/** Email / UPN claim. Cloudflare populates this from the IdP. */
|
|
5
|
+
readonly email?: string;
|
|
6
|
+
/** Cf Access aud (the App's UUID). */
|
|
7
|
+
readonly aud?: string | readonly string[];
|
|
8
|
+
/** Issued-at + expiry, seconds since epoch (RFC 7519). */
|
|
9
|
+
readonly iat?: number;
|
|
10
|
+
readonly exp?: number;
|
|
11
|
+
/** Token type — "app" for Cf Access app tokens. */
|
|
12
|
+
readonly type?: string;
|
|
13
|
+
/** Anything else the IdP / Cf added; we don't validate it. */
|
|
14
|
+
readonly [k: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export declare class JwtParseError extends Error {
|
|
17
|
+
readonly code: "jwt_parse_error";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Decode the payload of a JWT. Returns `null` for inputs that
|
|
21
|
+
* don't look like a JWT at all (e.g. an opaque token). Throws
|
|
22
|
+
* `JwtParseError` only for shapes that look JWT-like but have an
|
|
23
|
+
* undecodable payload — callers should treat both null and throw
|
|
24
|
+
* as "show empty identity".
|
|
25
|
+
*/
|
|
26
|
+
export declare function decodeJwtPayload(token: string): JwtPayload | null;
|
|
27
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAC1C,0DAA0D;IAC1D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;CAC5C;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAwBjE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface PkcePair {
|
|
2
|
+
/** Plain-text random secret, kept on the client. */
|
|
3
|
+
readonly verifier: string;
|
|
4
|
+
/** S256 hash of the verifier, sent in the authorization URL. */
|
|
5
|
+
readonly challenge: string;
|
|
6
|
+
}
|
|
7
|
+
/** Hard cap on regeneration attempts — defends against an
|
|
8
|
+
* algorithmic mistake silently spinning forever. The probability
|
|
9
|
+
* of a `-` or `_` first byte is ~2/64 per attempt, so even 5 tries
|
|
10
|
+
* is enough for ~6-nines reliability; we pick a higher bound so a
|
|
11
|
+
* pathological RNG (or a future encoding change) surfaces as a
|
|
12
|
+
* clear error rather than a hang. */
|
|
13
|
+
export declare const MAX_PKCE_REGEN_ATTEMPTS = 32;
|
|
14
|
+
export declare class PkceGenerationError extends Error {
|
|
15
|
+
readonly code: "pkce_generation_failed";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate a fresh PKCE pair satisfying both RFC 7636 and the
|
|
19
|
+
* Cloudflare Access "challenge must start with [a-zA-Z0-9]" rule.
|
|
20
|
+
* Pure (modulo `randomBytes`) — caller can re-test by injecting
|
|
21
|
+
* a deterministic RNG via the optional `rng` parameter.
|
|
22
|
+
*/
|
|
23
|
+
export declare function generatePkcePair(rng?: (size: number) => Uint8Array): PkcePair;
|
|
24
|
+
/** S256 challenge for an arbitrary verifier. Exposed for tests. */
|
|
25
|
+
export declare function sha256Base64Url(verifier: string): string;
|
|
26
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../src/auth/pkce.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;sCAKsC;AACtC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,wBAAwB,CAAU;CACnD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAkD,GACxE,QAAQ,CAgBV;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface RegistrationResult {
|
|
2
|
+
readonly clientId: string;
|
|
3
|
+
}
|
|
4
|
+
export declare class RegistrationError extends Error {
|
|
5
|
+
readonly code: "registration_error";
|
|
6
|
+
}
|
|
7
|
+
export declare function registerClient(registrationEndpoint: string, redirectUri: string, fetcher?: typeof fetch): Promise<RegistrationResult>;
|
|
8
|
+
//# sourceMappingURL=registration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.d.ts","sourceRoot":"","sources":["../../src/auth/registration.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAU;CAC/C;AAED,wBAAsB,cAAc,CAClC,oBAAoB,EAAE,MAAM,EAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CA6C7B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export declare const SESSION_VERSION = 1;
|
|
2
|
+
export interface CliSession {
|
|
3
|
+
readonly version: typeof SESSION_VERSION;
|
|
4
|
+
/** OAuth `access_token`. Sent to the bot as `Authorization: Bearer <accessToken>`. */
|
|
5
|
+
readonly accessToken: string;
|
|
6
|
+
/** OAuth `refresh_token` — used to silently mint a fresh
|
|
7
|
+
* access token when the current one expires. */
|
|
8
|
+
readonly refreshToken: string;
|
|
9
|
+
/** Epoch milliseconds at which `accessToken` ceases to be valid.
|
|
10
|
+
* Computed at write-time as `Date.now() + (expires_in * 1000)`. */
|
|
11
|
+
readonly accessTokenExpiresAt: number;
|
|
12
|
+
/** OAuth client id from dynamic-client-registration. Cached so
|
|
13
|
+
* refreshes don't re-register. */
|
|
14
|
+
readonly clientId: string;
|
|
15
|
+
/** Token endpoint discovered at login. Cached for refreshes so
|
|
16
|
+
* refresh doesn't re-walk discovery. */
|
|
17
|
+
readonly tokenEndpoint: string;
|
|
18
|
+
/** RFC 8707 resource indicator (the protected bot's canonical URL).
|
|
19
|
+
* Cached so silent refresh can re-include it without
|
|
20
|
+
* re-discovering — Cf Access binds the access_token's audience to
|
|
21
|
+
* this and the refresh grant must match. Optional in the on-disk
|
|
22
|
+
* schema so pre-0.7.1 sessions (which omit it) still parse —
|
|
23
|
+
* those callers fall through to a forced re-login on the next
|
|
24
|
+
* refresh attempt. */
|
|
25
|
+
readonly resource?: string;
|
|
26
|
+
/** ISO-8601 UTC timestamp of when this session was written. Used
|
|
27
|
+
* by `whoami` (slice 3) for diagnostic display only. */
|
|
28
|
+
readonly issuedAt: string;
|
|
29
|
+
}
|
|
30
|
+
export declare class SessionParseError extends Error {
|
|
31
|
+
readonly code: "session_parse_error";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read the session file. Returns `null` if the file doesn't exist
|
|
35
|
+
* (the user hasn't logged in yet — a normal state). Throws
|
|
36
|
+
* `SessionParseError` for a corrupt file: better to fail loudly
|
|
37
|
+
* than to silently re-prompt for login when the storage is
|
|
38
|
+
* actually broken.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readSession(sessionPath: string): Promise<CliSession | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Atomic-ish write: writes to `<path>.tmp` then renames into
|
|
43
|
+
* place. The whole-directory chmod is best-effort (Windows ignores
|
|
44
|
+
* mode bits) — the per-file mode is the load-bearing one.
|
|
45
|
+
*/
|
|
46
|
+
export declare function writeSession(sessionPath: string, session: CliSession): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* `launchpad logout`: zero out the session file. Idempotent —
|
|
49
|
+
* already-absent file is a no-op success. Returns whether a
|
|
50
|
+
* session actually existed (so the verb can render the right
|
|
51
|
+
* message).
|
|
52
|
+
*/
|
|
53
|
+
export declare function clearSession(sessionPath: string): Promise<boolean>;
|
|
54
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/auth/session.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,eAAe,CAAC;IACzC,sFAAsF;IACtF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;qDACiD;IACjD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;wEACoE;IACpE,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC;uCACmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;6CACyC;IACzC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;;2BAMuB;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;6DACyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAG,qBAAqB,CAAU;CAChD;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAmD5B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface TokenResponse {
|
|
2
|
+
readonly accessToken: string;
|
|
3
|
+
readonly refreshToken: string;
|
|
4
|
+
/** Seconds until `accessToken` expiry, as returned by the
|
|
5
|
+
* server. Caller converts to absolute epoch when persisting. */
|
|
6
|
+
readonly expiresInSec: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class TokenError extends Error {
|
|
9
|
+
readonly code: "token_error";
|
|
10
|
+
/** Optional HTTP status — present only for non-2xx responses, not
|
|
11
|
+
* for network errors. Lets the login flow distinguish "user
|
|
12
|
+
* denied at the IdP" from "network is down". */
|
|
13
|
+
readonly httpStatus?: number;
|
|
14
|
+
constructor(message: string, httpStatus?: number);
|
|
15
|
+
}
|
|
16
|
+
export declare function exchangeCodeForTokens(params: {
|
|
17
|
+
readonly tokenEndpoint: string;
|
|
18
|
+
readonly clientId: string;
|
|
19
|
+
readonly code: string;
|
|
20
|
+
readonly codeVerifier: string;
|
|
21
|
+
readonly redirectUri: string;
|
|
22
|
+
/** RFC 8707 resource indicator. Cf Access binds the resulting
|
|
23
|
+
* access_token's audience to this value; the bot's JWT
|
|
24
|
+
* validation MUST see a matching `aud` claim. Always pass it
|
|
25
|
+
* so the token is valid for the right protected app. */
|
|
26
|
+
readonly resource: string;
|
|
27
|
+
}, fetcher?: typeof fetch): Promise<TokenResponse>;
|
|
28
|
+
export declare function refreshTokens(params: {
|
|
29
|
+
readonly tokenEndpoint: string;
|
|
30
|
+
readonly clientId: string;
|
|
31
|
+
readonly refreshToken: string;
|
|
32
|
+
/** RFC 8707 resource indicator — same posture as
|
|
33
|
+
* exchangeCodeForTokens. The refreshed access_token's audience
|
|
34
|
+
* must match what `apiRaw` calls into. */
|
|
35
|
+
readonly resource: string;
|
|
36
|
+
}, fetcher?: typeof fetch): Promise<TokenResponse>;
|
|
37
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/auth/token.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;qEACiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAG,aAAa,CAAU;IACvC;;qDAEiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBACjB,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAKjD;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE;IACN,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;6DAGyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,EACD,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,aAAa,CAAC,CAUxB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE;IACN,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;+CAE2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,EACD,OAAO,GAAE,OAAO,KAAa,GAC5B,OAAO,CAAC,aAAa,CAAC,CAQxB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built cron-Worker artifact the CLI ships alongside the source tarball.
|
|
3
|
+
* `script` must match a `kind: worker` target the bot has registered for the
|
|
4
|
+
* app; the bot re-validates it against the app's surfaces before uploading.
|
|
5
|
+
*/
|
|
6
|
+
export interface WorkerArtifact {
|
|
7
|
+
/** Worker script name — must equal the manifest target's `script`. */
|
|
8
|
+
readonly script: string;
|
|
9
|
+
/** The bundled ES-module source (single file, workerd-compatible). */
|
|
10
|
+
readonly moduleContent: string;
|
|
11
|
+
/** Module filename for the multipart upload (e.g. `index.js`). */
|
|
12
|
+
readonly moduleFilename: string;
|
|
13
|
+
/** `compatibility_date` from the worker's wrangler.toml. */
|
|
14
|
+
readonly compatibilityDate: string;
|
|
15
|
+
/** `compatibility_flags` from the worker's wrangler.toml (e.g. nodejs_compat). */
|
|
16
|
+
readonly compatibilityFlags: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export type BuildWorkerResult = {
|
|
19
|
+
kind: "none";
|
|
20
|
+
} | {
|
|
21
|
+
kind: "ok";
|
|
22
|
+
artifact: WorkerArtifact;
|
|
23
|
+
} | {
|
|
24
|
+
kind: "error";
|
|
25
|
+
message: string;
|
|
26
|
+
};
|
|
27
|
+
/** Top-level scalar/array keys we need out of a worker's wrangler.toml. */
|
|
28
|
+
interface WranglerTopLevel {
|
|
29
|
+
readonly name?: string;
|
|
30
|
+
readonly main?: string;
|
|
31
|
+
readonly compatibility_date?: string;
|
|
32
|
+
readonly compatibility_flags?: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse ONLY the top-level keys of a wrangler.toml that precede the first
|
|
36
|
+
* `[section]` / `[[array-of-tables]]`. We need `name`, `main`,
|
|
37
|
+
* `compatibility_date`, `compatibility_flags` — all top-level scalars/string
|
|
38
|
+
* arrays. We deliberately do NOT parse `[triggers]` (crons) or
|
|
39
|
+
* `[[d1_databases]]`: the schedule + D1 binding are the bot-authoritative
|
|
40
|
+
* deploy contract (manifest `targets[]`), not CLI build inputs. A
|
|
41
|
+
* purpose-built reader avoids a TOML dependency for these four keys.
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseWranglerTopLevel(tomlText: string): WranglerTopLevel;
|
|
44
|
+
/**
|
|
45
|
+
* Script names of the manifest's **deployable** worker targets — `kind: worker`
|
|
46
|
+
* entries that carry a non-empty `schedule`. The schedule is the discriminator
|
|
47
|
+
* (ADR 0022 Decision #3): a worker target WITH a schedule is a *deploy surface*
|
|
48
|
+
* (build + upload it here); a worker target WITHOUT one is secrets-only (the
|
|
49
|
+
* existing fan-out target) and is NOT built. Keying the CLI build gate on the
|
|
50
|
+
* same `schedule` the bot keys its deploy gate on avoids a build-but-skip
|
|
51
|
+
* mismatch.
|
|
52
|
+
*/
|
|
53
|
+
export declare function scheduledWorkerScripts(manifestYaml: string): string[];
|
|
54
|
+
/**
|
|
55
|
+
* Bundle a worker entry into a single workerd-compatible ES module. Config is
|
|
56
|
+
* pinned to what a real ai-cost cron build produced cleanly (sp-tt2cap C3a
|
|
57
|
+
* spike, 2026-06-09): `conditions: [worker, browser]` + `node:*` external
|
|
58
|
+
* (nodejs_compat provides them at runtime). `write: false` returns the module
|
|
59
|
+
* source in-memory so it never touches disk or the source tarball.
|
|
60
|
+
*/
|
|
61
|
+
export declare function bundleWorker(entryAbs: string, workerDir: string): Promise<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Build the cron-Worker artifact for an app, if it declares one.
|
|
64
|
+
*
|
|
65
|
+
* Returns `{kind:"none"}` for single-tier apps (no `kind: worker` target) so
|
|
66
|
+
* the caller ships the tarball unchanged. Returns `{kind:"error"}` with a
|
|
67
|
+
* CLI-friendly message when a worker is declared but its build config or
|
|
68
|
+
* bundle can't be produced — a deploy that would silently skip the cron tier
|
|
69
|
+
* is worse than a loud failure.
|
|
70
|
+
*
|
|
71
|
+
* Only the FIRST worker target is built — the two-tier shape (one Pages, one
|
|
72
|
+
* cron Worker) is the only one ADR 0022 supports today. A second worker target
|
|
73
|
+
* is rejected loudly rather than silently dropped.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildWorkerArtifact(cwd: string, manifestYaml: string, walkFiles: readonly string[]): Promise<BuildWorkerResult>;
|
|
76
|
+
export {};
|
|
77
|
+
//# sourceMappingURL=cron-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-bundle.d.ts","sourceRoot":"","sources":["../../src/bundle/cron-bundle.ts"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,4DAA4D;IAC5D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,2EAA2E;AAC3E,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA0CxE;AAuBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBrE;AAkCD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAgD5B"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Default ignore patterns applied even when no `.gitignore` is
|
|
4
|
+
* present. Mirrors the bot's AC8 ingest policy on dotfiles +
|
|
5
|
+
* common build outputs.
|
|
6
|
+
*
|
|
7
|
+
* Each entry is interpreted as a "match the basename OR a path
|
|
8
|
+
* segment" rule — simpler than full gitignore glob semantics and
|
|
9
|
+
* sufficient for the common cases.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_IGNORE: readonly string[];
|
|
12
|
+
export interface WalkResult {
|
|
13
|
+
/** Relative paths from `cwd`, lexicographically sorted for determinism. */
|
|
14
|
+
readonly files: readonly string[];
|
|
15
|
+
/** Skipped paths and their reason — for `--verbose` output. */
|
|
16
|
+
readonly skipped: ReadonlyArray<{
|
|
17
|
+
path: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export interface WalkOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of files to return. Beyond this the walk
|
|
24
|
+
* aborts with an error rather than producing a partial result —
|
|
25
|
+
* the bot's AC8 caps at 5000 files; the walker errs lower so
|
|
26
|
+
* `launchpad deploy` surfaces "too many files" with a clearer
|
|
27
|
+
* error than a server-side rejection.
|
|
28
|
+
*/
|
|
29
|
+
readonly maxFiles?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class WalkError extends Error {
|
|
32
|
+
constructor(message: string);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Walk `cwd` and produce the list of files to bundle.
|
|
36
|
+
*
|
|
37
|
+
* Pure FS — no network, no shell-out. Respects `.gitignore` if
|
|
38
|
+
* present + the built-in DEFAULT_IGNORE. Skips symlinks
|
|
39
|
+
* silently (the bot rejects them anyway via AC8).
|
|
40
|
+
*/
|
|
41
|
+
export declare function walkCwd(cwd: string, options?: WalkOptions): WalkResult;
|
|
42
|
+
export { relative };
|
|
43
|
+
//# sourceMappingURL=cwd-walker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cwd-walker.d.ts","sourceRoot":"","sources":["../../src/bundle/cwd-walker.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAQ,QAAQ,EAAO,MAAM,WAAW,CAAC;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EA+B3C,CAAC;AAIF,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAID,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CAU1E;AA0LD,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CliConfig } from "../config.js";
|
|
2
|
+
import { type DeployBundleResult } from "./upload.js";
|
|
3
|
+
import { type WalkResult } from "./cwd-walker.js";
|
|
4
|
+
export interface BundleAndDeployArgs {
|
|
5
|
+
readonly cfg: CliConfig;
|
|
6
|
+
readonly cwd: string;
|
|
7
|
+
readonly slug: string;
|
|
8
|
+
}
|
|
9
|
+
export type BundleAndDeployResult = {
|
|
10
|
+
kind: "walk-error";
|
|
11
|
+
message: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "no-manifest";
|
|
14
|
+
message: string;
|
|
15
|
+
} | {
|
|
16
|
+
kind: "pack-error";
|
|
17
|
+
message: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "worker-build-error";
|
|
20
|
+
message: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "upload-error";
|
|
23
|
+
status: number;
|
|
24
|
+
body: unknown;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "ok";
|
|
27
|
+
result: Extract<DeployBundleResult, {
|
|
28
|
+
kind: "ok";
|
|
29
|
+
}>["response"];
|
|
30
|
+
walk: WalkResult;
|
|
31
|
+
fileCount: number;
|
|
32
|
+
compressedBytes: number;
|
|
33
|
+
/** The cron Worker script name that was built + shipped, if any. */
|
|
34
|
+
workerScript: string | null;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Bundle the user's CWD and ship it to the bot.
|
|
38
|
+
*
|
|
39
|
+
* Reads `launchpad.yaml` from `cwd` (it must exist — caller is
|
|
40
|
+
* expected to have invoked `launchpad init` first). Walks the
|
|
41
|
+
* CWD respecting .gitignore + default-ignore, packs the result
|
|
42
|
+
* into a gzipped tar via the existing `packTarGz`, and POSTs the
|
|
43
|
+
* tarball + manifest YAML as multipart/form-data to the bot's
|
|
44
|
+
* `/apps/<slug>/deploy/bundle` endpoint.
|
|
45
|
+
*
|
|
46
|
+
* **What this function does NOT do:** authz pre-flight,
|
|
47
|
+
* provisioning of a not-yet-existing slug, status polling for
|
|
48
|
+
* the live URL. All of those are caller responsibilities.
|
|
49
|
+
*/
|
|
50
|
+
export declare function bundleAndDeploy(args: BundleAndDeployArgs): Promise<BundleAndDeployResult>;
|
|
51
|
+
//# sourceMappingURL=orchestrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrate.d.ts","sourceRoot":"","sources":["../../src/bundle/orchestrate.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACvD;IACE,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,OAAO,CAAC,kBAAkB,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAChE,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEN;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,qBAAqB,CAAC,CAoFhC"}
|