@theholocron/holocron-plugin-vercel 2.0.0-alpha.0 → 2.0.0-alpha.10

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/README.md CHANGED
@@ -3,6 +3,12 @@
3
3
  Vercel plugin for [Holocron](../cli). Implements the `deployment`
4
4
  capability against the [Vercel REST API](https://vercel.com/docs/rest-api).
5
5
 
6
+ ## Install
7
+
8
+ ```bash
9
+ pnpm add -D @theholocron/holocron-plugin-vercel@alpha
10
+ ```
11
+
6
12
  ## Auth
7
13
 
8
14
  Token resolution order:
@@ -20,18 +26,22 @@ always cover what holocron needs at the API level. Explicit token only.
20
26
  ```jsonc
21
27
  // holocron.config.json
22
28
  {
23
- "providers": {
24
- "deployment": ["vercel", { "teamId": "team_xxx" }]
25
- }
29
+ "providers": {
30
+ "deployment": ["vercel", { "teamId": "team_xxx" }],
31
+ },
26
32
  }
27
33
  ```
28
34
 
29
35
  - `teamId` (optional) — Vercel team id. When set, all requests are
30
- scoped to that team. Leave unset for personal-account projects.
36
+ scoped to that team. Leave unset for personal-account projects.
31
37
 
32
38
  ## Status
33
39
 
34
- **v0.0.0 — first port.** Capability covers:
40
+ **`v2.0.0-alpha.0`**published on npm under the `alpha` dist-tag.
41
+ [Release notes](https://github.com/theholocron/holocron/releases/tag/v2.0.0-alpha.0).
42
+ APIs may still shift before stable v2.0.0.
43
+
44
+ Capability covers:
35
45
 
36
46
  - `listProjects()` / `ensureProject()` — idempotent project create
37
47
  - `updateProjectSettings()` — toggle preview deploys, git-creates-deploys
@@ -39,7 +49,7 @@ always cover what holocron needs at the API level. Explicit token only.
39
49
  - `triggerDeployment()` — branch deploys with optional named target
40
50
  - `getDeployment()` — fetch a deployment by id
41
51
 
42
- Out of scope for v1 (file a follow-up if needed):
52
+ Out of scope for alpha.0 (file a follow-up if needed):
43
53
 
44
54
  - Domain management (`addDomain` / `removeDomain`)
45
55
  - Deletion (`deleteProject`)
package/dist/index.d.mts CHANGED
@@ -4,10 +4,13 @@ import { Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRec
4
4
  /**
5
5
  * Token resolution for the Vercel plugin.
6
6
  *
7
- * Resolution order:
7
+ * Resolution order (matches the standard 4-step precedence set by
8
+ * `.notes/tech-auth-bootstrap.spec.md`):
8
9
  * 1. explicit `cliToken` argument (from `--token` flag)
9
10
  * 2. HOLOCRON_VERCEL_TOKEN env var (preferred — explicit intent)
10
11
  * 3. VERCEL_TOKEN env var (the default the Vercel CLI also reads)
12
+ * 4. keyring (com.theholocron.cli / "vercel")
13
+ * 5. AuthError naming all four options + the bootstrap hint
11
14
  *
12
15
  * No `vercel auth` fallback — Vercel CLI auth is per-account-scoped
13
16
  * and the resulting tokens don't always cover team operations.
@@ -20,6 +23,8 @@ interface ResolveTokenInput {
20
23
  cliToken?: string;
21
24
  /** Env vars; passed in for testability. Defaults to `process.env`. */
22
25
  env?: NodeJS.ProcessEnv;
26
+ /** Keyring lookup fn; passed in for testability. Defaults to `getToken(provider)`. */
27
+ keyring?: (provider: string) => string | null;
23
28
  }
24
29
  declare function resolveToken(input?: ResolveTokenInput): string;
25
30
  //#endregion
@@ -43,7 +48,7 @@ interface RestClientOptions {
43
48
  baseUrl?: string;
44
49
  }
45
50
  interface RequestOptions {
46
- method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
51
+ method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
47
52
  body?: unknown;
48
53
  /** Additional query-string params. */
49
54
  query?: Record<string, string>;
@@ -88,6 +93,27 @@ declare class VercelDeployment implements Deployment {
88
93
  private getProjectByName;
89
94
  }
90
95
  //#endregion
96
+ //#region src/verify-token.d.ts
97
+ /**
98
+ * `verifyToken` — plugin-level export used by `holocron auth set` +
99
+ * `holocron auth check`. Hits `GET /v2/user` and translates the
100
+ * response into the normalized `VerifyTokenResult` shape.
101
+ */
102
+ interface VerifyTokenSuccess {
103
+ ok: true;
104
+ subject: string;
105
+ }
106
+ interface VerifyTokenFailure {
107
+ ok: false;
108
+ message: string;
109
+ }
110
+ type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;
111
+ interface VerifyTokenOptions {
112
+ baseUrl?: string;
113
+ fetch?: typeof fetch;
114
+ }
115
+ declare function verifyToken(token: string, opts?: VerifyTokenOptions): Promise<VerifyTokenResult>;
116
+ //#endregion
91
117
  //#region src/index.d.ts
92
118
  interface VercelPluginOptions extends ResolveTokenInput {
93
119
  /** Vercel team id. Set when working with a team-owned project. */
@@ -111,5 +137,12 @@ declare function createPlugin(options?: VercelPluginOptions): {
111
137
  deployment: () => Deployment;
112
138
  };
113
139
  };
140
+ /**
141
+ * One-line hint printed by `holocron auth set vercel` when no token
142
+ * is supplied or the supplied token is rejected. Points operators at
143
+ * https://vercel.com/account/tokens where PATs are minted with
144
+ * "Full Account" scope for team-level ops.
145
+ */
146
+ declare const AUTH_HINT: string;
114
147
  //#endregion
115
- export { AuthError, PluginContext, ResolveTokenInput, VercelDeployment, VercelPluginOptions, VercelRestClient, createContext, createPlugin, deployment, resolveToken };
148
+ export { AUTH_HINT, AuthError, PluginContext, ResolveTokenInput, VercelDeployment, VercelPluginOptions, VercelRestClient, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createPlugin, deployment, resolveToken, verifyToken };
package/dist/index.mjs CHANGED
@@ -1,12 +1,15 @@
1
- import { ProviderApiError } from "@theholocron/cli";
1
+ import { ProviderApiError, getToken } from "@theholocron/cli";
2
2
  //#region src/auth.ts
3
3
  /**
4
4
  * Token resolution for the Vercel plugin.
5
5
  *
6
- * Resolution order:
6
+ * Resolution order (matches the standard 4-step precedence set by
7
+ * `.notes/tech-auth-bootstrap.spec.md`):
7
8
  * 1. explicit `cliToken` argument (from `--token` flag)
8
9
  * 2. HOLOCRON_VERCEL_TOKEN env var (preferred — explicit intent)
9
10
  * 3. VERCEL_TOKEN env var (the default the Vercel CLI also reads)
11
+ * 4. keyring (com.theholocron.cli / "vercel")
12
+ * 5. AuthError naming all four options + the bootstrap hint
10
13
  *
11
14
  * No `vercel auth` fallback — Vercel CLI auth is per-account-scoped
12
15
  * and the resulting tokens don't always cover team operations.
@@ -16,8 +19,9 @@ var AuthError = class extends Error {
16
19
  };
17
20
  function resolveToken(input = {}) {
18
21
  const env = input.env ?? process.env;
19
- const token = input.cliToken || env.HOLOCRON_VERCEL_TOKEN || env.VERCEL_TOKEN;
20
- if (!token) throw new AuthError("no Vercel token found. Pass --token <PAT>, or set HOLOCRON_VERCEL_TOKEN / VERCEL_TOKEN.");
22
+ const keyring = input.keyring ?? getToken;
23
+ const token = input.cliToken || env["HOLOCRON_VERCEL_TOKEN"] || env["VERCEL_TOKEN"] || keyring("vercel");
24
+ if (!token) throw new AuthError("no Vercel token found. Pass --token <PAT>, set HOLOCRON_VERCEL_TOKEN / VERCEL_TOKEN, or run: holocron auth set vercel <PAT>");
21
25
  return token;
22
26
  }
23
27
  //#endregion
@@ -176,7 +180,9 @@ var VercelRestClient = class {
176
180
  this.token = opts.token;
177
181
  if (opts.teamId !== void 0) this.teamId = opts.teamId;
178
182
  this.fetchImpl = opts.fetch ?? globalThis.fetch;
179
- this.baseUrl = (opts.baseUrl ?? "https://api.vercel.com").replace(/\/+$/, "");
183
+ let url = opts.baseUrl ?? "https://api.vercel.com";
184
+ while (url.endsWith("/")) url = url.slice(0, -1);
185
+ this.baseUrl = url;
180
186
  }
181
187
  async request(path, opts = {}) {
182
188
  const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : "/" + path}`);
@@ -213,6 +219,31 @@ var VercelRestClient = class {
213
219
  }
214
220
  };
215
221
  //#endregion
222
+ //#region src/verify-token.ts
223
+ /**
224
+ * `verifyToken` — plugin-level export used by `holocron auth set` +
225
+ * `holocron auth check`. Hits `GET /v2/user` and translates the
226
+ * response into the normalized `VerifyTokenResult` shape.
227
+ */
228
+ async function verifyToken(token, opts = {}) {
229
+ const restOpts = { token };
230
+ if (opts.baseUrl !== void 0) restOpts.baseUrl = opts.baseUrl;
231
+ if (opts.fetch !== void 0) restOpts.fetch = opts.fetch;
232
+ const rest = new VercelRestClient(restOpts);
233
+ try {
234
+ const res = await rest.request("/v2/user");
235
+ return {
236
+ ok: true,
237
+ subject: `user @ ${res?.user?.email ?? res?.user?.username ?? res?.user?.name ?? res?.user?.id ?? "unknown"}`
238
+ };
239
+ } catch (err) {
240
+ return {
241
+ ok: false,
242
+ message: err instanceof Error ? err.message : String(err)
243
+ };
244
+ }
245
+ }
246
+ //#endregion
216
247
  //#region src/index.ts
217
248
  function createContext(options = {}) {
218
249
  const restOpts = { token: resolveToken(options) };
@@ -236,5 +267,12 @@ function createPlugin(options = {}) {
236
267
  capabilities: { deployment: () => deployment(ctx) }
237
268
  };
238
269
  }
270
+ /**
271
+ * One-line hint printed by `holocron auth set vercel` when no token
272
+ * is supplied or the supplied token is rejected. Points operators at
273
+ * https://vercel.com/account/tokens where PATs are minted with
274
+ * "Full Account" scope for team-level ops.
275
+ */
276
+ const AUTH_HINT = "generate a Vercel Personal Access Token at https://vercel.com/account/tokens (scope: Full Account for team ops), then run: holocron auth set vercel <PAT>";
239
277
  //#endregion
240
- export { AuthError, VercelDeployment, VercelRestClient, createContext, createPlugin, deployment, resolveToken };
278
+ export { AUTH_HINT, AuthError, VercelDeployment, VercelRestClient, createContext, createPlugin, deployment, resolveToken, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-vercel",
3
- "version": "2.0.0-alpha.0",
3
+ "version": "2.0.0-alpha.10",
4
4
  "description": "Holocron plugin for Vercel. Implements the deployment capability against the Vercel REST API.",
5
5
  "homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-vercel#readme",
6
6
  "bugs": "https://github.com/theholocron/holocron/issues",
@@ -21,7 +21,7 @@
21
21
  }
22
22
  },
23
23
  "peerDependencies": {
24
- "@theholocron/cli": "2.0.0-alpha.0"
24
+ "@theholocron/cli": "2.0.0-alpha.10"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@theholocron/tsconfig": "^4.1.0",
@@ -32,7 +32,8 @@
32
32
  "typescript": "^5.9.3",
33
33
  "vitest": "^3.2.6",
34
34
  "tsdown": "^0.22.3",
35
- "@theholocron/cli": "2.0.0-alpha.0"
35
+ "tsx": "^4.22.4",
36
+ "@theholocron/cli": "2.0.0-alpha.10"
36
37
  },
37
38
  "publishConfig": {
38
39
  "access": "public"
@@ -47,7 +48,8 @@
47
48
  "typecheck": "tsc --noEmit",
48
49
  "test": "vitest run",
49
50
  "test:watch": "vitest",
50
- "test:coverage": "vitest run --coverage"
51
+ "test:coverage": "vitest run --coverage",
52
+ "validate": "tsx scripts/validate.mjs"
51
53
  },
52
54
  "types": "./dist/index.d.mts"
53
55
  }