@theholocron/holocron-plugin-clerk 2.0.0-alpha.20 → 2.0.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,59 +1,14 @@
1
- import { Auth, AuthDescription, AuthEvent, AuthIdentity, AuthUser, CreateAuthUserInput, ParseWebhookInput, WebhookDashboardInfo } from "@theholocron/cli";
1
+ import { Auth, AuthDescription, AuthError, AuthEvent, AuthIdentity, AuthUser, CreateAuthUserInput, ParseWebhookInput, ResolveTokenInput, RestClient, RestClient as RestClient$1, WebhookDashboardInfo } from "@theholocron/cli";
2
2
 
3
3
  //#region src/auth.d.ts
4
- /**
5
- * Token resolution for the Clerk 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_CLERK_SECRET_KEY env var (preferred — explicit intent)
11
- * 3. CLERK_SECRET_KEY env var (the default Clerk's docs reference)
12
- * 4. keyring (com.theholocron.cli / "clerk")
13
- * 5. AuthError naming all four options + the bootstrap hint
14
- *
15
- * The key (sk_test_* / sk_live_*) determines which Clerk instance —
16
- * Development or Production — every call hits.
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.clerk.com/v1.
34
- *
35
- * Same pattern as the github/vercel/neon REST clients — bearer auth,
36
- * JSON-only bodies, transport-failure wrapping with `status: 0` so the
37
- * orchestrator's soft-skip path sees a clear "Clerk GET /path failed"
38
- * message instead of a generic `TypeError: fetch failed`.
39
- */
40
- interface RestClientOptions {
7
+ declare function createClerkRestClient(opts: {
41
8
  token: string;
42
- fetch?: typeof fetch;
43
9
  baseUrl?: string;
44
- }
45
- interface RequestOptions {
46
- method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
47
- body?: unknown;
48
- query?: Record<string, string>;
49
- }
50
- declare class ClerkRestClient {
51
- private readonly token;
52
- private readonly fetchImpl;
53
- readonly baseUrl: string;
54
- constructor(opts: RestClientOptions);
55
- request<T>(path: string, opts?: RequestOptions): Promise<T>;
56
- }
10
+ fetch?: typeof fetch;
11
+ }): RestClient$1;
57
12
  //#endregion
58
13
  //#region src/capabilities/auth.d.ts
59
14
  type ClerkAuthOptions = Record<string, never>;
