@softwarepatterns/am 0.0.1 → 0.1.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.
- package/README.md +87 -79
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +367 -82
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types/auth.d.ts +218 -75
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +141 -7
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard error object following RFC 7807 (Problem Details for HTTP APIs).
|
|
3
|
+
*
|
|
4
|
+
* Returned in AuthError.problem when the server responds with application/problem+json.
|
|
5
|
+
*
|
|
6
|
+
* - `type`: A URI reference that identifies the problem type. Often links to human-readable documentation.
|
|
7
|
+
* - `title`: A short, human-readable summary of the problem type.
|
|
8
|
+
* - `status`: The HTTP status code.
|
|
9
|
+
* - `code`: Application-specific error code for programmatic handling. Maps to the final part of the error type.
|
|
10
|
+
* - `detail`: Human-readable explanation specific to this occurrence. Do not rely on this for programmatic handling.
|
|
11
|
+
* - `invalidParams`: Present on validation errors (typically 400). Provides field-level details
|
|
12
|
+
* for building precise UI feedback and can be used for programmatic handling. Each entry includes:
|
|
13
|
+
* - `in`: Location of the invalid parameter (body, cookie, header, query, path).
|
|
14
|
+
* - `path`: Dot-separated path to the invalid parameter.
|
|
15
|
+
* - `type`: Error type code for this parameter (e.g. "required", "email", "min_length").
|
|
16
|
+
* - `received`: The actual value received.
|
|
17
|
+
* - `expected`: (optional) Description of the expected value.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* catch (e) {
|
|
22
|
+
* if (e instanceof AuthError && e.invalidParams) {
|
|
23
|
+
* const errors = e.invalidParams.reduce((acc, p) => {
|
|
24
|
+
* acc[p.path] = p.type;
|
|
25
|
+
* return acc;
|
|
26
|
+
* }, {} as Record<string, string>);
|
|
27
|
+
* setFieldErrors(errors);
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
1
32
|
type ProblemDetails = {
|
|
2
33
|
type: string;
|
|
3
34
|
title: string;
|
|
@@ -12,28 +43,98 @@ type ProblemDetails = {
|
|
|
12
43
|
expected?: string;
|
|
13
44
|
}[];
|
|
14
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Opaque identifier for a client application.
|
|
48
|
+
*
|
|
49
|
+
* Used to look up client-specific settings on how authentication should be handled.
|
|
50
|
+
*
|
|
51
|
+
* All client-specific operations (invites, branding, rate limits) are scoped to a ClientId.
|
|
52
|
+
*/
|
|
15
53
|
type ClientId = `cid${string}`;
|
|
54
|
+
/** Identifier for a user. */
|
|
16
55
|
type UserId = `uid${string}`;
|
|
56
|
+
/** Identifier for an account (i.e., a billable entity). */
|
|
17
57
|
type AccountId = `acc${string}`;
|
|
58
|
+
/** Identifier for a membership linking a user to an account. */
|
|
18
59
|
type MembershipId = `mbr${string}`;
|
|
19
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Possible statuses for an account.
|
|
62
|
+
*
|
|
63
|
+
* - active: Normal operation
|
|
64
|
+
* - trial: In trial period
|
|
65
|
+
* - past_due: Payment failed but grace period active
|
|
66
|
+
* - suspended: Access restricted due to billing or policy
|
|
67
|
+
* - closed: Permanently closed
|
|
68
|
+
*/
|
|
69
|
+
type AccountStatus = "active" | "trial" | "past_due" | "suspended" | "closed";
|
|
70
|
+
/**
|
|
71
|
+
* Accounts are billable entities that can access resources. Users are linked to accounts via memberships with roles.
|
|
72
|
+
*
|
|
73
|
+
* An account with subaccounts is acting as a tenant, and is used to create services with their own billing,
|
|
74
|
+
* accounts, users, memberships, etc. This is useful for SaaS platforms that want to offer isolated environments
|
|
75
|
+
* for different customers, and to allow reselling of their services to other SaaS providers.
|
|
76
|
+
*
|
|
77
|
+
* For example, an email service lets customers sign up. However, some customers want to offer
|
|
78
|
+
* email services to their own clients. Therefore, the email provider has an account for each customer, and those
|
|
79
|
+
* customers have accounts for their own clients as well. Each level is isolated, with separate billing and users.
|
|
80
|
+
*/
|
|
81
|
+
type AccountResource = {
|
|
82
|
+
id: AccountId;
|
|
83
|
+
parentId: AccountId | null;
|
|
84
|
+
/** Display name chosen by the account owner */
|
|
85
|
+
name: string | null;
|
|
86
|
+
/** URL to the account's avatar image */
|
|
87
|
+
avatarUrl: string | null;
|
|
88
|
+
/** Current account status */
|
|
89
|
+
status: AccountStatus;
|
|
90
|
+
/** ISO 8601 timestamp until which the account is paid (null if never paid or closed) */
|
|
91
|
+
paidUntil: string | null;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Possible statuses for a user.
|
|
95
|
+
*
|
|
96
|
+
* - active: Normal operation
|
|
97
|
+
* - trial: In trial period
|
|
98
|
+
* - past_due: Payment failed but grace period active
|
|
99
|
+
* - suspended: Access restricted due to billing or policy
|
|
100
|
+
* - closed: Permanently closed
|
|
101
|
+
*/
|
|
102
|
+
type UserStatus = "active" | "disabled" | "suspended" | "deleted";
|
|
103
|
+
/**
|
|
104
|
+
* A reference to a user. Will not be deleted even due to GDPR requests or account closures,
|
|
105
|
+
* to maintain referential integrity in audit logs and historical records.
|
|
106
|
+
*/
|
|
20
107
|
type UserResource = {
|
|
21
108
|
id: UserId;
|
|
22
109
|
accountId: AccountId;
|
|
23
110
|
status: UserStatus;
|
|
24
111
|
preferredMembershipId: MembershipId | null;
|
|
25
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Personal identity information (PII) for a user. Will be deleted due to GDPR requests or account
|
|
115
|
+
* closures to respect legal requirements of various regions..
|
|
116
|
+
*/
|
|
26
117
|
type UserIdentity = {
|
|
27
118
|
id: UserId;
|
|
28
119
|
avatarUrl: string | null;
|
|
120
|
+
/** External identifier from third-party provider (i.e., SCIM) */
|
|
29
121
|
externalId: string | null;
|
|
30
122
|
givenName: string | null;
|
|
31
123
|
familyName: string | null;
|
|
32
124
|
displayName: string | null;
|
|
125
|
+
/** Preferred language code (en-CA, fr-FR, zh-CN, etc.) */
|
|
33
126
|
preferredLanguage: string | null;
|
|
127
|
+
/** Locale code (e.g., "en-US") */
|
|
34
128
|
locale: string | null;
|
|
35
129
|
timezone: string | null;
|
|
36
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Roles within an account membership.
|
|
133
|
+
*
|
|
134
|
+
* - owner: Full administrative access, may perform destructive actions.
|
|
135
|
+
* - member: Standard non-destructive access
|
|
136
|
+
* - viewer: Read-only access
|
|
137
|
+
*/
|
|
37
138
|
type MembershipRole = "owner" | "member" | "viewer";
|
|
38
139
|
type Membership = {
|
|
39
140
|
id: MembershipId;
|
|
@@ -41,34 +142,128 @@ type Membership = {
|
|
|
41
142
|
accountId: AccountId;
|
|
42
143
|
role: MembershipRole;
|
|
43
144
|
};
|
|
145
|
+
/**
|
|
146
|
+
* Email credential record attached to a user.
|
|
147
|
+
*
|
|
148
|
+
* Sensitive fields (email) are only included when explicitly requested
|
|
149
|
+
* or when the caller has appropriate permissions.
|
|
150
|
+
*/
|
|
44
151
|
type EmailCredential = {
|
|
45
152
|
id: string;
|
|
46
153
|
email: string | null;
|
|
47
|
-
hashedEmail: string | null;
|
|
48
|
-
hashedPassword: string | null;
|
|
49
154
|
emailVerifiedAt: string | null;
|
|
50
155
|
};
|
|
51
156
|
type SessionTokens = {
|
|
157
|
+
/** Signed JWT access token for authenticating API requests */
|
|
52
158
|
accessToken: string;
|
|
159
|
+
/** Opaque refresh token for obtaining new access tokens */
|
|
53
160
|
refreshToken: string;
|
|
54
161
|
tokenType: "Bearer";
|
|
162
|
+
/** Seconds until the access token expires from time of issuance */
|
|
55
163
|
expiresIn: number;
|
|
56
164
|
idToken?: string;
|
|
165
|
+
/** Absolute expiration time (milliseconds since epoch) set by the client library */
|
|
166
|
+
expiresAt: number;
|
|
57
167
|
};
|
|
168
|
+
/**
|
|
169
|
+
* Complete profile of the currently authenticated user.
|
|
170
|
+
*
|
|
171
|
+
* Combines basic user data with identity, credentials, memberships, and freshness timestamp.
|
|
172
|
+
*
|
|
173
|
+
* `lastUpdatedAt` is updated whenever the profile is fetched from the server.
|
|
174
|
+
*/
|
|
58
175
|
type SessionProfile = UserResource & {
|
|
59
|
-
identity: UserIdentity;
|
|
176
|
+
identity: UserIdentity | null;
|
|
60
177
|
emailCredentials: EmailCredential[];
|
|
61
|
-
memberships: Membership
|
|
178
|
+
memberships: (Membership & {
|
|
179
|
+
account: AccountResource;
|
|
180
|
+
})[];
|
|
181
|
+
/** Currently active membership in the accessToken (determined by preferredMembershipId or context) */
|
|
62
182
|
activeMembership: Membership | null;
|
|
183
|
+
lastUpdatedAt: number;
|
|
63
184
|
};
|
|
64
|
-
|
|
65
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Combined authentication state containing tokens and optional profile.
|
|
187
|
+
*/
|
|
188
|
+
type Authentication = {
|
|
189
|
+
tokens: SessionTokens;
|
|
66
190
|
profile: SessionProfile;
|
|
67
191
|
};
|
|
192
|
+
/**
|
|
193
|
+
* Result of checkEmail() indicating whether the email is registered.
|
|
194
|
+
*/
|
|
68
195
|
type EmailCheckStatus = "active" | "inactive";
|
|
196
|
+
/**
|
|
197
|
+
* Supported login methods for an email address.
|
|
198
|
+
*
|
|
199
|
+
* Currently limited to email/password and magic link flows.
|
|
200
|
+
*/
|
|
69
201
|
type LoginMethod = "email_password" | "magic_link";
|
|
202
|
+
/**
|
|
203
|
+
* Minimal storage interface required for session persistence.
|
|
204
|
+
*
|
|
205
|
+
* Compatible with localStorage, sessionStorage, AsyncStorage (React Native), or any custom implementation.
|
|
206
|
+
*/
|
|
207
|
+
type StorageLike = {
|
|
208
|
+
getItem(key: string): string | null;
|
|
209
|
+
setItem(key: string, value: string): void;
|
|
210
|
+
removeItem(key: string): void;
|
|
211
|
+
};
|
|
70
212
|
|
|
213
|
+
type StorageConfig = StorageLike | "localStorage" | null | undefined;
|
|
71
214
|
type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
215
|
+
type Config = {
|
|
216
|
+
baseUrl: string;
|
|
217
|
+
earlyRefreshMs: number;
|
|
218
|
+
fetchFn: FetchFn;
|
|
219
|
+
profileStorageKey: string;
|
|
220
|
+
storage: StorageConfig;
|
|
221
|
+
tokensStorageKey: string;
|
|
222
|
+
};
|
|
223
|
+
type AuthEventMap = {
|
|
224
|
+
refresh: SessionTokens;
|
|
225
|
+
profileChange: SessionProfile;
|
|
226
|
+
unauthenticated: AuthError;
|
|
227
|
+
sessionChange: AuthSession | null;
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* AuthError represents structured authentication failures from Accountmaker endpoints.
|
|
231
|
+
*
|
|
232
|
+
* AuthError wraps RFC 7807 Problem Details. invalidParams may be present for field-level validation.
|
|
233
|
+
* Network failures throw other error types.
|
|
234
|
+
*
|
|
235
|
+
* Also note that the `type` field often contains a URI that points to documentation about the
|
|
236
|
+
* specific error type, including how to resolve it, code samples, and links to the RFCs or other
|
|
237
|
+
* standards that define the error.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* try {
|
|
242
|
+
* const session = await am.signIn({ email: 'test@example.com', password: 'password123' });
|
|
243
|
+
* } catch (e) {
|
|
244
|
+
* if (e instanceof AuthError) {
|
|
245
|
+
* console.error("Authentication failed:", e.title);
|
|
246
|
+
* if (e.invalidParams) {
|
|
247
|
+
* for (const param of e.invalidParams) {
|
|
248
|
+
* console.error(` - Invalid parameter: ${param.path} (${param.type})`);
|
|
249
|
+
* }
|
|
250
|
+
* }
|
|
251
|
+
* } else {
|
|
252
|
+
* console.error("Unexpected error:", e);
|
|
253
|
+
* }
|
|
254
|
+
* }
|
|
255
|
+
* ```
|
|
256
|
+
*
|
|
257
|
+
* Note that HTTP error codes are distinctly:
|
|
258
|
+
* - 400: Client error (bad request, invalid input, etc.)
|
|
259
|
+
* - 401: Unauthenticated (we don't know who you are)
|
|
260
|
+
* - 402: Payment required (e.g. billing issue)
|
|
261
|
+
* - 403: Unauthorized (we know who you are, but you don't have permission)
|
|
262
|
+
* - 404: Not found
|
|
263
|
+
* - 409: Conflict (email already registered, user already invited, etc.)
|
|
264
|
+
* - 429: Too many requests (rate limiting)
|
|
265
|
+
* - 500: Internal server error (server's fault)
|
|
266
|
+
*/
|
|
72
267
|
declare class AuthError extends Error {
|
|
73
268
|
readonly problem: ProblemDetails;
|
|
74
269
|
constructor(problem: ProblemDetails);
|
|
@@ -79,57 +274,140 @@ declare class AuthError extends Error {
|
|
|
79
274
|
get detail(): string | undefined;
|
|
80
275
|
get invalidParams(): ProblemDetails["invalidParams"] | undefined;
|
|
81
276
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
277
|
+
/**
|
|
278
|
+
* AuthSession represents an authenticated user with automatic token refresh and persisted state.
|
|
279
|
+
*
|
|
280
|
+
* AuthSession owns tokens, profile data, refresh logic, and authenticated requests.
|
|
281
|
+
*/
|
|
86
282
|
declare class AuthSession {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
get
|
|
95
|
-
get
|
|
96
|
-
|
|
97
|
-
|
|
283
|
+
constructor(initial: Authentication, config: Partial<Config>);
|
|
284
|
+
/**
|
|
285
|
+
* Removes all persisted data (tokens, profile) from storage, and prevents future
|
|
286
|
+
* refreshes of token and profile data. Does NOT clear current token or profile data from the
|
|
287
|
+
* session memory, but effectively deactivates the session for future use.
|
|
288
|
+
*/
|
|
289
|
+
clear(): void;
|
|
290
|
+
get tokens(): SessionTokens;
|
|
291
|
+
get profile(): SessionProfile;
|
|
292
|
+
toJSON(): Authentication;
|
|
293
|
+
/**
|
|
294
|
+
* Creates an AuthSession from existing authentication data. Useful for restoring
|
|
295
|
+
* a session from custom storage or creating a session from custom server-provided data.
|
|
296
|
+
*/
|
|
297
|
+
static fromJSON(initial: Authentication, config: Partial<Config>): AuthSession;
|
|
298
|
+
/**
|
|
299
|
+
* Returns true if the access token is expired or will expire soon. The
|
|
300
|
+
* "soon" threshold is configured via Config.earlyRefreshMs (default 1 minute).
|
|
301
|
+
*/
|
|
98
302
|
isExpired(): boolean;
|
|
99
303
|
/**
|
|
100
|
-
*
|
|
304
|
+
* Performs standard fetch() with a Bearer token and automatic refresh.
|
|
305
|
+
*
|
|
306
|
+
* Returns Response, does not parse the body, does not throw for HTTP status codes.
|
|
307
|
+
* Throws AuthError when refresh fails, trows runtime errors on network failure.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* const res = await session.fetch("/api/projects");
|
|
312
|
+
* const projects = await res.json();
|
|
313
|
+
* ```
|
|
314
|
+
*
|
|
315
|
+
* Any service can validate tokens using:
|
|
316
|
+
* https://api.accountmaker.com/.well-known/jwks.json?client_id={clientId}
|
|
317
|
+
*/
|
|
318
|
+
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
319
|
+
/**
|
|
320
|
+
* Replaces the access token using the refresh token.
|
|
101
321
|
*
|
|
102
|
-
*
|
|
103
|
-
* Authorization header will be set with the current access token.
|
|
322
|
+
* It is called automatically by all other methods when the access token is expired or near expiry.
|
|
104
323
|
*/
|
|
105
|
-
fetch(url: string | URL | Request, init?: RequestInit): Promise<Response>;
|
|
106
324
|
refresh(): Promise<void>;
|
|
325
|
+
/**
|
|
326
|
+
* refetchProfile() replaces the cached profile with server state.
|
|
327
|
+
*
|
|
328
|
+
* Concurrent calls are deduplicated.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```ts
|
|
332
|
+
* await session.refetchProfile();
|
|
333
|
+
* console.log("Updated profile:", session.profile);
|
|
334
|
+
* ```
|
|
335
|
+
*
|
|
336
|
+
* Throws AuthError on network errors, etc.
|
|
337
|
+
* @throws AuthError
|
|
338
|
+
*/
|
|
339
|
+
refetchProfile(): Promise<void>;
|
|
340
|
+
/**
|
|
341
|
+
* Requests a verification email for the current user.
|
|
342
|
+
*
|
|
343
|
+
* Throws AuthError on network errors, etc.
|
|
344
|
+
* @throws AuthError
|
|
345
|
+
*/
|
|
107
346
|
sendVerificationEmail(): Promise<void>;
|
|
108
|
-
me(): Promise<SessionProfile>;
|
|
109
|
-
user(id: UserId): Promise<UserResource>;
|
|
110
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Am runs authentication flows and produces AuthSession.
|
|
350
|
+
*
|
|
351
|
+
* Use Am before a session exists (sign-in, sign-up, magic link, invites, password reset, CSRF).
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```ts
|
|
355
|
+
* const am = new Am();
|
|
356
|
+
* const session = await am.signIn({ email: 'user@example.com', password: 'secret' });
|
|
357
|
+
* // Now use `session` for protected API calls
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
111
360
|
declare class Am {
|
|
112
|
-
private options;
|
|
113
361
|
constructor(config?: Partial<Config>);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
362
|
+
/**
|
|
363
|
+
* session returns the current AuthSession or null.
|
|
364
|
+
*
|
|
365
|
+
* Use restoreSession() to load from storage.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```ts
|
|
369
|
+
* const session = am.session;
|
|
370
|
+
* if (!session) throw new Error("Not authenticated");
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
get session(): AuthSession | null;
|
|
374
|
+
/**
|
|
375
|
+
* Constructs AuthSession from existing tokens and profile.
|
|
376
|
+
*
|
|
377
|
+
* Use this after a server-side auth handshake or custom persistence.
|
|
378
|
+
*/
|
|
379
|
+
createSession(initial: Authentication): AuthSession;
|
|
380
|
+
/**
|
|
381
|
+
* restoreSession loads AuthSession from storage or returns null.
|
|
382
|
+
*
|
|
383
|
+
* Invalid or partial stored data is cleared.
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```ts
|
|
387
|
+
* const am = new Am({ storage: 'localStorage' });
|
|
388
|
+
* const session = am.restoreSession();
|
|
389
|
+
* if (session) session.fetch("/api/me");
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
restoreSession(): AuthSession | null;
|
|
393
|
+
/**
|
|
394
|
+
* Subscribes to auth events and returns an unsubscribe function.
|
|
395
|
+
*/
|
|
396
|
+
on<K extends keyof AuthEventMap>(event: K, fn: (v: AuthEventMap[K]) => void): () => boolean;
|
|
397
|
+
/**
|
|
398
|
+
* acceptInvite exchanges an invite token for a fresh AuthSession.
|
|
399
|
+
*
|
|
400
|
+
* Throws AuthError on invalid, expired, or already-used tokens.
|
|
401
|
+
*/
|
|
120
402
|
acceptInvite(query: {
|
|
121
403
|
clientId: ClientId;
|
|
122
404
|
token: string;
|
|
123
|
-
}): Promise<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
status: EmailCheckStatus;
|
|
130
|
-
preferred: LoginMethod[];
|
|
131
|
-
available: LoginMethod[];
|
|
132
|
-
}>;
|
|
405
|
+
}): Promise<AuthSession>;
|
|
406
|
+
/**
|
|
407
|
+
* checkEmail returns how an email should authenticate for this client.
|
|
408
|
+
*
|
|
409
|
+
* Use this to choose password vs magic link vs SSO before rendering a login form.
|
|
410
|
+
*/
|
|
133
411
|
checkEmail(body: {
|
|
134
412
|
clientId: ClientId;
|
|
135
413
|
email: string;
|
|
@@ -139,67 +417,74 @@ declare class Am {
|
|
|
139
417
|
preferred: LoginMethod[];
|
|
140
418
|
available: LoginMethod[];
|
|
141
419
|
}>;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
420
|
+
/**
|
|
421
|
+
* Sets the httpOnly CSRF cookie.
|
|
422
|
+
*
|
|
423
|
+
* Call csrfToken() next to fetch a signed token for form posts.
|
|
424
|
+
*/
|
|
145
425
|
csrfSession(): Promise<{
|
|
146
426
|
csrfToken: string;
|
|
147
427
|
}>;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
428
|
+
/**
|
|
429
|
+
* Returns a signed CSRF token for form posts.
|
|
430
|
+
*
|
|
431
|
+
* Call csrfSession() first to set the CSRF cookie.
|
|
432
|
+
*/
|
|
151
433
|
csrfToken(): Promise<{
|
|
152
434
|
csrfToken: string;
|
|
153
435
|
}>;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
password: string;
|
|
162
|
-
csrfToken?: string;
|
|
163
|
-
}): Promise<AuthenticationResult>;
|
|
164
|
-
static tokenLogin(token: string, config?: Partial<Config>): Promise<AuthenticationResult>;
|
|
165
|
-
tokenLogin(token: string): Promise<AuthenticationResult>;
|
|
166
|
-
static refresh(refreshToken: string, config?: Partial<Config>): Promise<SessionTokens>;
|
|
167
|
-
refresh(refreshToken: string): Promise<SessionTokens>;
|
|
168
|
-
static register(body: {
|
|
436
|
+
/**
|
|
437
|
+
* Authenticates with email and password and returns a new AuthSession.
|
|
438
|
+
*
|
|
439
|
+
* Tokens and profile are persisted when storage is configured.
|
|
440
|
+
*/
|
|
441
|
+
signIn(body: {
|
|
442
|
+
clientId: ClientId;
|
|
169
443
|
email: string;
|
|
170
444
|
password: string;
|
|
171
445
|
csrfToken?: string;
|
|
172
|
-
}
|
|
173
|
-
|
|
446
|
+
}): Promise<AuthSession>;
|
|
447
|
+
/**
|
|
448
|
+
* Authenticates with a one-time token and returns a new AuthSession.
|
|
449
|
+
*
|
|
450
|
+
* Use this for magic links and similar one-time login flows.
|
|
451
|
+
*/
|
|
452
|
+
signInWithToken(token: string): Promise<AuthSession>;
|
|
453
|
+
/**
|
|
454
|
+
* Creates a new user and returns a new AuthSession.
|
|
455
|
+
*
|
|
456
|
+
* Tokens and profile are persisted when storage is configured.
|
|
457
|
+
*/
|
|
458
|
+
signUp(body: {
|
|
459
|
+
clientId: ClientId;
|
|
174
460
|
email: string;
|
|
175
461
|
password: string;
|
|
176
462
|
csrfToken?: string;
|
|
177
|
-
}): Promise<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}, config?: Partial<Config>): Promise<void>;
|
|
463
|
+
}): Promise<AuthSession>;
|
|
464
|
+
/**
|
|
465
|
+
* Sets a new password using a one-time reset token.
|
|
466
|
+
*/
|
|
182
467
|
resetPassword(body: {
|
|
183
468
|
token: string;
|
|
184
469
|
newPassword: string;
|
|
185
470
|
}): Promise<void>;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}, config?: Partial<Config>): Promise<void>;
|
|
471
|
+
/**
|
|
472
|
+
* Sends a one-time sign-in link to an email address.
|
|
473
|
+
*/
|
|
190
474
|
sendMagicLink(body: {
|
|
475
|
+
clientId: ClientId;
|
|
191
476
|
email: string;
|
|
192
477
|
csrfToken?: string;
|
|
193
478
|
}): Promise<void>;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}, config?: Partial<Config>): Promise<void>;
|
|
479
|
+
/**
|
|
480
|
+
* Sends a password reset link to an email address.
|
|
481
|
+
*/
|
|
198
482
|
sendPasswordReset(body: {
|
|
483
|
+
clientId: ClientId;
|
|
199
484
|
email: string;
|
|
200
485
|
csrfToken?: string;
|
|
201
486
|
}): Promise<void>;
|
|
202
487
|
}
|
|
203
488
|
|
|
204
489
|
export { Am, AuthError, AuthSession };
|
|
205
|
-
export type {
|
|
490
|
+
export type { AccountId, AccountResource, AccountStatus, Authentication, ClientId, EmailCheckStatus, EmailCredential, LoginMethod, Membership, MembershipId, MembershipRole, ProblemDetails, SessionProfile, SessionTokens, StorageLike, UserId, UserIdentity, UserResource, UserStatus };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function t(t){return t.replace(/_([a-z])/g,(t,e)=>e.toUpperCase())}function
|
|
1
|
+
const t=Symbol("session_state"),e=Symbol("auth_session"),n=Symbol("auth_state"),r=Symbol("emitter");function s(t){return t?"localStorage"===t?function(){try{return"undefined"==typeof window?null:window.localStorage?window.localStorage:null}catch{return null}}():t:null}function o(t,e){return t?function(t){if(!t)return null;try{return JSON.parse(t)}catch{return null}}(t.getItem(e)):null}function i(t,e,n){if(t)try{t.setItem(e,JSON.stringify(n))}catch{}}function a(t,e){if(t)try{t.removeItem(e)}catch{}}function c(t,e,n){if(!t)return;const r=o(t,e),s=l(r)?r:null;null===r||s||a(t,e),s&&s.expiresAt>=n.expiresAt||i(t,e,n)}function u(t,e,n){if(!t)return;const r=o(t,e),s=f(r)?r:null;null===r||s||a(t,e),s&&s.lastUpdatedAt>=n.lastUpdatedAt||i(t,e,n)}function l(t){return!!t&&"string"==typeof t.accessToken&&"string"==typeof t.refreshToken&&"number"==typeof t.expiresAt&&"number"==typeof t.expiresIn&&"Bearer"===t.tokenType}function f(t){return!!t&&"string"==typeof t.id&&"string"==typeof t.accountId&&"string"==typeof t.status&&"number"==typeof t.lastUpdatedAt&&("object"==typeof t.identity||null===t.identity)}function h(e){return e[t]}function p(t){return t[n]}function y(t,n){t[e]=n;const s=h(n);!function(t,e){t[r]=(t,n)=>{const r=p(e).listeners[t];if(r)for(const e of r)try{e(n)}catch{console.warn("Unhandled error in AuthEvent listener for event",t)}}}(s,t),g(s,"sessionChange",n)}function g(t,e,n){(0,t[r])(e,n)}function d(t){return t.replace(/_([a-z])/g,(t,e)=>e.toUpperCase())}function m(t){if(null===t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(t=>m(t));const e=t,n={};for(const t of Object.keys(e))Object.prototype.hasOwnProperty.call(e,t)&&(n[d(t)]=m(e[t]));return n}function w(t){return t.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}function b(t){if(null===t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(t=>b(t));const e=t,n={};for(const t of Object.keys(e))Object.prototype.hasOwnProperty.call(e,t)&&(n[w(t)]=b(e[t]));return n}class k extends Error{constructor(t){super(t.title),this.name="AuthError",this.problem=Object.freeze(t)}get type(){return this.problem.type}get title(){return this.problem.title}get status(){return this.problem.status}get code(){return this.problem.code}get detail(){return this.problem.detail}get invalidParams(){return this.problem.invalidParams}}const S={fetchFn:function(){const t=globalThis.fetch;return"function"==typeof t?t.bind(globalThis):async()=>{throw new Error("Missing fetch implementation. Provide config.fetchFn or use a runtime with global fetch.")}}(),baseUrl:"https://api.accountmaker.com",earlyRefreshMs:6e4,storage:null,tokensStorageKey:"am_tokens",profileStorageKey:"am_profile"};const P=async(t,e,n={})=>t.config.fetchFn(e,function(t,e){const n=new Headers(t.headers);return n.set("Authorization",`Bearer ${e}`),{...t,headers:n}}(n,t.tokens.accessToken)),A=async(t,e,n={})=>{U(t)&&await x(t);let r=await P(t,e,n);if(401!==r.status)return r;if(t.cleared)return r;try{return await x(t),r=await P(t,e,n),r}catch(e){throw!t.cleared&&K(e)&&g(t,"unauthenticated",e),e}},j=async t=>{if(204===t.status)return;const e=m(await async function(t){const e=t.headers.get("Content-Type")||"";if(!e.includes("application/json")&&!e.includes("+json"))return null;try{return await t.json()}catch{return null}}(t));if(!t.ok)throw new k(function(t,e){return function(t){return(t.headers.get("Content-Type")||"").includes("application/problem+json")}(t)&&e&&"object"==typeof e&&"string"==typeof e.type&&"string"==typeof e.title&&"number"==typeof e.status?e:function(t,e){return{type:"about:blank",title:t.statusText||"Request failed",status:t.status,detail:"string"==typeof e?e:void 0}}(t,e)}(t,e));return e},T=async(t,e,n={})=>{const r=await A(t,e,n);return j(r)},O=async({fetchFn:t,baseUrl:e},n,r={})=>{const s=new URLSearchParams(b(r)).toString(),o=s?`${e}${n}?${s}`:`${e}${n}`,i=await t(o,{method:"GET",headers:{Accept:"application/json"}});return j(i)},$=async({fetchFn:t,baseUrl:e},n,r)=>{const s=await t(`${e}${n}`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(b(r))});return j(s)},U=t=>{const e=Math.min(Math.max(t.config.earlyRefreshMs,0),3e5);return Date.now()>=t.tokens.expiresAt-e},x=async t=>{if(!t.cleared){t.refreshPromise||(t.refreshPromise=async function(t){const{fetchFn:e,baseUrl:n}=t.config,r=await e(`${n}/auth/refresh`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(b({refreshToken:t.tokens.refreshToken}))}),o=v(await j(r));t.tokens=o;const i=s(t.config.storage);c(i,t.config.tokensStorageKey,o),g(t,"refresh",o)}(t));try{await t.refreshPromise}finally{t.refreshPromise=null}}},K=t=>t instanceof k&&401===t.status,v=t=>{const e="number"==typeof t.expiresIn?t.expiresIn:0;return{...t,expiresAt:Date.now()+1e3*e}},I=t=>({...t,lastUpdatedAt:Date.now()});async function C(t){const e=I(await(async(t,e,n={})=>{const r=new URLSearchParams(b(n)).toString(),s=t.config.baseUrl,o=r?`${s}${e}?${r}`:`${s}${e}`;return await T(t,o,{method:"GET",headers:{Accept:"application/json"}})})(t,"/auth/me",{}));t.profile=e;u(s(t.config.storage),t.config.profileStorageKey,e),g(t,"profileChange",e)}const E=t=>({tokens:v(t.tokens),profile:I(t.profile)});class J{constructor(e,n){const r={...S,...n},o={...e,config:r,refreshPromise:null,profilePromise:null,cleared:!1};!function(e,n){e[t]=n}(this,o);const i=s(r.storage);c(i,r.tokensStorageKey,o.tokens),o.profile&&u(i,r.profileStorageKey,o.profile)}clear(){const t=h(this);!function(t){const e=s(t.storage);a(e,t.profileStorageKey),a(e,t.tokensStorageKey)}(t.config),t.cleared=!0}get tokens(){return h(this).tokens}get profile(){return h(this).profile}toJSON(){const t=h(this);return{tokens:t.tokens,profile:t.profile}}static fromJSON(t,e){return new J(t,e)}isExpired(){return U(h(this))}async fetch(t,e={}){return A(h(this),t,e)}async refresh(){return x(h(this))}async refetchProfile(){const t=h(this);if(!t.cleared){t.profilePromise||(t.profilePromise=C(t));try{await t.profilePromise}finally{t.profilePromise=null}}}async sendVerificationEmail(){await(async(t,e,n)=>{const r=t.config.baseUrl;return await T(t,`${r}${e}`,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(b(n))})})(h(this),"/auth/send-verification-email",{})}}class N{constructor(t){var e,r;e=this,r={config:{...S,...t},listeners:{}},e[n]=r}get session(){return this[e]||null}createSession(t){const e=new J(t,p(this).config);return y(this,e),e}restoreSession(){const t=p(this).config,e=s(t.storage);if(!e)return null;const n=o(e,t.tokensStorageKey),r=l(n)?n:null,i=o(e,t.profileStorageKey),c=f(i)?i:null;if(!r||!c)return a(e,t.tokensStorageKey),a(e,t.profileStorageKey),null;const u=new J({tokens:r,profile:c},t);return y(this,u),u}on(t,e){const n=p(this).listeners,r=n[t]??(n[t]=new Set);return r.add(e),()=>r.delete(e)}async acceptInvite(t){const e=p(this).config,n=E(await O(e,"/auth/accept-invite",t)),r=new J(n,e);return y(this,r),r}async checkEmail(t){return $(p(this).config,"/auth/check-email",t)}async csrfSession(){return O(p(this).config,"/auth/csrf-session")}async csrfToken(){return O(p(this).config,"/auth/csrf-token")}async signIn(t){const e=p(this).config,n=E(await $(e,"/auth/sign-in",t)),r=new J(n,e);return y(this,r),r}async signInWithToken(t){const e=p(this).config,n=E(await O(e,"/auth/sign-in-with-token",{token:t})),r=new J(n,e);return y(this,r),r}async signUp(t){const e=p(this).config,n=E(await $(e,"/auth/sign-up",t)),r=new J(n,e);return y(this,r),r}async resetPassword(t){return $(p(this).config,"/auth/reset-password",t)}async sendMagicLink(t){return $(p(this).config,"/auth/send-magic-link",t)}async sendPasswordReset(t){return $(p(this).config,"/auth/send-password-reset",t)}}export{N as Am,k as AuthError,J as AuthSession};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/auth.ts"],"sourcesContent":[null],"names":["camelCaseStr","str","replace","_","letter","toUpperCase","camelCaseObj","input","Array","isArray","map","item","obj","result","key","Object","keys","prototype","hasOwnProperty","call","snakeCaseStr","toLowerCase","snakeCaseObj","AuthError","Error","constructor","problem","super","title","this","name","freeze","type","status","code","detail","invalidParams","defaultConfig","fetchFn","f","globalThis","fetch","async","defaultFetchFn","baseUrl","handleResponse","res","raw","contentType","headers","get","includes","json","readJsonSafe","ok","isProblemJson","statusText","toGenericProblem","undefined","unauthGet","path","query","qs","URLSearchParams","toString","url","method","Accept","unauthPost","body","JSON","stringify","authGet","accessToken","Authorization","AuthSession","tokens","config","lastUpdated","Date","refreshToken","idToken","tokenType","expiresIn","lastUpdatedAt","expiresAt","getTime","isExpired","now","init","refresh","sendVerificationEmail","authPost","me","user","id","Am","options","createAuthSession","acceptInvite","checkEmail","csrfSession","csrfToken","login","tokenLogin","token","register","resetPassword","sendMagicLink","sendPasswordReset"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/auth.ts"],"sourcesContent":[null],"names":["SESSION_STATE","Symbol","AUTH_SESSION","AUTH_STATE","EMITTER","resolveStorage","storageConfig","window","localStorage","getBrowserLocalStorage","readJson","storage","key","raw","JSON","parse","safeParse","getItem","writeJson","value","setItem","stringify","removeKey","removeItem","writeTokensIfNewer","next","curRaw","cur","isSessionTokens","expiresAt","writeProfileIfNewer","isSessionProfile","lastUpdatedAt","x","accessToken","refreshToken","expiresIn","tokenType","id","accountId","status","identity","getSessionState","session","getAuthState","am","setAuthSession","sessionState","event","set","listeners","fn","console","warn","setSessionStateEmitter","emitSessionStateEvent","emit","camelCaseStr","str","replace","_","letter","toUpperCase","camelCaseObj","input","Array","isArray","map","item","obj","result","Object","keys","prototype","hasOwnProperty","call","snakeCaseStr","toLowerCase","snakeCaseObj","AuthError","Error","constructor","problem","super","title","this","name","freeze","type","code","detail","invalidParams","defaultConfig","fetchFn","f","globalThis","fetch","bind","async","defaultFetchFn","baseUrl","earlyRefreshMs","tokensStorageKey","profileStorageKey","fetchSessionResponse","state","init","config","token","headers","Headers","withBearer","tokens","fetchSessionResponseEnsureFresh","isExpired","refresh","res","cleared","e","isUnauthenticatedAuthError","handleJsonOrThrow","json","contentType","get","includes","readJsonSafe","ok","isProblemJson","statusText","undefined","toGenericProblem","getProblemJson","getSessionJsonEnsureFresh","unauthGet","path","query","qs","URLSearchParams","toString","url","method","Accept","unauthPost","body","early","Math","min","max","Date","now","refreshPromise","toSessionTokens","doRefresh","toSessionProfile","profile","doRefetchProfile","authGet","handleAuthenticationResponse","AuthSession","initial","merged","profilePromise","setSessionState","clear","clearAuth","toJSON","fromJSON","refetchProfile","sendVerificationEmail","authPost","Am","createSession","restoreSession","tokensRaw","profileRaw","on","Set","add","delete","acceptInvite","checkEmail","csrfSession","csrfToken","signIn","signInWithToken","signUp","resetPassword","sendMagicLink","sendPasswordReset"],"mappings":"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"}
|