@authyon/server 0.1.5

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.js ADDED
@@ -0,0 +1,477 @@
1
+ // src/errors.ts
2
+ var AuthyonError = class extends Error {
3
+ constructor(status, body) {
4
+ super(body.detail ?? body.title ?? `Authyon request failed with status ${status}`);
5
+ this.name = "AuthyonError";
6
+ this.status = status;
7
+ this.code = body.code ?? "unknown";
8
+ this.title = body.title ?? "Error";
9
+ this.detail = body.detail;
10
+ }
11
+ is(code) {
12
+ return this.code === code;
13
+ }
14
+ };
15
+
16
+ // src/client.ts
17
+ var DEFAULT_BASE_URL = "https://api.authyon.com";
18
+ var EXPIRY_SKEW_MS = 3e4;
19
+ function toQuery(params = {}) {
20
+ const query = new URLSearchParams();
21
+ for (const [key, value] of Object.entries(params)) {
22
+ if (value !== void 0) query.set(key, String(value));
23
+ }
24
+ const qs = query.toString();
25
+ return qs ? `?${qs}` : "";
26
+ }
27
+ var AuthyonServerClient = class {
28
+ constructor(options = {}) {
29
+ this.environmentToken = null;
30
+ this.environmentTokenInFlight = null;
31
+ // ── Discovery ──────────────────────────────────────────────────────────────
32
+ this.discovery = {
33
+ /** GET /.well-known/jwks.json — the environment's public signing keys. */
34
+ jwks: (publishableKey) => this.request(
35
+ publishableKey ? `/.well-known/${encodeURIComponent(publishableKey)}/jwks.json` : "/.well-known/jwks.json"
36
+ ),
37
+ /** GET /.well-known/openid-configuration — OIDC discovery document. */
38
+ openidConfiguration: (publishableKey) => this.request(
39
+ publishableKey ? `/.well-known/${encodeURIComponent(publishableKey)}/openid-configuration` : "/.well-known/openid-configuration"
40
+ )
41
+ };
42
+ // ── Environment-level machine auth ───────────────────────────────────────
43
+ this.environmentAuth = {
44
+ /** POST /env/oauth/token — exchanges environment client credentials for an access token. */
45
+ token: (credentials) => this.request("/env/oauth/token", {
46
+ method: "POST",
47
+ body: {
48
+ grant_type: "client_credentials",
49
+ client_id: credentials.clientId,
50
+ client_secret: credentials.clientSecret
51
+ }
52
+ })
53
+ };
54
+ // ── Tenant-level machine auth ─────────────────────────────────────────────
55
+ this.tenantAuth = {
56
+ /** POST /tenant/oauth/token — exchanges a tenant's client credentials for a scoped access token. */
57
+ token: (credentials) => this.request("/tenant/oauth/token", {
58
+ method: "POST",
59
+ body: {
60
+ grant_type: "client_credentials",
61
+ client_id: credentials.clientId,
62
+ client_secret: credentials.clientSecret
63
+ }
64
+ })
65
+ };
66
+ // ── Environment management (users, tenants, roles, permissions, audit) ───
67
+ this.environment = {
68
+ users: {
69
+ /** GET /env/users — paginated list of users in the environment. */
70
+ list: (params = {}) => this.request("/env/users", { envBearer: true, query: params }),
71
+ /** POST /env/users — create a user in the environment; returns only the new id. */
72
+ create: (input) => this.request("/env/users", { method: "POST", envBearer: true, body: input }),
73
+ /** GET /env/users/{userId} — fetch an environment user by id. */
74
+ get: (userId) => this.request(`/env/users/${encodeURIComponent(userId)}`, { envBearer: true }),
75
+ /** POST /env/users/{userId}/roles — grant a role to an environment user. */
76
+ assignRole: (userId, role) => this.request(`/env/users/${encodeURIComponent(userId)}/roles`, {
77
+ method: "POST",
78
+ envBearer: true,
79
+ body: { role }
80
+ }),
81
+ /** DELETE /env/users/{userId}/roles/{role} — revoke a role from an environment user. */
82
+ removeRole: (userId, role) => this.request(`/env/users/${encodeURIComponent(userId)}/roles/${encodeURIComponent(role)}`, {
83
+ method: "DELETE",
84
+ envBearer: true
85
+ }),
86
+ /** POST /env/users/{userId}/permissions — grant a direct permission to an environment user. */
87
+ grantPermission: (userId, permission) => this.request(`/env/users/${encodeURIComponent(userId)}/permissions`, {
88
+ method: "POST",
89
+ envBearer: true,
90
+ body: { permission }
91
+ }),
92
+ /** DELETE /env/users/{userId}/permissions/{permission} — revoke a direct permission. */
93
+ revokePermission: (userId, permission) => this.request(
94
+ `/env/users/${encodeURIComponent(userId)}/permissions/${encodeURIComponent(permission)}`,
95
+ { method: "DELETE", envBearer: true }
96
+ ),
97
+ /** POST /env/users/{userId}/unlock — clears an environment user's lockout. */
98
+ unlock: (userId, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/unlock`, {
99
+ method: "POST",
100
+ envBearer: true,
101
+ body: { reason }
102
+ }),
103
+ /** POST /env/users/{userId}/password — sets a new password for the user. */
104
+ setPassword: (userId, newPassword, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/password`, {
105
+ method: "POST",
106
+ envBearer: true,
107
+ body: { newPassword, reason }
108
+ }),
109
+ /** POST /env/users/{userId}/sessions/revoke-all — revokes every session the user has. */
110
+ revokeSessions: (userId, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/sessions/revoke-all`, {
111
+ method: "POST",
112
+ envBearer: true,
113
+ body: { reason }
114
+ }),
115
+ /** DELETE /env/users/{userId}/sessions/{sessionId} — revokes a single session. */
116
+ revokeSession: (userId, sessionId, reason) => this.request(
117
+ `/env/users/${encodeURIComponent(userId)}/sessions/${encodeURIComponent(sessionId)}`,
118
+ { method: "DELETE", envBearer: true, query: { reason } }
119
+ ),
120
+ /** POST /env/users/{userId}/disable — bans the user indefinitely; revokes live sessions. */
121
+ disable: (userId, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/disable`, {
122
+ method: "POST",
123
+ envBearer: true,
124
+ body: { reason }
125
+ }),
126
+ /** POST /env/users/{userId}/enable — lifts a ban. */
127
+ enable: (userId, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/enable`, {
128
+ method: "POST",
129
+ envBearer: true,
130
+ body: { reason }
131
+ }),
132
+ /** POST /env/users/{userId}/suspend — blocks the user temporarily; clears itself after `durationMinutes`. */
133
+ suspend: (userId, durationMinutes, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/suspend`, {
134
+ method: "POST",
135
+ envBearer: true,
136
+ body: { durationMinutes, reason }
137
+ }),
138
+ /** POST /env/users/{userId}/unsuspend — lifts a suspension early. */
139
+ unsuspend: (userId, reason) => this.request(`/env/users/${encodeURIComponent(userId)}/unsuspend`, {
140
+ method: "POST",
141
+ envBearer: true,
142
+ body: { reason }
143
+ }),
144
+ /** POST /env/users/{userId}/tenants — adds an environment user to a tenant. */
145
+ assignTenant: (userId, tenantId, roles) => this.request(`/env/users/${encodeURIComponent(userId)}/tenants`, {
146
+ method: "POST",
147
+ envBearer: true,
148
+ body: { tenantId, roles }
149
+ }),
150
+ /** DELETE /env/users/{userId}/tenants/{tenantId} — removes an environment user from a tenant. */
151
+ removeTenant: (userId, tenantId) => this.request(
152
+ `/env/users/${encodeURIComponent(userId)}/tenants/${encodeURIComponent(tenantId)}`,
153
+ { method: "DELETE", envBearer: true }
154
+ )
155
+ },
156
+ tenants: {
157
+ /** GET /env/tenants — list tenants in the environment. */
158
+ list: () => this.request("/env/tenants", { envBearer: true }),
159
+ /** POST /env/tenants — create a tenant in the environment. */
160
+ create: (input) => this.request("/env/tenants", { method: "POST", envBearer: true, body: input }),
161
+ /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
162
+ get: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, { envBearer: true }),
163
+ /** PUT /env/tenants/{tenantId} — update a tenant. */
164
+ update: (tenantId, input) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, {
165
+ method: "PUT",
166
+ envBearer: true,
167
+ body: input
168
+ }),
169
+ /** DELETE /env/tenants/{tenantId} — delete a tenant. */
170
+ delete: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}`, {
171
+ method: "DELETE",
172
+ envBearer: true
173
+ }),
174
+ members: {
175
+ /**
176
+ * GET /env/tenants/{tenantId}/members — a tenant's members as full
177
+ * user records. Confirmed live: a bare array (unlike
178
+ * `environment.users.list()`, this one does NOT paginate despite
179
+ * accepting `skip`/`take`), with the same shape
180
+ * `environment.users.list()` items have.
181
+ */
182
+ list: (tenantId, params = {}) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/members`, {
183
+ envBearer: true,
184
+ query: params
185
+ }),
186
+ /** POST /env/tenants/{tenantId}/members — add a member to a tenant. */
187
+ add: (tenantId, userId, roles) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/members`, {
188
+ method: "POST",
189
+ envBearer: true,
190
+ body: { userId, roles }
191
+ }),
192
+ /** DELETE /env/tenants/{tenantId}/members/{userId} — remove a member from a tenant. */
193
+ remove: (tenantId, userId) => this.request(
194
+ `/env/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}`,
195
+ { method: "DELETE", envBearer: true }
196
+ ),
197
+ /** POST /env/tenants/{tenantId}/members/{userId}/roles — grant a tenant role to a member. */
198
+ assignRole: (tenantId, userId, role) => this.request(
199
+ `/env/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}/roles`,
200
+ { method: "POST", envBearer: true, body: { role } }
201
+ ),
202
+ /** DELETE .../members/{userId}/roles/{role} — revoke a tenant role from a member. */
203
+ removeRole: (tenantId, userId, role) => this.request(
204
+ `/env/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}/roles/${encodeURIComponent(role)}`,
205
+ { method: "DELETE", envBearer: true }
206
+ ),
207
+ /** POST .../members/{userId}/permissions — grant a permission to a tenant member. */
208
+ grantPermission: (tenantId, userId, permission) => this.request(
209
+ `/env/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}/permissions`,
210
+ { method: "POST", envBearer: true, body: { permission } }
211
+ ),
212
+ /** DELETE .../members/{userId}/permissions/{permission} — revoke a permission from a tenant member. */
213
+ revokePermission: (tenantId, userId, permission) => this.request(
214
+ `/env/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}/permissions/${encodeURIComponent(permission)}`,
215
+ { method: "DELETE", envBearer: true }
216
+ )
217
+ },
218
+ roles: {
219
+ /** GET /env/tenants/{tenantId}/roles — list a tenant's roles. */
220
+ list: (tenantId) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/roles`, { envBearer: true }),
221
+ /** POST /env/tenants/{tenantId}/roles — create a tenant role. */
222
+ create: (tenantId, input) => this.request(`/env/tenants/${encodeURIComponent(tenantId)}/roles`, {
223
+ method: "POST",
224
+ envBearer: true,
225
+ body: input
226
+ }),
227
+ /** GET /env/tenants/{tenantId}/roles/{roleId} — fetch a tenant role by id. */
228
+ get: (tenantId, roleId) => this.request(
229
+ `/env/tenants/${encodeURIComponent(tenantId)}/roles/${encodeURIComponent(roleId)}`,
230
+ { envBearer: true }
231
+ ),
232
+ /** PUT /env/tenants/{tenantId}/roles/{roleId} — update a tenant role. */
233
+ update: (tenantId, roleId, input) => this.request(
234
+ `/env/tenants/${encodeURIComponent(tenantId)}/roles/${encodeURIComponent(roleId)}`,
235
+ { method: "PUT", envBearer: true, body: input }
236
+ ),
237
+ /** DELETE /env/tenants/{tenantId}/roles/{roleId} — delete a tenant role. */
238
+ delete: (tenantId, roleId) => this.request(
239
+ `/env/tenants/${encodeURIComponent(tenantId)}/roles/${encodeURIComponent(roleId)}`,
240
+ { method: "DELETE", envBearer: true }
241
+ )
242
+ }
243
+ },
244
+ roles: {
245
+ /** GET /env/roles — environment-level roles, grouped into custom and system-defined. */
246
+ list: () => this.request("/env/roles", { envBearer: true }),
247
+ /** POST /env/roles — create an environment-level role. */
248
+ create: (input) => this.request("/env/roles", { method: "POST", envBearer: true, body: input }),
249
+ /** PUT /env/roles/{roleId} — update an environment-level role. */
250
+ update: (roleId, input) => this.request(`/env/roles/${encodeURIComponent(roleId)}`, {
251
+ method: "PUT",
252
+ envBearer: true,
253
+ body: input
254
+ }),
255
+ /** DELETE /env/roles/{roleId} — delete an environment-level role. */
256
+ delete: (roleId) => this.request(`/env/roles/${encodeURIComponent(roleId)}`, {
257
+ method: "DELETE",
258
+ envBearer: true
259
+ })
260
+ },
261
+ permissions: {
262
+ /** GET /env/permissions — environment-level permissions, grouped by the role they're attached to. */
263
+ list: () => this.request("/env/permissions", { envBearer: true }),
264
+ /** POST /env/permissions — create an environment-level permission. */
265
+ create: (input) => this.request("/env/permissions", { method: "POST", envBearer: true, body: input }),
266
+ /** PUT /env/permissions/{permissionId} — update an environment-level permission. */
267
+ update: (permissionId, description) => this.request(`/env/permissions/${encodeURIComponent(permissionId)}`, {
268
+ method: "PUT",
269
+ envBearer: true,
270
+ body: { description }
271
+ }),
272
+ /** DELETE /env/permissions/{permissionId} — delete an environment-level permission. */
273
+ delete: (permissionId) => this.request(`/env/permissions/${encodeURIComponent(permissionId)}`, {
274
+ method: "DELETE",
275
+ envBearer: true
276
+ }),
277
+ /** GET /permissions/reserved — reserved permission names you can't redefine. */
278
+ reserved: () => this.request("/permissions/reserved", { envBearer: true })
279
+ },
280
+ audit: {
281
+ /** GET /env/audit — paginated list of the environment's audit events. */
282
+ list: (params = {}) => this.request("/env/audit", { envBearer: true, query: params }),
283
+ /** GET /env/audit/login-activity — paginated login activity in the environment. */
284
+ loginActivity: (params = {}) => this.request("/env/audit/login-activity", { envBearer: true, query: params })
285
+ }
286
+ };
287
+ // ── Generic permission grants ─────────────────────────────────────────────
288
+ this.permissions = {
289
+ /** POST /users/{userId}/permissions — grant a permission directly to a user. */
290
+ grant: (userId, permission) => this.request(`/users/${encodeURIComponent(userId)}/permissions`, {
291
+ method: "POST",
292
+ envBearer: true,
293
+ body: { permission }
294
+ }),
295
+ /** DELETE /users/{userId}/permissions/{permission} — revoke a permission from a user. */
296
+ revoke: (userId, permission) => this.request(
297
+ `/users/${encodeURIComponent(userId)}/permissions/${encodeURIComponent(permission)}`,
298
+ { method: "DELETE", envBearer: true }
299
+ )
300
+ };
301
+ this.envKey = options.envKey;
302
+ this.clientId = options.clientId;
303
+ this.clientSecret = options.clientSecret;
304
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
305
+ this.fetchImpl = options.fetch ?? fetch.bind(globalThis);
306
+ }
307
+ async request(path, options = {}) {
308
+ const headers = { ...options.headers };
309
+ if (options.body !== void 0) headers["Content-Type"] = "application/json";
310
+ if (options.envBearer) {
311
+ headers.Authorization = `Bearer ${await this.getEnvironmentAccessToken()}`;
312
+ }
313
+ if (this.envKey) headers["X-Authyon-Environment"] = this.envKey;
314
+ const response = await this.fetchImpl(`${this.baseUrl}${path}${toQuery(options.query)}`, {
315
+ method: options.method ?? "GET",
316
+ headers,
317
+ body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
318
+ });
319
+ if (!response.ok) {
320
+ let body = {};
321
+ try {
322
+ body = await response.json();
323
+ } catch {
324
+ }
325
+ throw new AuthyonError(response.status, body);
326
+ }
327
+ if (response.status === 204) return void 0;
328
+ return await response.json();
329
+ }
330
+ /** Mints (and caches) an environment access token from `clientId`/`clientSecret`. */
331
+ async getEnvironmentAccessToken() {
332
+ if (this.environmentToken && Date.now() < this.environmentToken.expiresAt - EXPIRY_SKEW_MS) {
333
+ return this.environmentToken.accessToken;
334
+ }
335
+ if (this.environmentTokenInFlight) return this.environmentTokenInFlight;
336
+ if (!this.clientId || !this.clientSecret) {
337
+ throw new Error(
338
+ "Authyon: `clientId`/`clientSecret` are required for environment management calls (mint a pair in the console, under the environment's OAuth clients)."
339
+ );
340
+ }
341
+ this.environmentTokenInFlight = this.environmentAuth.token({ clientId: this.clientId, clientSecret: this.clientSecret }).then((token) => {
342
+ this.environmentToken = {
343
+ accessToken: token.access_token,
344
+ expiresAt: Date.now() + token.expires_in * 1e3
345
+ };
346
+ return token.access_token;
347
+ }).finally(() => {
348
+ this.environmentTokenInFlight = null;
349
+ });
350
+ return this.environmentTokenInFlight;
351
+ }
352
+ // ── Token verification ────────────────────────────────────────────────────
353
+ //
354
+ // Per RFC 7662 §2.1, the CALLER must authenticate here too — the token
355
+ // being inspected sits in the body, but the request itself needs an
356
+ // environment (or tenant) client-credentials bearer token, same as
357
+ // `environment.*`. Confirmed against the live API: calling either
358
+ // endpoint with only the `X-Authyon-Environment` header (no bearer)
359
+ // returns 401 with `WWW-Authenticate: Bearer`.
360
+ /** POST /auth/introspect — lightweight token introspection (RFC 7662). */
361
+ introspect(token) {
362
+ return this.request("/auth/introspect", { method: "POST", envBearer: true, body: { token } });
363
+ }
364
+ /** POST /auth/validate — recommended: cross-checks DB state, catches revocation immediately. */
365
+ async validate(token) {
366
+ const raw = await this.request("/auth/validate", { method: "POST", envBearer: true, body: { token } });
367
+ return { valid: raw.valid, reason: raw.reason ?? null, user: raw.profile };
368
+ }
369
+ /**
370
+ * Scopes a client to a single tenant's OAuth credentials — mints and
371
+ * caches its access token independently of the environment plane. Use
372
+ * this for the `TenantManagement` endpoints (`/tenant/...`), which act on
373
+ * "the token's tenant" rather than one you pass by id.
374
+ */
375
+ tenant(credentials) {
376
+ return new TenantScopedClient(this, credentials);
377
+ }
378
+ /** @internal used by {@link TenantScopedClient} to share the base URL/fetch/error handling. */
379
+ _requestAsTenant(accessToken, path, options = {}) {
380
+ return this.request(path, {
381
+ ...options,
382
+ headers: { ...options.headers, Authorization: `Bearer ${accessToken}` },
383
+ envBearer: false
384
+ });
385
+ }
386
+ };
387
+ var TenantScopedClient = class {
388
+ constructor(server, credentials) {
389
+ this.token = null;
390
+ this.tokenInFlight = null;
391
+ this.members = {
392
+ /**
393
+ * GET /tenant/members — members of the token's tenant.
394
+ *
395
+ * ⚠️ Inferred, not confirmed live (no tenant client credentials
396
+ * available to exchange for a scoped token) — assumed to share
397
+ * `/env/tenants/{id}/members`'s confirmed shape (bare array of full
398
+ * user records), since both are the "admin" member listing as opposed
399
+ * to `/auth/tenants/{id}/members`'s paginated, lightweight one.
400
+ */
401
+ list: (params = {}) => this.request("/tenant/members", { query: params }),
402
+ /** POST /tenant/members — add a member to the token's tenant. */
403
+ add: (userId, roles) => this.request("/tenant/members", { method: "POST", body: { userId, roles } }),
404
+ /** DELETE /tenant/members/{userId} — remove a member from the token's tenant. */
405
+ remove: (userId) => this.request(`/tenant/members/${encodeURIComponent(userId)}`, { method: "DELETE" }),
406
+ /** POST /tenant/members/{userId}/roles — grant a role to a member of the tenant. */
407
+ assignRole: (userId, role) => this.request(`/tenant/members/${encodeURIComponent(userId)}/roles`, {
408
+ method: "POST",
409
+ body: { role }
410
+ }),
411
+ /** DELETE /tenant/members/{userId}/roles/{role} — revoke a role from a member of the tenant. */
412
+ removeRole: (userId, role) => this.request(
413
+ `/tenant/members/${encodeURIComponent(userId)}/roles/${encodeURIComponent(role)}`,
414
+ { method: "DELETE" }
415
+ ),
416
+ /** POST /tenant/members/{userId}/permissions — grant a permission to a member of the tenant. */
417
+ grantPermission: (userId, permission) => this.request(`/tenant/members/${encodeURIComponent(userId)}/permissions`, {
418
+ method: "POST",
419
+ body: { permission }
420
+ }),
421
+ /** DELETE .../permissions/{permission} — revoke a permission from a member of the tenant. */
422
+ revokePermission: (userId, permission) => this.request(
423
+ `/tenant/members/${encodeURIComponent(userId)}/permissions/${encodeURIComponent(permission)}`,
424
+ { method: "DELETE" }
425
+ )
426
+ };
427
+ this.roles = {
428
+ /**
429
+ * GET /tenant/roles — roles in the token's tenant, grouped into custom
430
+ * and system-defined.
431
+ *
432
+ * ⚠️ Inferred, not confirmed live (the test environment had no tenants
433
+ * to exchange a scoped token for) — assumed to share `/env/roles`'
434
+ * grouped shape, since both operate on the same underlying role model.
435
+ */
436
+ list: () => this.request("/tenant/roles"),
437
+ /** POST /tenant/roles — create a role in the tenant. */
438
+ create: (input) => this.request("/tenant/roles", { method: "POST", body: input }),
439
+ /** GET /tenant/roles/{roleId} — fetch a tenant role by id. */
440
+ get: (roleId) => this.request(`/tenant/roles/${encodeURIComponent(roleId)}`),
441
+ /** PUT /tenant/roles/{roleId} — update a role in the tenant. */
442
+ update: (roleId, input) => this.request(`/tenant/roles/${encodeURIComponent(roleId)}`, { method: "PUT", body: input }),
443
+ /** DELETE /tenant/roles/{roleId} — delete a role in the tenant. */
444
+ delete: (roleId) => this.request(`/tenant/roles/${encodeURIComponent(roleId)}`, { method: "DELETE" })
445
+ };
446
+ this.server = server;
447
+ this.credentials = credentials;
448
+ }
449
+ async getAccessToken() {
450
+ if (this.token && Date.now() < this.token.expiresAt - EXPIRY_SKEW_MS) {
451
+ return this.token.accessToken;
452
+ }
453
+ if (this.tokenInFlight) return this.tokenInFlight;
454
+ this.tokenInFlight = this.server.tenantAuth.token(this.credentials).then((token) => {
455
+ this.token = {
456
+ accessToken: token.access_token,
457
+ expiresAt: Date.now() + token.expires_in * 1e3
458
+ };
459
+ return token.access_token;
460
+ }).finally(() => {
461
+ this.tokenInFlight = null;
462
+ });
463
+ return this.tokenInFlight;
464
+ }
465
+ async request(path, options = {}) {
466
+ return this.server._requestAsTenant(await this.getAccessToken(), path, options);
467
+ }
468
+ };
469
+ function createClient(options = {}) {
470
+ return new AuthyonServerClient(options);
471
+ }
472
+ export {
473
+ AuthyonError,
474
+ AuthyonServerClient,
475
+ TenantScopedClient,
476
+ createClient
477
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@authyon/server",
3
+ "version": "0.1.5",
4
+ "description": "Authyon SDK for backends — server-to-server organization/member management and access-token verification.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "sideEffects": false,
21
+ "scripts": {
22
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "keywords": [
26
+ "authyon",
27
+ "auth",
28
+ "server-to-server",
29
+ "management-api",
30
+ "token-verification"
31
+ ],
32
+ "devDependencies": {
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5.5.0"
35
+ }
36
+ }