@@ -61,7 +16,7 @@ declare class ClerkAuth implements Auth {
61
16
  private readonly rest;
62
17
  readonly key: "auth";
63
18
  readonly providerName = "clerk";
64
- constructor(rest: ClerkRestClient, _opts?: ClerkAuthOptions);
19
+ constructor(rest: RestClient, _opts?: ClerkAuthOptions);
65
20
  describe(): Promise<AuthDescription>;
66
21
  whoami(): Promise<AuthIdentity>;
67
22
  ensureWebhookApp(): Promise<{
@@ -109,7 +64,7 @@ interface ClerkPluginOptions extends ResolveTokenInput {
109
64
  }
110
65
  interface PluginContext {
111
66
  options: ClerkPluginOptions;
112
- rest: ClerkRestClient;
67
+ rest: RestClient;
113
68
  }
114
69
  declare function createContext(options?: ClerkPluginOptions): PluginContext;
115
70
  declare function auth(ctx: PluginContext): Auth;
@@ -127,4 +82,4 @@ declare function createPlugin(options?: ClerkPluginOptions): {
127
82
  */
128
83
  declare const AUTH_HINT: string;
129
84
  //#endregion
130
- export { AUTH_HINT, AuthError, ClerkAuth, ClerkPluginOptions, ClerkRestClient, PluginContext, ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, auth, createContext, createPlugin, parseWebhook, resolveToken, verifyToken };
85
+ export { AUTH_HINT, AuthError, ClerkAuth, ClerkPluginOptions, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, auth, createClerkRestClient, createContext, createPlugin, parseWebhook, resolveToken, verifyToken };
package/dist/index.mjs CHANGED
@@ -1,29 +1,11 @@
1
- import { ProviderApiError, WebhookVerificationError, getToken } from "@theholocron/cli";
1
+ import { AuthError, ProviderApiError, WebhookVerificationError, createResolveToken, createRestClient } from "@theholocron/cli";
2
2
  //#region src/auth.ts
3
- /**
4
- * Token resolution for the Clerk 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_CLERK_SECRET_KEY env var (preferred — explicit intent)
10
- * 3. CLERK_SECRET_KEY env var (the default Clerk's docs reference)
11
- * 4. keyring (com.theholocron.cli / "clerk")
12
- * 5. AuthError naming all four options + the bootstrap hint
13
- *
14
- * The key (sk_test_* / sk_live_*) determines which Clerk instance —
15
- * Development or Production — every call hits.
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_CLERK_SECRET_KEY"] || env["CLERK_SECRET_KEY"] || keyring("clerk");
24
- if (!token) throw new AuthError("no Clerk secret key found. Pass --token <KEY>, set HOLOCRON_CLERK_SECRET_KEY / CLERK_SECRET_KEY, or run: holocron auth set clerk <KEY>");
25
- return token;
26
- }
3
+ const resolveToken = createResolveToken({
4
+ envName: "HOLOCRON_CLERK_SECRET_KEY",
5
+ vendorEnvName: "CLERK_SECRET_KEY",
6
+ keyringService: "clerk",
7
+ errorMessage: "no Clerk secret key found. Pass --token <KEY>, set HOLOCRON_CLERK_SECRET_KEY / CLERK_SECRET_KEY, or run: holocron auth set clerk <KEY>"
8
+ });
27
9
  //#endregion
28
10
  //#region src/capabilities/auth.ts
29
11
  /**
@@ -116,58 +98,14 @@ function isAlreadyExistsError(err) {
116
98
  }
117
99
  //#endregion
118
100
  //#region src/rest.ts
119
- /**
120
- * Thin REST wrapper around api.clerk.com/v1.
121
- *
122
- * Same pattern as the github/vercel/neon REST clients — bearer auth,
123
- * JSON-only bodies, transport-failure wrapping with `status: 0` so the
124
- * orchestrator's soft-skip path sees a clear "Clerk GET /path failed"
125
- * message instead of a generic `TypeError: fetch failed`.
126
- */
127
- var ClerkRestClient = class {
128
- token;
129
- fetchImpl;
130
- baseUrl;
131
- constructor(opts) {
132
- this.token = opts.token;
133
- this.fetchImpl = opts.fetch ?? globalThis.fetch;
134
- let url = opts.baseUrl ?? "https://api.clerk.com/v1";
135
- while (url.endsWith("/")) url = url.slice(0, -1);
136
- this.baseUrl = url;
137
- }
138
- async request(path, opts = {}) {
139
- const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : "/" + path}`);
140
- for (const [k, v] of Object.entries(opts.query ?? {})) url.searchParams.set(k, v);
141
- const fullUrl = url.toString();
142
- const headers = {
143
- authorization: `Bearer ${this.token}`,
144
- accept: "application/json"
145
- };
146
- const init = {
147
- method: opts.method ?? "GET",
148
- headers
149
- };
150
- if (opts.body !== void 0) {
151
- headers["content-type"] = "application/json";
152
- init.body = JSON.stringify(opts.body);
153
- }
154
- let res;
155
- try {
156
- res = await this.fetchImpl(fullUrl, init);
157
- } catch (err) {
158
- const detail = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
159
- throw new ProviderApiError(`Clerk ${init.method} ${path} failed: ${detail}`, 0, void 0);
160
- }
161
- if (!res.ok) {
162
- const body = await res.text().catch(() => "");
163
- throw new ProviderApiError(`Clerk ${init.method} ${path} → ${res.status}`, res.status, body);
164
- }
165
- if (res.status === 204) return void 0;
166
- const text = await res.text();
167
- if (!text) return void 0;
168
- return JSON.parse(text);
169
- }
170
- };
101
+ function createClerkRestClient(opts) {
102
+ return createRestClient({
103
+ baseUrl: opts.baseUrl ?? "https://api.clerk.com/v1",
104
+ token: opts.token,
105
+ vendor: "Clerk",
106
+ fetch: opts.fetch
107
+ });
108
+ }
171
109
  //#endregion
172
110
  //#region src/parse-webhook.ts
173
111
  /**
@@ -248,10 +186,11 @@ async function verifySignature(input) {
248
186
  * canonical "is this secret key valid?" endpoint.
249
187
  */
250
188
  async function verifyToken(token, opts = {}) {
251
- const restOpts = { token };
252
- if (opts.baseUrl !== void 0) restOpts.baseUrl = opts.baseUrl;
253
- if (opts.fetch !== void 0) restOpts.fetch = opts.fetch;
254
- const rest = new ClerkRestClient(restOpts);
189
+ const rest = createClerkRestClient({
190
+ token,
191
+ baseUrl: opts.baseUrl,
192
+ fetch: opts.fetch
193
+ });
255
194
  try {
256
195
  const instance = await rest.request("/instance");
257
196
  return {
@@ -268,12 +207,13 @@ async function verifyToken(token, opts = {}) {
268
207
  //#endregion
269
208
  //#region src/index.ts
270
209
  function createContext(options = {}) {
271
- const restOpts = { token: resolveToken(options) };
272
- if (options.baseUrl !== void 0) restOpts.baseUrl = options.baseUrl;
273
- if (options.fetch !== void 0) restOpts.fetch = options.fetch;
274
210
  return {
275
211
  options,
276
- rest: new ClerkRestClient(restOpts)
212
+ rest: createClerkRestClient({
213
+ token: resolveToken(options),
214
+ baseUrl: options.baseUrl,
215
+ fetch: options.fetch
216
+ })
277
217
  };
278
218
  }
279
219
  function auth(ctx) {
@@ -294,4 +234,4 @@ function createPlugin(options = {}) {
294
234
  */
295
235
  const AUTH_HINT = "grab your SECRET key (sk_test_* / sk_live_*) at https://dashboard.clerk.com → API Keys, then run: holocron auth set clerk <KEY>. Do NOT use the publishable key.";
296
236
  //#endregion
297
- export { AUTH_HINT, AuthError, ClerkAuth, ClerkRestClient, auth, createContext, createPlugin, parseWebhook, resolveToken, verifyToken };
237
+ export { AUTH_HINT, AuthError, ClerkAuth, auth, createClerkRestClient, createContext, createPlugin, parseWebhook, resolveToken, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-clerk",
3
- "version": "2.0.0-alpha.20",
3
+ "version": "2.0.0-alpha.22",
4
4
  "description": "Holocron plugin for Clerk. Implements the auth capability against Clerk's Backend REST API.",
5
5
  "homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-clerk#readme",
6
6
  "bugs": "https://github.com/theholocron/holocron/issues",
@@ -21,13 +21,14 @@
21
21
  }
22
22
  },
23
23
  "peerDependencies": {
24
- "@theholocron/cli": "2.0.0-alpha.20"
24
+ "@theholocron/cli": "2.0.0-alpha.22"
25
25
  },
26
26
  "devDependencies": {
27
- "@theholocron/eslint-config": "^5.1.2",
28
- "@theholocron/tsconfig": "^5.1.2",
29
- "@tsconfig/node-lts": "^24.0.0",
30
- "@vitest/coverage-v8": "^3.2.6",
27
+ "@types/node": "^26",
28
+ "@theholocron/eslint-config": "^5.2.0",
29
+ "@theholocron/tsconfig": "^6.0.0",
30
+ "@theholocron/tsdown-config": "^5.1.2",
31
+ "@theholocron/vitest-config": "^5.2.0",
31
32
  "@vitest/eslint-plugin": "^1.6.23",
32
33
  "eslint": "^10.7.0",
33
34
  "eslint-plugin-n": "^18.2.2",
@@ -35,8 +36,8 @@
35
36
  "tsdown": "^0.22.3",
36
37
  "tsx": "^4.22.4",
37
38
  "typescript": "^5.9.3",
38
- "vitest": "^3.2.6",
39
- "@theholocron/cli": "2.0.0-alpha.20"
39
+ "vitest": "^4.1.10",
40
+ "@theholocron/cli": "2.0.0-alpha.22"
40
41
  },
41
42
  "publishConfig": {
42
43
  "access": "public"