authmi 1.0.0 → 1.2.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.
@@ -0,0 +1,706 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ // src/config.ts
34
+ function resolveConfig(provider) {
35
+ const raw = typeof provider === "function" ? provider() : provider;
36
+ return {
37
+ baseUrl: raw.baseUrl,
38
+ apiKey: raw.apiKey ?? "",
39
+ serviceId: raw.serviceId ?? "",
40
+ clientId: raw.clientId ?? "",
41
+ clientSecret: raw.clientSecret ?? "",
42
+ defaultTokenExpiry: raw.defaultTokenExpiry ?? 24
43
+ };
44
+ }
45
+
46
+ // src/storage/localStorage.ts
47
+ var STORAGE_KEY = "authmi_token";
48
+ var LocalStorageTokenStorage = class {
49
+ canAccess() {
50
+ if (typeof window === "undefined") return false;
51
+ try {
52
+ const probe = "__authmi_storage_test__";
53
+ localStorage.setItem(probe, "1");
54
+ localStorage.removeItem(probe);
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+ getToken() {
61
+ if (!this.canAccess()) return null;
62
+ try {
63
+ return localStorage.getItem(STORAGE_KEY);
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+ setToken(token) {
69
+ if (!this.canAccess()) return;
70
+ try {
71
+ localStorage.setItem(STORAGE_KEY, token);
72
+ } catch {
73
+ }
74
+ }
75
+ removeToken() {
76
+ if (!this.canAccess()) return;
77
+ try {
78
+ localStorage.removeItem(STORAGE_KEY);
79
+ } catch {
80
+ }
81
+ }
82
+ };
83
+
84
+ // src/storage/memory.ts
85
+ var MemoryTokenStorage = class {
86
+ constructor() {
87
+ this.token = null;
88
+ }
89
+ getToken() {
90
+ return this.token;
91
+ }
92
+ setToken(token) {
93
+ this.token = token;
94
+ }
95
+ removeToken() {
96
+ this.token = null;
97
+ }
98
+ };
99
+
100
+ // src/types.ts
101
+ var AuthMiError = class extends Error {
102
+ constructor(message, code, statusCode) {
103
+ super(message);
104
+ this.code = code;
105
+ this.statusCode = statusCode;
106
+ this.name = "AuthMiError";
107
+ }
108
+ };
109
+ var ScopeError = class extends AuthMiError {
110
+ constructor(message, requiredScopes, providedScopes) {
111
+ super(message, "INSUFFICIENT_SCOPES", 403);
112
+ this.requiredScopes = requiredScopes;
113
+ this.providedScopes = providedScopes;
114
+ this.name = "ScopeError";
115
+ }
116
+ };
117
+
118
+ // src/client.ts
119
+ var AuthMiClient = class {
120
+ constructor(config, options) {
121
+ this.configProvider = config;
122
+ this.storage = options?.storage ?? (typeof window !== "undefined" ? new LocalStorageTokenStorage() : new MemoryTokenStorage());
123
+ this.cache = options?.cache || null;
124
+ }
125
+ /** Resolve current config (supports lazy evaluation) */
126
+ get config() {
127
+ return resolveConfig(this.configProvider);
128
+ }
129
+ // ============ HTTP plumbing ============
130
+ async request(endpoint, options = {}, requireUserToken = false, requireServiceAuth = true) {
131
+ const cfg = this.config;
132
+ const url = `${cfg.baseUrl}${endpoint}`;
133
+ const headers = {
134
+ "Content-Type": "application/json",
135
+ ...options.headers || {}
136
+ };
137
+ if (!headers["Authorization"]) {
138
+ if (requireUserToken) {
139
+ const token = await this.storage.getToken();
140
+ if (token) headers["Authorization"] = `Bearer ${token}`;
141
+ } else if (requireServiceAuth && cfg.clientId && cfg.clientSecret) {
142
+ headers["Authorization"] = `Basic ${btoa(`${cfg.clientId}:${cfg.clientSecret}`)}`;
143
+ headers["X-Service-ID"] = cfg.serviceId || cfg.clientId;
144
+ } else if (requireServiceAuth && cfg.apiKey) {
145
+ headers["Authorization"] = `Bearer ${cfg.apiKey}`;
146
+ }
147
+ }
148
+ try {
149
+ const response = await fetch(url, { ...options, headers });
150
+ const data = await response.json();
151
+ if (!response.ok) {
152
+ if (response.status === 403 && data.required && data.provided) {
153
+ throw new ScopeError(
154
+ data.error || "Insufficient scopes",
155
+ data.required,
156
+ data.provided
157
+ );
158
+ }
159
+ throw new AuthMiError(
160
+ data.error || `HTTP ${response.status}`,
161
+ data.code || "UNKNOWN_ERROR",
162
+ response.status
163
+ );
164
+ }
165
+ return data;
166
+ } catch (error) {
167
+ if (error instanceof AuthMiError) throw error;
168
+ throw new AuthMiError(
169
+ error instanceof Error ? error.message : "Network error",
170
+ "NETWORK_ERROR"
171
+ );
172
+ }
173
+ }
174
+ // ============ Configuration ============
175
+ configure(config) {
176
+ const current = resolveConfig(this.configProvider);
177
+ this.configProvider = { ...current, ...config };
178
+ }
179
+ getConfig() {
180
+ const { apiKey: _, clientSecret: __, ...rest } = resolveConfig(this.configProvider);
181
+ return rest;
182
+ }
183
+ // ============ Token Management ============
184
+ async getAccessToken() {
185
+ return this.storage.getToken();
186
+ }
187
+ setAccessToken(token) {
188
+ this.storage.setToken(token);
189
+ }
190
+ clearAccessToken() {
191
+ this.storage.removeToken();
192
+ }
193
+ async isLoggedIn() {
194
+ const token = await this.storage.getToken();
195
+ return !!token;
196
+ }
197
+ // ============ Auth Endpoints ============
198
+ async signup(credentials) {
199
+ const response = await this.request("/api/v1/auth/signup", {
200
+ method: "POST",
201
+ body: JSON.stringify(credentials)
202
+ }, false, false);
203
+ return this.mapAuthToken(response);
204
+ }
205
+ async login(credentials) {
206
+ const cfg = this.config;
207
+ const response = await this.request("/api/v1/auth/login", {
208
+ method: "POST",
209
+ body: JSON.stringify({
210
+ email: credentials.email,
211
+ password: credentials.password,
212
+ client_id: cfg.serviceId,
213
+ expires_in_hours: credentials.expiresInHours || cfg.defaultTokenExpiry,
214
+ scopes: credentials.scopes
215
+ })
216
+ }, false, false);
217
+ const token = this.mapAuthToken(response);
218
+ this.setAccessToken(token.accessToken);
219
+ return token;
220
+ }
221
+ async logout() {
222
+ const token = await this.storage.getToken();
223
+ if (token) {
224
+ try {
225
+ await this.request("/api/v1/auth/logout", { method: "POST" }, true);
226
+ } catch {
227
+ }
228
+ }
229
+ this.clearAccessToken();
230
+ }
231
+ async refreshToken() {
232
+ const response = await this.request("/api/v1/auth/refresh", { method: "POST" }, true);
233
+ const token = {
234
+ accessToken: response.access_token,
235
+ tokenType: "Bearer",
236
+ expiresIn: response.expires_in,
237
+ expiresAt: response.expires_at,
238
+ userId: "",
239
+ email: ""
240
+ };
241
+ this.setAccessToken(token.accessToken);
242
+ return token;
243
+ }
244
+ async getMe() {
245
+ const response = await this.request("/api/v1/auth/me", {}, true);
246
+ return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
247
+ }
248
+ async forgotPassword(request) {
249
+ return this.request("/api/v1/auth/forgot-password", {
250
+ method: "POST",
251
+ body: JSON.stringify({ email: request.email, client_id: this.config.serviceId })
252
+ }, false, false);
253
+ }
254
+ async resetPassword(request) {
255
+ return this.request("/api/v1/auth/reset-password", {
256
+ method: "POST",
257
+ body: JSON.stringify({ token: request.token, new_password: request.newPassword })
258
+ }, false, false);
259
+ }
260
+ async verifyEmail(request) {
261
+ return this.request("/api/v1/auth/verify-email", {
262
+ method: "POST",
263
+ body: JSON.stringify({ token: request.token })
264
+ }, false, false);
265
+ }
266
+ async resendVerification(request) {
267
+ return this.request("/api/v1/auth/resend-verification", {
268
+ method: "POST",
269
+ body: JSON.stringify({ email: request.email, client_id: this.config.serviceId })
270
+ }, false, false);
271
+ }
272
+ async deactivateAccount(password) {
273
+ await this.request("/api/v1/auth/deactivate", {
274
+ method: "POST",
275
+ body: JSON.stringify({ password })
276
+ }, true, false);
277
+ }
278
+ mapAuthToken(raw) {
279
+ return {
280
+ accessToken: raw.access_token,
281
+ tokenType: raw.token_type,
282
+ expiresIn: raw.expires_in,
283
+ expiresAt: raw.expires_at,
284
+ userId: raw.user_id,
285
+ email: raw.email,
286
+ emailVerified: raw.email_verified,
287
+ scopes: raw.scopes
288
+ };
289
+ }
290
+ // ============ OAuth ============
291
+ async initiateOAuth(provider, redirectUri) {
292
+ const cfg = this.config;
293
+ if (!cfg.clientId && !cfg.clientSecret && !cfg.apiKey) {
294
+ throw new AuthMiError("Credentials required for OAuth", "MISSING_CREDENTIALS");
295
+ }
296
+ const response = await this.request("/api/v1/auth/oauth/initiate", {
297
+ method: "POST",
298
+ body: JSON.stringify({ provider, redirectUri, client_id: cfg.serviceId || cfg.clientId })
299
+ }, false, false);
300
+ return response.url;
301
+ }
302
+ handleOAuthCallback(url) {
303
+ const parsed = typeof url === "string" ? new URL(url) : url;
304
+ const token = parsed.searchParams.get("token");
305
+ const userId = parsed.searchParams.get("user_id");
306
+ const email = parsed.searchParams.get("email");
307
+ if (!token || !userId || !email) return null;
308
+ this.setAccessToken(token);
309
+ return { token, userId, email };
310
+ }
311
+ isOAuthCallback(url) {
312
+ const parsed = typeof url === "string" ? new URL(url) : url;
313
+ return !!(parsed.searchParams.has("token") && parsed.searchParams.has("user_id") && parsed.searchParams.has("email"));
314
+ }
315
+ // ============ SAML ============
316
+ async initiateSaml(request) {
317
+ return this.request("/api/v1/auth/saml/initiate", {
318
+ method: "POST",
319
+ body: JSON.stringify({ email: request.email, redirect_uri: request.redirectUri })
320
+ }, false, false);
321
+ }
322
+ async parseSamlMetadata(xml) {
323
+ return this.request("/api/v1/auth/saml/parse-metadata", {
324
+ method: "POST",
325
+ body: JSON.stringify({ metadata_xml: xml })
326
+ }, false, false);
327
+ }
328
+ async listSamlConnections() {
329
+ const response = await this.request("/api/v1/auth/saml/connections");
330
+ return response.connections;
331
+ }
332
+ async createSamlConnection(request) {
333
+ return this.request("/api/v1/auth/saml/connections", {
334
+ method: "POST",
335
+ body: JSON.stringify(request)
336
+ });
337
+ }
338
+ async deleteSamlConnection(id) {
339
+ await this.request(`/api/v1/auth/saml/connections/${encodeURIComponent(id)}`, {
340
+ method: "DELETE"
341
+ });
342
+ }
343
+ // ============ 2FA ============
344
+ async setup2fa() {
345
+ return this.request("/api/v1/auth/2fa/setup", { method: "POST" }, true, false);
346
+ }
347
+ async enable2fa(code) {
348
+ return this.request("/api/v1/auth/2fa/enable", {
349
+ method: "POST",
350
+ body: JSON.stringify({ code })
351
+ }, true, false);
352
+ }
353
+ async disable2fa(password) {
354
+ await this.request("/api/v1/auth/2fa/disable", {
355
+ method: "POST",
356
+ body: JSON.stringify({ password })
357
+ }, true, false);
358
+ }
359
+ async regenerateBackupCodes() {
360
+ return this.request("/api/v1/auth/2fa/backup-codes", { method: "POST" }, true, false);
361
+ }
362
+ async challenge2fa(request) {
363
+ return this.request("/api/v1/auth/2fa/challenge", {
364
+ method: "POST",
365
+ body: JSON.stringify(request)
366
+ }, false, false);
367
+ }
368
+ // ============ Users ============
369
+ async createUser(request) {
370
+ const response = await this.request(
371
+ "/api/v1/users/create",
372
+ {
373
+ method: "POST",
374
+ body: JSON.stringify(request)
375
+ }
376
+ );
377
+ return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
378
+ }
379
+ async listUsers() {
380
+ const response = await this.request("/api/v1/users/list");
381
+ return response.users.map((u) => ({
382
+ userId: u.user_id,
383
+ email: u.email,
384
+ name: u.name,
385
+ createdAt: u.created_at
386
+ }));
387
+ }
388
+ async getUser(userId) {
389
+ const response = await this.request(
390
+ `/api/v1/users/${encodeURIComponent(userId)}`
391
+ );
392
+ return { userId: response.user_id, email: response.email, name: response.name, createdAt: response.created_at };
393
+ }
394
+ async deleteUser(userId) {
395
+ await this.request("/api/v1/users/delete", {
396
+ method: "POST",
397
+ body: JSON.stringify({ user_id: userId })
398
+ });
399
+ }
400
+ async deleteUserById(userId) {
401
+ await this.request(`/api/v1/users/${encodeURIComponent(userId)}`, { method: "DELETE" });
402
+ }
403
+ async updatePassword(userId, oldPassword, newPassword) {
404
+ await this.request("/api/v1/users/password", {
405
+ method: "POST",
406
+ body: JSON.stringify({ user_id: userId, old_password: oldPassword, new_password: newPassword })
407
+ });
408
+ }
409
+ // ============ Roles ============
410
+ async createRole(request) {
411
+ const response = await this.request(
412
+ "/api/v1/users/roles/create",
413
+ { method: "POST", body: JSON.stringify(request) }
414
+ );
415
+ return { roleId: response.role_id, name: response.name, description: response.description, createdAt: response.created_at };
416
+ }
417
+ async listRoles() {
418
+ const response = await this.request("/api/v1/users/roles/list");
419
+ return response.roles.map((r) => ({
420
+ roleId: r.role_id,
421
+ name: r.name,
422
+ description: r.description,
423
+ createdAt: r.created_at
424
+ }));
425
+ }
426
+ async deleteRole(roleId) {
427
+ await this.request(`/api/v1/users/roles/${encodeURIComponent(roleId)}`, { method: "DELETE" });
428
+ }
429
+ async assignRole(userId, roleId) {
430
+ await this.request("/api/v1/users/roles/assign", {
431
+ method: "POST",
432
+ body: JSON.stringify({ user_id: userId, role_id: roleId })
433
+ });
434
+ }
435
+ async unassignRole(userId, roleId) {
436
+ await this.request("/api/v1/users/roles/unassign", {
437
+ method: "POST",
438
+ body: JSON.stringify({ user_id: userId, role_id: roleId })
439
+ });
440
+ }
441
+ async getUserRoles(userId) {
442
+ const response = await this.request(
443
+ `/api/v1/users/${encodeURIComponent(userId)}/roles`
444
+ );
445
+ return response.roles.map((r) => ({
446
+ roleId: r.role_id,
447
+ name: r.name,
448
+ description: r.description,
449
+ createdAt: r.created_at
450
+ }));
451
+ }
452
+ // ============ API Keys ============
453
+ async listApiKeys() {
454
+ const response = await this.request("/api/v1/keys/list");
455
+ return response.keys.map((k) => ({
456
+ keyId: k.keyId,
457
+ name: k.name,
458
+ scope: k.scope,
459
+ scopes: k.scopes,
460
+ keyType: k.keyType,
461
+ tpsLimit: k.tpsLimit,
462
+ revoked: k.revoked,
463
+ createdAt: k.createdAt
464
+ }));
465
+ }
466
+ async createApiKey(request) {
467
+ const response = await this.request(
468
+ "/api/v1/keys/create",
469
+ {
470
+ method: "POST",
471
+ body: JSON.stringify({
472
+ user_id: request.userId,
473
+ name: request.name,
474
+ scope: request.scope || "service",
475
+ scopes: request.scopes,
476
+ key_type: request.keyType || "service",
477
+ tps_limit: request.tpsLimit || 100
478
+ })
479
+ }
480
+ );
481
+ return { keyId: response.key_id, apiKey: response.api_key, name: response.name, scope: response.scope, scopes: response.scopes };
482
+ }
483
+ async revokeApiKey(keyId) {
484
+ await this.request("/api/v1/keys/revoke", {
485
+ method: "POST",
486
+ body: JSON.stringify({ key_id: keyId })
487
+ });
488
+ }
489
+ // ============ Scopes ============
490
+ async listScopes() {
491
+ const response = await this.request("/api/v1/scopes/list");
492
+ return response.scopes;
493
+ }
494
+ async createScope(request) {
495
+ const response = await this.request(
496
+ "/api/v1/scopes/create",
497
+ { method: "POST", body: JSON.stringify(request) }
498
+ );
499
+ return { scopeId: response.scope_id, name: response.name, key: response.key, description: response.description, createdAt: response.created_at };
500
+ }
501
+ async deleteScope(scopeId) {
502
+ await this.request("/api/v1/scopes/delete", {
503
+ method: "POST",
504
+ body: JSON.stringify({ scope_id: scopeId })
505
+ });
506
+ }
507
+ // ============ Introspection & Validation ============
508
+ async introspect(request) {
509
+ if (this.cache && request.token) {
510
+ const cached = this.cache.get(request.token);
511
+ if (cached) return cached;
512
+ }
513
+ const result = await this.request("/api/v1/introspect", {
514
+ method: "POST",
515
+ body: JSON.stringify({
516
+ serviceId: request.serviceId,
517
+ token: request.token,
518
+ apiKey: request.apiKey,
519
+ requiredScopes: request.requiredScopes
520
+ })
521
+ });
522
+ if (this.cache && request.token) {
523
+ this.cache.set(request.token, result);
524
+ }
525
+ return result;
526
+ }
527
+ async validate() {
528
+ const cfg = this.config;
529
+ const token = await this.storage.getToken();
530
+ if (!token) return { valid: false, error: "No token stored" };
531
+ if (!cfg.serviceId) return { valid: false, error: "Service ID not configured" };
532
+ if (!cfg.apiKey && !cfg.clientSecret) return { valid: false, error: "Service credentials not configured" };
533
+ try {
534
+ const result = await this.introspect({ serviceId: cfg.serviceId, token });
535
+ return {
536
+ valid: result.valid,
537
+ type: result.type === "bearer" ? "token" : "api_key",
538
+ scopes: result.scopes,
539
+ userId: result.userId,
540
+ email: result.email,
541
+ error: result.error
542
+ };
543
+ } catch (error) {
544
+ if (error instanceof ScopeError) {
545
+ return { valid: false, error: error.message, scopes: error.providedScopes };
546
+ }
547
+ if (error instanceof AuthMiError && error.statusCode === 401) {
548
+ return { valid: false, error: "Invalid or expired token" };
549
+ }
550
+ throw error;
551
+ }
552
+ }
553
+ async validateWithScopes(requiredScopes) {
554
+ const cfg = this.config;
555
+ const token = await this.storage.getToken();
556
+ if (!token) return { valid: false, error: "No token provided" };
557
+ if (!cfg.apiKey && !cfg.clientSecret) return { valid: false, error: "Service credentials not configured" };
558
+ if (!cfg.serviceId) return { valid: false, error: "Service ID not configured" };
559
+ try {
560
+ const result = await this.introspect({ serviceId: cfg.serviceId, token, requiredScopes });
561
+ return {
562
+ valid: result.valid,
563
+ type: result.type === "bearer" ? "token" : "api_key",
564
+ scopes: result.scopes,
565
+ userId: result.userId,
566
+ email: result.email,
567
+ error: result.error
568
+ };
569
+ } catch (error) {
570
+ if (error instanceof ScopeError) {
571
+ return { valid: false, error: error.message, scopes: error.providedScopes };
572
+ }
573
+ if (error instanceof AuthMiError && error.statusCode === 401) {
574
+ return { valid: false, error: "Invalid or expired token" };
575
+ }
576
+ throw error;
577
+ }
578
+ }
579
+ async requireScopes(...requiredScopes) {
580
+ const result = await this.validateWithScopes(requiredScopes);
581
+ if (!result.valid) {
582
+ throw new AuthMiError(result.error || "Authentication required", "UNAUTHORIZED", 401);
583
+ }
584
+ const hasScopes = requiredScopes.every((s) => result.scopes?.includes(s));
585
+ if (!hasScopes) {
586
+ throw new ScopeError(`Required: ${requiredScopes.join(", ")}`, requiredScopes, result.scopes || []);
587
+ }
588
+ return result;
589
+ }
590
+ async withScope(scopes, fn) {
591
+ await this.requireScopes(...scopes);
592
+ return fn();
593
+ }
594
+ // ============ Webhooks ============
595
+ async listWebhooks() {
596
+ const response = await this.request("/api/v1/webhooks/list");
597
+ return response.webhooks;
598
+ }
599
+ async registerWebhook(request) {
600
+ const response = await this.request(
601
+ "/api/v1/webhooks/register",
602
+ { method: "POST", body: JSON.stringify(request) }
603
+ );
604
+ return { webhookId: response.webhook_id, url: response.url, events: response.events, active: response.active, createdAt: response.created_at };
605
+ }
606
+ async deleteWebhook(webhookId) {
607
+ await this.request("/api/v1/webhooks/delete", {
608
+ method: "POST",
609
+ body: JSON.stringify({ webhook_id: webhookId })
610
+ });
611
+ }
612
+ // ============ Billing ============
613
+ async listPlans() {
614
+ const response = await this.request("/api/v1/billing/plans");
615
+ return response.plans;
616
+ }
617
+ async getSubscription() {
618
+ return this.request("/api/v1/billing/subscription");
619
+ }
620
+ async createCheckout(priceId) {
621
+ return this.request("/api/v1/billing/checkout", {
622
+ method: "POST",
623
+ body: JSON.stringify({ price_id: priceId })
624
+ });
625
+ }
626
+ async createPortalSession() {
627
+ return this.request("/api/v1/billing/portal", { method: "POST" });
628
+ }
629
+ // ============ Audit ============
630
+ async getAuditLogs(query) {
631
+ const params = new URLSearchParams();
632
+ if (query?.limit) params.set("limit", String(query.limit));
633
+ if (query?.offset) params.set("offset", String(query.offset));
634
+ if (query?.actorId) params.set("actor_id", query.actorId);
635
+ if (query?.action) params.set("action", query.action);
636
+ if (query?.resourceType) params.set("resource_type", query.resourceType);
637
+ if (query?.startDate) params.set("start_date", query.startDate);
638
+ if (query?.endDate) params.set("end_date", query.endDate);
639
+ const qs = params.toString();
640
+ const response = await this.request(
641
+ `/api/v1/audit-logs${qs ? `?${qs}` : ""}`
642
+ );
643
+ return response.logs;
644
+ }
645
+ // ============ Services ============
646
+ async getService(serviceId) {
647
+ return this.request(`/api/v1/services/${encodeURIComponent(serviceId)}`);
648
+ }
649
+ async updateService(serviceId, data) {
650
+ return this.request(`/api/v1/services/${encodeURIComponent(serviceId)}`, {
651
+ method: "POST",
652
+ body: JSON.stringify(data)
653
+ });
654
+ }
655
+ async rotateClientSecret(serviceId) {
656
+ return this.request(
657
+ `/api/v1/services/${encodeURIComponent(serviceId)}/rotate-secret`,
658
+ { method: "POST" }
659
+ );
660
+ }
661
+ // ============ JWKS ============
662
+ async getJwks(serviceId) {
663
+ return this.request(`/.well-known/jwks.json?service_id=${encodeURIComponent(serviceId)}`);
664
+ }
665
+ // ============ Onboarding (admin only) ============
666
+ async onboardService(request, masterAdminKey) {
667
+ const response = await this.request("/api/v1/services/onboard", {
668
+ method: "POST",
669
+ headers: {
670
+ "x-onboarding-admin-key": masterAdminKey
671
+ },
672
+ body: JSON.stringify({
673
+ service_name: request.serviceName,
674
+ owner_email: request.ownerEmail
675
+ })
676
+ });
677
+ return {
678
+ serviceId: response.service_id,
679
+ serviceName: response.service_name,
680
+ ownerEmail: response.owner_email,
681
+ adminKeyId: response.admin_key_id,
682
+ serviceAdminApiKey: response.service_admin_api_key,
683
+ createdAt: response.created_at
684
+ };
685
+ }
686
+ async deleteService(serviceId, masterAdminKey) {
687
+ await this.request("/api/v1/services/deboard", {
688
+ method: "POST",
689
+ headers: {
690
+ "x-onboarding-admin-key": masterAdminKey
691
+ },
692
+ body: JSON.stringify({ service_id: serviceId })
693
+ });
694
+ }
695
+ };
696
+
697
+ export {
698
+ __require,
699
+ __commonJS,
700
+ __toESM,
701
+ LocalStorageTokenStorage,
702
+ MemoryTokenStorage,
703
+ AuthMiError,
704
+ ScopeError,
705
+ AuthMiClient
706
+ };