@theholocron/holocron-plugin-vercel 2.0.0-alpha.5 → 2.0.0-alpha.51

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
@@ -1,3 +1,5 @@
1
+ <!-- editorconfig-checker-disable-file -->
2
+
1
3
  # `@theholocron/holocron-plugin-vercel`
2
4
 
3
5
  Vercel plugin for [Holocron](../cli). Implements the `deployment`
@@ -5,8 +7,10 @@ capability against the [Vercel REST API](https://vercel.com/docs/rest-api).
5
7
 
6
8
  ## Install
7
9
 
10
+ <!-- prettier-ignore -->
8
11
  ```bash
9
12
  pnpm add -D @theholocron/holocron-plugin-vercel@alpha
13
+
10
14
  ```
11
15
 
12
16
  ## Auth
@@ -23,17 +27,19 @@ always cover what holocron needs at the API level. Explicit token only.
23
27
 
24
28
  ## Config
25
29
 
30
+ <!-- prettier-ignore -->
26
31
  ```jsonc
27
32
  // holocron.config.json
28
33
  {
29
- "providers": {
30
- "deployment": ["vercel", { "teamId": "team_xxx" }],
31
- },
34
+ "providers": {
35
+ "deployment": ["vercel", { "teamId": "team_xxx" }],
36
+ },
32
37
  }
38
+
33
39
  ```
34
40
 
35
41
  - `teamId` (optional) — Vercel team id. When set, all requests are
36
- scoped to that team. Leave unset for personal-account projects.
42
+ scoped to that team. Leave unset for personal-account projects.
37
43
 
38
44
  ## Status
39
45
 
package/dist/index.d.mts CHANGED
@@ -1,66 +1,15 @@
1
- import { Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger } from "@theholocron/cli";
1
+ import { AuthError, Deployment, DeploymentProject, DeploymentProjectSettings, DeploymentRecord, DeploymentTarget, DeploymentTrigger, ResolveTokenInput, RestClient, RestClient as RestClient$1 } from "@theholocron/cli";
2
2
 
3
3
  //#region src/auth.d.ts
4
- /**
5
- * Token resolution for the Vercel plugin.
6
- *
7
- * Resolution order (matches the standard 4-step precedence set by
8
- * `.notes/tech-auth-bootstrap.spec.md`):
9
- * 1. explicit `cliToken` argument (from `--token` flag)
10
- * 2. HOLOCRON_VERCEL_TOKEN env var (preferred — explicit intent)
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
14
- *
15
- * No `vercel auth` fallback — Vercel CLI auth is per-account-scoped
16
- * and the resulting tokens don't always cover team operations.
17
- */
18
- declare class AuthError extends Error {
19
- name: string;
20
- }
21
- interface ResolveTokenInput {
22
- /** From `--token` CLI flag. */
23
- cliToken?: string;
24
- /** Env vars; passed in for testability. Defaults to `process.env`. */
25
- env?: NodeJS.ProcessEnv;
26
- /** Keyring lookup fn; passed in for testability. Defaults to `getToken(provider)`. */
27
- keyring?: (provider: string) => string | null;
28
- }
29
- declare function resolveToken(input?: ResolveTokenInput): string;
4
+ declare const resolveToken: (input?: import("@theholocron/http-client").ResolveTokenInput) => string;
30
5
  //#endregion
31
6
  //#region src/rest.d.ts
32
- /**
33
- * Thin REST wrapper around api.vercel.com.
34
- *
35
- * Differences from the GitHub REST client:
36
- * - Vercel uses simple `Bearer <token>` (no api-version header)
37
- * - Team scoping is a query-string param (`teamId=...`), not a path
38
- * prefix; the client appends it to every URL when configured
39
- * - 204 responses are honored the same way; transport failures get
40
- * wrapped in `ProviderApiError` with `status: 0` for clear hint
41
- * output
42
- */
43
- interface RestClientOptions {
7
+ declare function createVercelRestClient(opts: {
44
8
  token: string;
45
- /** Vercel team id. When set, scoped to that team for every request. */
46
9
  teamId?: string;
47
- fetch?: typeof fetch;
48
10
  baseUrl?: string;
49
- }
50
- interface RequestOptions {
51
- method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
52
- body?: unknown;
53
- /** Additional query-string params. */
54
- query?: Record<string, string>;
55
- }
56
- declare class VercelRestClient {
57
- private readonly token;
58
- private readonly teamId?;
59
- private readonly fetchImpl;
60
- readonly baseUrl: string;
61
- constructor(opts: RestClientOptions);
62
- request<T>(path: string, opts?: RequestOptions): Promise<T>;
63
- }
11
+ fetch?: typeof fetch;
12
+ }): RestClient$1;
64
13
  //#endregion
65
14
  //#region src/capabilities/deployment.d.ts
66
15
  interface DeploymentOptions {
@@ -72,7 +21,7 @@ declare class VercelDeployment implements Deployment {
72
21
  readonly key: "deployment";
73
22
  readonly providerName = "vercel";
74
23
  private readonly defaultFramework;
75
- constructor(rest: VercelRestClient, opts?: DeploymentOptions);
24
+ constructor(rest: RestClient, opts?: DeploymentOptions);
76
25
  listProjects(): Promise<DeploymentProject[]>;
77
26
  ensureProject(input: {
78
27
  name: string;
@@ -127,7 +76,7 @@ interface VercelPluginOptions extends ResolveTokenInput {
127
76
  }
128
77
  interface PluginContext {
129
78
  options: VercelPluginOptions;
130
- rest: VercelRestClient;
79
+ rest: RestClient;
131
80
  }
132
81
  declare function createContext(options?: VercelPluginOptions): PluginContext;
133
82
  declare function deployment(ctx: PluginContext): Deployment;
@@ -145,4 +94,4 @@ declare function createPlugin(options?: VercelPluginOptions): {
145
94
  */
146
95
  declare const AUTH_HINT: string;
147
96
  //#endregion
148
- export { AUTH_HINT, AuthError, PluginContext, ResolveTokenInput, VercelDeployment, VercelPluginOptions, VercelRestClient, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createPlugin, deployment, resolveToken, verifyToken };
97
+ export { AUTH_HINT, AuthError, PluginContext, type ResolveTokenInput, VercelDeployment, VercelPluginOptions, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createContext, createPlugin, createVercelRestClient, deployment, resolveToken, verifyToken };
package/dist/index.mjs CHANGED
@@ -1,29 +1,11 @@
1
- import { ProviderApiError, getToken } from "@theholocron/cli";
1
+ import { AuthError, ProviderApiError, createResolveToken, createRestClient } from "@theholocron/cli";
2
2
  //#region src/auth.ts
3
- /**
4
- * Token resolution for the Vercel plugin.
5
- *
6
- * Resolution order (matches the standard 4-step precedence set by
7
- * `.notes/tech-auth-bootstrap.spec.md`):
8
- * 1. explicit `cliToken` argument (from `--token` flag)
9
- * 2. HOLOCRON_VERCEL_TOKEN env var (preferred — explicit intent)
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
13
- *
14
- * No `vercel auth` fallback — Vercel CLI auth is per-account-scoped
15
- * and the resulting tokens don't always cover team operations.
16
- */
17
- var AuthError = class extends Error {
18
- name = "AuthError";
19
- };
20
- function resolveToken(input = {}) {
21
- const env = input.env ?? process.env;
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>");
25
- return token;
26
- }
3
+ const resolveToken = createResolveToken({
4
+ envName: "HOLOCRON_VERCEL_TOKEN",
5
+ vendorEnvName: "VERCEL_TOKEN",
6
+ keyringService: "vercel",
7
+ errorMessage: "no Vercel token found. Pass --token <PAT>, set HOLOCRON_VERCEL_TOKEN / VERCEL_TOKEN, or run: holocron auth set vercel <PAT>"
8
+ });
27
9
  //#endregion
28
10
  //#region src/capabilities/deployment.ts
29
11
  /**
@@ -160,64 +142,15 @@ function normalizeState(s) {
160
142
  }
161
143
  //#endregion
162
144
  //#region src/rest.ts
163
- /**
164
- * Thin REST wrapper around api.vercel.com.
165
- *
166
- * Differences from the GitHub REST client:
167
- * - Vercel uses simple `Bearer <token>` (no api-version header)
168
- * - Team scoping is a query-string param (`teamId=...`), not a path
169
- * prefix; the client appends it to every URL when configured
170
- * - 204 responses are honored the same way; transport failures get
171
- * wrapped in `ProviderApiError` with `status: 0` for clear hint
172
- * output
173
- */
174
- var VercelRestClient = class {
175
- token;
176
- teamId;
177
- fetchImpl;
178
- baseUrl;
179
- constructor(opts) {
180
- this.token = opts.token;
181
- if (opts.teamId !== void 0) this.teamId = opts.teamId;
182
- this.fetchImpl = opts.fetch ?? globalThis.fetch;
183
- let url = opts.baseUrl ?? "https://api.vercel.com";
184
- while (url.endsWith("/")) url = url.slice(0, -1);
185
- this.baseUrl = url;
186
- }
187
- async request(path, opts = {}) {
188
- const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : "/" + path}`);
189
- if (this.teamId) url.searchParams.set("teamId", this.teamId);
190
- for (const [k, v] of Object.entries(opts.query ?? {})) url.searchParams.set(k, v);
191
- const fullUrl = url.toString();
192
- const headers = {
193
- authorization: `Bearer ${this.token}`,
194
- accept: "application/json"
195
- };
196
- const init = {
197
- method: opts.method ?? "GET",
198
- headers
199
- };
200
- if (opts.body !== void 0) {
201
- headers["content-type"] = "application/json";
202
- init.body = JSON.stringify(opts.body);
203
- }
204
- let res;
205
- try {
206
- res = await this.fetchImpl(fullUrl, init);
207
- } catch (err) {
208
- const detail = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
209
- throw new ProviderApiError(`Vercel ${init.method} ${path} failed: ${detail}`, 0, void 0);
210
- }
211
- if (!res.ok) {
212
- const body = await res.text().catch(() => "");
213
- throw new ProviderApiError(`Vercel ${init.method} ${path} → ${res.status}`, res.status, body);
214
- }
215
- if (res.status === 204) return void 0;
216
- const text = await res.text();
217
- if (!text) return void 0;
218
- return JSON.parse(text);
219
- }
220
- };
145
+ function createVercelRestClient(opts) {
146
+ return createRestClient({
147
+ baseUrl: opts.baseUrl ?? "https://api.vercel.com",
148
+ token: opts.token,
149
+ defaultQuery: opts.teamId ? { teamId: opts.teamId } : void 0,
150
+ vendor: "Vercel",
151
+ fetch: opts.fetch
152
+ });
153
+ }
221
154
  //#endregion
222
155
  //#region src/verify-token.ts
223
156
  /**
@@ -226,10 +159,11 @@ var VercelRestClient = class {
226
159
  * response into the normalized `VerifyTokenResult` shape.
227
160
  */
228
161
  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);
162
+ const rest = createVercelRestClient({
163
+ token,
164
+ baseUrl: opts.baseUrl,
165
+ fetch: opts.fetch
166
+ });
233
167
  try {
234
168
  const res = await rest.request("/v2/user");
235
169
  return {
@@ -246,13 +180,14 @@ async function verifyToken(token, opts = {}) {
246
180
  //#endregion
247
181
  //#region src/index.ts
248
182
  function createContext(options = {}) {
249
- const restOpts = { token: resolveToken(options) };
250
- if (options.teamId !== void 0) restOpts.teamId = options.teamId;
251
- if (options.baseUrl !== void 0) restOpts.baseUrl = options.baseUrl;
252
- if (options.fetch !== void 0) restOpts.fetch = options.fetch;
253
183
  return {
254
184
  options,
255
- rest: new VercelRestClient(restOpts)
185
+ rest: createVercelRestClient({
186
+ token: resolveToken(options),
187
+ teamId: options.teamId,
188
+ baseUrl: options.baseUrl,
189
+ fetch: options.fetch
190
+ })
256
191
  };
257
192
  }
258
193
  function deployment(ctx) {
@@ -275,4 +210,4 @@ function createPlugin(options = {}) {
275
210
  */
276
211
  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>";
277
212
  //#endregion
278
- export { AUTH_HINT, AuthError, VercelDeployment, VercelRestClient, createContext, createPlugin, deployment, resolveToken, verifyToken };
213
+ export { AUTH_HINT, AuthError, VercelDeployment, createContext, createPlugin, createVercelRestClient, 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.5",
3
+ "version": "2.0.0-alpha.51",
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,19 +21,23 @@
21
21
  }
22
22
  },
23
23
  "peerDependencies": {
24
- "@theholocron/cli": "2.0.0-alpha.5"
24
+ "@theholocron/cli": "2.0.0-alpha.51"
25
25
  },
26
26
  "devDependencies": {
27
- "@theholocron/tsconfig": "^4.1.0",
28
- "@tsconfig/node-lts": "^24.0.0",
29
- "@vitest/coverage-v8": "^3.2.6",
30
- "eslint": "^9.36.0",
31
- "globals": "^16.5.0",
32
- "typescript": "^5.9.3",
33
- "vitest": "^3.2.6",
27
+ "@types/node": "^26",
28
+ "@theholocron/eslint-config": "^7.0.0",
29
+ "@theholocron/tsconfig": "^7.0.0",
30
+ "@theholocron/tsdown-config": "^7.0.0",
31
+ "@theholocron/vitest-config": "^7.0.0",
32
+ "@vitest/eslint-plugin": "^1.6.23",
33
+ "eslint": "^10.7.0",
34
+ "eslint-plugin-n": "^18.2.2",
35
+ "globals": "^17.7.0",
34
36
  "tsdown": "^0.22.3",
35
37
  "tsx": "^4.22.4",
36
- "@theholocron/cli": "2.0.0-alpha.5"
38
+ "typescript": "^5.9.3",
39
+ "vitest": "^4.1.10",
40
+ "@theholocron/cli": "2.0.0-alpha.51"
37
41
  },
38
42
  "publishConfig": {
39
43
  "access": "public"