@aooth/user 0.2.0 → 0.2.2

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.
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_federated_identity_store = require("./federated-identity-store-D-LvRXdx.cjs");
2
+ const require_federated_identity_store = require("./federated-identity-store-Cbstwl4-.cjs");
3
3
  let node_crypto = require("node:crypto");
4
- //#region src/atscript-db/federated-identity-store.ts
4
+ // src/atscript-db/federated-identity-store.ts
5
5
  function isConflict$1(err) {
6
6
  return typeof err === "object" && err !== null && err.code === "CONFLICT";
7
7
  }
@@ -71,8 +71,7 @@ var FederatedIdentityStoreAtscriptDb = class extends require_federated_identity_
71
71
  return (await this.table.deleteMany({ userId })).deletedCount;
72
72
  }
73
73
  };
74
- //#endregion
75
- //#region src/atscript-db/index.ts
74
+ // src/atscript-db/index.ts
76
75
  function isConflict(err) {
77
76
  return typeof err === "object" && err !== null && err.code === "CONFLICT";
78
77
  }
@@ -161,6 +160,5 @@ var UsersStoreAtscriptDb = class extends require_federated_identity_store.UserSt
161
160
  throw new require_federated_identity_store.UserAuthError("CAS_EXHAUSTED");
162
161
  }
163
162
  };
164
- //#endregion
165
163
  exports.FederatedIdentityStoreAtscriptDb = FederatedIdentityStoreAtscriptDb;
166
164
  exports.UsersStoreAtscriptDb = UsersStoreAtscriptDb;
@@ -1,5 +1,4 @@
1
- import { D as UserCredentials, i as NewFederatedIdentity, k as UserStoreUpdate, n as FederatedIdentityStore, o as UserStore, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity } from "./federated-identity-store-B_jEkl-a.cjs";
2
- //#region src/atscript-db/federated-identity-store.d.ts
1
+ import { D as UserCredentials, i as NewFederatedIdentity, k as UserStoreUpdate, n as FederatedIdentityStore, o as UserStore, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity } from "./federated-identity-store-D10-BT9l.cjs";
3
2
  /**
4
3
  * Structural surface of `AtscriptDbTable` covering exactly the methods this
5
4
  * adapter calls — kept loose so `@aooth/user` doesn't pull `@atscript/db` types
@@ -39,7 +38,7 @@ interface FederatedIdentityStoreAtscriptDbOptions {
39
38
  * is a plain indexed column, so `listForUser` / `deleteAllForUser` scan it
40
39
  * natively.
41
40
  */
42
- declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
41
+ export declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
43
42
  private readonly table;
44
43
  private readonly clock;
45
44
  constructor(opts: FederatedIdentityStoreAtscriptDbOptions);
@@ -50,15 +49,13 @@ declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
50
49
  touchLogin(provider: string, subject: string, profile?: FederatedProfileSnapshot): Promise<void>;
51
50
  deleteAllForUser(userId: string): Promise<number>;
52
51
  }
53
- //#endregion
54
- //#region src/atscript-db/index.d.ts
55
52
  /**
56
53
  * Persisted row shape — `UserCredentials` plus the consumer's custom user
57
54
  * fields. The `.as` model shipped at `@aooth/user/atscript-db/model.as`
58
55
  * (`AoothUserCredentials`) matches by construction; consumers extend it with
59
56
  * their own `.as` interface to add custom columns.
60
57
  */
61
- type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials & TUserCustom;
58
+ export type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials & TUserCustom;
62
59
  /**
63
60
  * Structural surface of `AtscriptDbTable` covering exactly the methods this
64
61
  * adapter calls. Kept loose to avoid pulling `@atscript/db` types into the
@@ -67,7 +64,7 @@ type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials &
67
64
  *
68
65
  * Mirrors `AuthCredentialTable` from `@aooth/auth/atscript-db`.
69
66
  */
70
- interface AuthUserTable<TUserCustom extends object = object> {
67
+ export interface AuthUserTable<TUserCustom extends object = object> {
71
68
  count(query: {
72
69
  filter: Record<string, unknown>;
73
70
  }): Promise<number>;
@@ -105,7 +102,7 @@ interface UsersStoreAtscriptDbOptions<TUserCustom extends object> {
105
102
  * `@meta.id` PK (`id`) and the unique `username` index, plus any
106
103
  * annotation-resolved `handleFields`; writes key on `id`.
107
104
  */
108
- declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends UserStore<TUserCustom> {
105
+ export declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends UserStore<TUserCustom> {
109
106
  protected table: AuthUserTable<TUserCustom>;
110
107
  /** Secondary handle fields tried (in order) by `findByHandle` after `username`. */
111
108
  protected readonly handleFields: string[];
@@ -129,5 +126,4 @@ declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends
129
126
  */
130
127
  withCas(id: string, mutator: (current: UserCredentials & TUserCustom) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
131
128
  }
132
- //#endregion
133
- export { AuthUserTable, FederatedIdentityStoreAtscriptDb, type FederatedIdentityTable, UserCredentialsRow, UsersStoreAtscriptDb };
129
+ export type { FederatedIdentityTable };
@@ -1,5 +1,4 @@
1
- import { D as UserCredentials, i as NewFederatedIdentity, k as UserStoreUpdate, n as FederatedIdentityStore, o as UserStore, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity } from "./federated-identity-store-B_jEkl-a.mjs";
2
- //#region src/atscript-db/federated-identity-store.d.ts
1
+ import { D as UserCredentials, i as NewFederatedIdentity, k as UserStoreUpdate, n as FederatedIdentityStore, o as UserStore, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity } from "./federated-identity-store-D10-BT9l.mjs";
3
2
  /**
4
3
  * Structural surface of `AtscriptDbTable` covering exactly the methods this
5
4
  * adapter calls — kept loose so `@aooth/user` doesn't pull `@atscript/db` types
@@ -39,7 +38,7 @@ interface FederatedIdentityStoreAtscriptDbOptions {
39
38
  * is a plain indexed column, so `listForUser` / `deleteAllForUser` scan it
40
39
  * natively.
41
40
  */
42
- declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
41
+ export declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
43
42
  private readonly table;
44
43
  private readonly clock;
45
44
  constructor(opts: FederatedIdentityStoreAtscriptDbOptions);
@@ -50,15 +49,13 @@ declare class FederatedIdentityStoreAtscriptDb extends FederatedIdentityStore {
50
49
  touchLogin(provider: string, subject: string, profile?: FederatedProfileSnapshot): Promise<void>;
51
50
  deleteAllForUser(userId: string): Promise<number>;
52
51
  }
53
- //#endregion
54
- //#region src/atscript-db/index.d.ts
55
52
  /**
56
53
  * Persisted row shape — `UserCredentials` plus the consumer's custom user
57
54
  * fields. The `.as` model shipped at `@aooth/user/atscript-db/model.as`
58
55
  * (`AoothUserCredentials`) matches by construction; consumers extend it with
59
56
  * their own `.as` interface to add custom columns.
60
57
  */
61
- type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials & TUserCustom;
58
+ export type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials & TUserCustom;
62
59
  /**
63
60
  * Structural surface of `AtscriptDbTable` covering exactly the methods this
64
61
  * adapter calls. Kept loose to avoid pulling `@atscript/db` types into the
@@ -67,7 +64,7 @@ type UserCredentialsRow<TUserCustom extends object = object> = UserCredentials &
67
64
  *
68
65
  * Mirrors `AuthCredentialTable` from `@aooth/auth/atscript-db`.
69
66
  */
70
- interface AuthUserTable<TUserCustom extends object = object> {
67
+ export interface AuthUserTable<TUserCustom extends object = object> {
71
68
  count(query: {
72
69
  filter: Record<string, unknown>;
73
70
  }): Promise<number>;
@@ -105,7 +102,7 @@ interface UsersStoreAtscriptDbOptions<TUserCustom extends object> {
105
102
  * `@meta.id` PK (`id`) and the unique `username` index, plus any
106
103
  * annotation-resolved `handleFields`; writes key on `id`.
107
104
  */
108
- declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends UserStore<TUserCustom> {
105
+ export declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends UserStore<TUserCustom> {
109
106
  protected table: AuthUserTable<TUserCustom>;
110
107
  /** Secondary handle fields tried (in order) by `findByHandle` after `username`. */
111
108
  protected readonly handleFields: string[];
@@ -129,5 +126,4 @@ declare class UsersStoreAtscriptDb<TUserCustom extends object = object> extends
129
126
  */
130
127
  withCas(id: string, mutator: (current: UserCredentials & TUserCustom) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
131
128
  }
132
- //#endregion
133
- export { AuthUserTable, FederatedIdentityStoreAtscriptDb, type FederatedIdentityTable, UserCredentialsRow, UsersStoreAtscriptDb };
129
+ export type { FederatedIdentityTable };
@@ -1,6 +1,6 @@
1
- import { c as setAtPath, l as UserStore, n as pickDefinedProfile, t as FederatedIdentityStore, u as UserAuthError } from "./federated-identity-store-CRycYlMj.mjs";
1
+ import { c as setAtPath, l as UserStore, n as pickDefinedProfile, t as FederatedIdentityStore, u as UserAuthError } from "./federated-identity-store-BZRvw9Pz.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
- //#region src/atscript-db/federated-identity-store.ts
3
+ // src/atscript-db/federated-identity-store.ts
4
4
  function isConflict$1(err) {
5
5
  return typeof err === "object" && err !== null && err.code === "CONFLICT";
6
6
  }
@@ -70,8 +70,7 @@ var FederatedIdentityStoreAtscriptDb = class extends FederatedIdentityStore {
70
70
  return (await this.table.deleteMany({ userId })).deletedCount;
71
71
  }
72
72
  };
73
- //#endregion
74
- //#region src/atscript-db/index.ts
73
+ // src/atscript-db/index.ts
75
74
  function isConflict(err) {
76
75
  return typeof err === "object" && err !== null && err.code === "CONFLICT";
77
76
  }
@@ -160,5 +159,4 @@ var UsersStoreAtscriptDb = class extends UserStore {
160
159
  throw new UserAuthError("CAS_EXHAUSTED");
161
160
  }
162
161
  };
163
- //#endregion
164
162
  export { FederatedIdentityStoreAtscriptDb, UsersStoreAtscriptDb };
@@ -1,5 +1,5 @@
1
1
  import "node:crypto";
2
- //#region src/errors.ts
2
+ // src/errors.ts
3
3
  const defaultMessages = {
4
4
  NOT_FOUND: "User not found",
5
5
  ALREADY_EXISTS: "User already exists",
@@ -24,8 +24,7 @@ var UserAuthError = class extends Error {
24
24
  this.details = details;
25
25
  }
26
26
  };
27
- //#endregion
28
- //#region src/store/user-store.ts
27
+ // src/store/user-store.ts
29
28
  /**
30
29
  * Storage seam for user credentials, keyed by the stable surrogate **`id`**
31
30
  * (the token subject). Reads come in three flavours:
@@ -40,8 +39,7 @@ var UserAuthError = class extends Error {
40
39
  * Writes (`update`/`delete`/`withCas`) all key on the surrogate `id`.
41
40
  */
42
41
  var UserStore = class {};
43
- //#endregion
44
- //#region src/utils.ts
42
+ // src/utils.ts
45
43
  function maskEmail(email) {
46
44
  if (!email) return "";
47
45
  const at = email.indexOf("@");
@@ -101,8 +99,7 @@ function incrementAtPath(obj, path, amount) {
101
99
  const existing = current[leaf];
102
100
  current[leaf] = (typeof existing === "number" ? existing : 0) + amount;
103
101
  }
104
- //#endregion
105
- //#region src/store/federated-identity-store.ts
102
+ // src/store/federated-identity-store.ts
106
103
  /**
107
104
  * Copy only the DEFINED display fields — so a `touchLogin` / `link` with a
108
105
  * partial profile (e.g. Apple omitting the email on a repeat login) never
@@ -126,5 +123,4 @@ function pickDefinedProfile(src) {
126
123
  * keeps the federated-login core (`@aooth/idp`, phase 2) storage-agnostic.
127
124
  */
128
125
  var FederatedIdentityStore = class {};
129
- //#endregion
130
126
  export { maskEmail as a, setAtPath as c, incrementAtPath as i, UserStore as l, pickDefinedProfile as n, maskMfaValue as o, deepMerge as r, maskPhone as s, FederatedIdentityStore as t, UserAuthError as u };
@@ -1,5 +1,5 @@
1
1
  require("node:crypto");
2
- //#region src/errors.ts
2
+ // src/errors.ts
3
3
  const defaultMessages = {
4
4
  NOT_FOUND: "User not found",
5
5
  ALREADY_EXISTS: "User already exists",
@@ -24,8 +24,7 @@ var UserAuthError = class extends Error {
24
24
  this.details = details;
25
25
  }
26
26
  };
27
- //#endregion
28
- //#region src/store/user-store.ts
27
+ // src/store/user-store.ts
29
28
  /**
30
29
  * Storage seam for user credentials, keyed by the stable surrogate **`id`**
31
30
  * (the token subject). Reads come in three flavours:
@@ -40,8 +39,7 @@ var UserAuthError = class extends Error {
40
39
  * Writes (`update`/`delete`/`withCas`) all key on the surrogate `id`.
41
40
  */
42
41
  var UserStore = class {};
43
- //#endregion
44
- //#region src/utils.ts
42
+ // src/utils.ts
45
43
  function maskEmail(email) {
46
44
  if (!email) return "";
47
45
  const at = email.indexOf("@");
@@ -101,8 +99,7 @@ function incrementAtPath(obj, path, amount) {
101
99
  const existing = current[leaf];
102
100
  current[leaf] = (typeof existing === "number" ? existing : 0) + amount;
103
101
  }
104
- //#endregion
105
- //#region src/store/federated-identity-store.ts
102
+ // src/store/federated-identity-store.ts
106
103
  /**
107
104
  * Copy only the DEFINED display fields — so a `touchLogin` / `link` with a
108
105
  * partial profile (e.g. Apple omitting the email on a repeat login) never
@@ -126,7 +123,6 @@ function pickDefinedProfile(src) {
126
123
  * keeps the federated-login core (`@aooth/idp`, phase 2) storage-agnostic.
127
124
  */
128
125
  var FederatedIdentityStore = class {};
129
- //#endregion
130
126
  Object.defineProperty(exports, "FederatedIdentityStore", {
131
127
  enumerable: true,
132
128
  get: function() {
@@ -1,4 +1,3 @@
1
- //#region src/types.d.ts
2
1
  interface UserCredentials {
3
2
  id: string;
4
3
  username: string;
@@ -243,8 +242,6 @@ interface TotpConfig {
243
242
  /** Injectable clock for testability */
244
243
  clock?: () => number;
245
244
  }
246
- //#endregion
247
- //#region src/store/user-store.d.ts
248
245
  interface WithCasOptions {
249
246
  /**
250
247
  * Total attempts (1 initial + retries). Default `2` = one retry. Each
@@ -312,8 +309,6 @@ declare abstract class UserStore<T extends object = object> {
312
309
  */
313
310
  abstract withCas(id: string, mutator: (current: UserCredentials & T) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
314
311
  }
315
- //#endregion
316
- //#region src/store/federated-identity-store.d.ts
317
312
  /**
318
313
  * Display fields snapshotted from an IdP profile onto a federated-identity row.
319
314
  * Refreshed on each login via {@link FederatedIdentityStore.touchLogin}; never
@@ -404,5 +399,4 @@ declare abstract class FederatedIdentityStore {
404
399
  */
405
400
  abstract deleteAllForUser(userId: string): Promise<number>;
406
401
  }
407
- //#endregion
408
402
  export { TotpConfig as C, UserCredentials as D, UserAuthErrorType as E, UserServiceConfig as O, PolicyCheckResult as S, TrustedDeviceRecord as T, PasswordData as _, pickDefinedProfile as a, PasswordPolicyEvalFn as b, AccountData as c, LockoutConfig as d, LoginResult as f, PasswordConfig as g, MfaMethodInfo as h, NewFederatedIdentity as i, UserStoreUpdate as k, DeepPartial as l, MfaMethod as m, FederatedIdentityStore as n, UserStore as o, MfaData as p, FederatedProfileSnapshot as r, WithCasOptions as s, FederatedIdentity as t, LockStatus as u, PasswordPolicyContext as v, TransferablePolicy as w, PasswordPolicyInstance as x, PasswordPolicyDef as y };
@@ -1,4 +1,3 @@
1
- //#region src/types.d.ts
2
1
  interface UserCredentials {
3
2
  id: string;
4
3
  username: string;
@@ -243,8 +242,6 @@ interface TotpConfig {
243
242
  /** Injectable clock for testability */
244
243
  clock?: () => number;
245
244
  }
246
- //#endregion
247
- //#region src/store/user-store.d.ts
248
245
  interface WithCasOptions {
249
246
  /**
250
247
  * Total attempts (1 initial + retries). Default `2` = one retry. Each
@@ -312,8 +309,6 @@ declare abstract class UserStore<T extends object = object> {
312
309
  */
313
310
  abstract withCas(id: string, mutator: (current: UserCredentials & T) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
314
311
  }
315
- //#endregion
316
- //#region src/store/federated-identity-store.d.ts
317
312
  /**
318
313
  * Display fields snapshotted from an IdP profile onto a federated-identity row.
319
314
  * Refreshed on each login via {@link FederatedIdentityStore.touchLogin}; never
@@ -404,5 +399,4 @@ declare abstract class FederatedIdentityStore {
404
399
  */
405
400
  abstract deleteAllForUser(userId: string): Promise<number>;
406
401
  }
407
- //#endregion
408
402
  export { TotpConfig as C, UserCredentials as D, UserAuthErrorType as E, UserServiceConfig as O, PolicyCheckResult as S, TrustedDeviceRecord as T, PasswordData as _, pickDefinedProfile as a, PasswordPolicyEvalFn as b, AccountData as c, LockoutConfig as d, LoginResult as f, PasswordConfig as g, MfaMethodInfo as h, NewFederatedIdentity as i, UserStoreUpdate as k, DeepPartial as l, MfaMethod as m, FederatedIdentityStore as n, UserStore as o, MfaData as p, FederatedProfileSnapshot as r, WithCasOptions as s, FederatedIdentity as t, LockStatus as u, PasswordPolicyContext as v, TransferablePolicy as w, PasswordPolicyInstance as x, PasswordPolicyDef as y };
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_federated_identity_store = require("./federated-identity-store-D-LvRXdx.cjs");
2
+ const require_federated_identity_store = require("./federated-identity-store-Cbstwl4-.cjs");
3
3
  let node_crypto = require("node:crypto");
4
- //#region src/base-x/base32.ts
4
+ // src/base-x/base32.ts
5
5
  /**
6
6
  * Partially copied from "thirty-two" library, all credits to Chris Umbel.
7
7
  *
@@ -72,8 +72,7 @@ function decode(input) {
72
72
  }
73
73
  return output.subarray(0, index);
74
74
  }
75
- //#endregion
76
- //#region src/mfa/totp.ts
75
+ // src/mfa/totp.ts
77
76
  function generateTotpSecret(bytes = 20) {
78
77
  return encode((0, node_crypto.randomBytes)(bytes)).toString().replace(/=+$/, "").toUpperCase();
79
78
  }
@@ -127,8 +126,7 @@ function hotpCode(key, counter, digits) {
127
126
  const offset = hmacResult[hmacResult.length - 1] & 15;
128
127
  return (((hmacResult[offset] & 127) << 24 | (hmacResult[offset + 1] & 255) << 16 | (hmacResult[offset + 2] & 255) << 8 | hmacResult[offset + 3] & 255) % 10 ** digits).toString().padStart(digits, "0");
129
128
  }
130
- //#endregion
131
- //#region src/password/hasher.ts
129
+ // src/password/hasher.ts
132
130
  const DEFAULTS = {
133
131
  N: 16384,
134
132
  r: 8,
@@ -138,11 +136,11 @@ const DEFAULTS = {
138
136
  };
139
137
  const PREFIX = "$scrypt$";
140
138
  /** Node's default scrypt memory cap (32 MiB) — kept as the floor. */
141
- const DEFAULT_MAXMEM = 32 * 1024 * 1024;
139
+ const DEFAULT_MAXMEM = 33554432;
142
140
  /** Upper bound for the memory a (possibly stored, untrusted) parameter set may ask for. */
143
- const MAX_MAXMEM = 1024 * 1024 * 1024;
141
+ const MAX_MAXMEM = 1073741824;
144
142
  function scryptAsync(password, salt, keyLength, options) {
145
- const maxmem = Math.min(MAX_MAXMEM, Math.max(DEFAULT_MAXMEM, 256 * options.N * options.r + 1024 * 1024));
143
+ const maxmem = Math.min(MAX_MAXMEM, Math.max(DEFAULT_MAXMEM, 256 * options.N * options.r + 1048576));
146
144
  return new Promise((resolve, reject) => {
147
145
  (0, node_crypto.scrypt)(password, salt, keyLength, {
148
146
  ...options,
@@ -212,7 +210,7 @@ var PasswordHasher = class {
212
210
  const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
213
211
  const digits = "0123456789";
214
212
  const special = "!@#$%^&*()-_=+";
215
- const all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+";
213
+ const all = lower + upper + digits + special;
216
214
  const bytes = (0, node_crypto.randomBytes)(minLen);
217
215
  const result = Array.from({ length: minLen });
218
216
  result[0] = lower[bytes[0] % 26];
@@ -228,8 +226,7 @@ var PasswordHasher = class {
228
226
  return result.join("");
229
227
  }
230
228
  };
231
- //#endregion
232
- //#region src/password/policy.ts
229
+ // src/password/policy.ts
233
230
  function normalizePolicies(policies) {
234
231
  return (policies || []).map((p) => p instanceof PasswordPolicy ? p : new PasswordPolicy(p));
235
232
  }
@@ -283,8 +280,7 @@ var PasswordPolicy = class {
283
280
  return this.serialized !== void 0;
284
281
  }
285
282
  };
286
- //#endregion
287
- //#region src/user-service.ts
283
+ // src/user-service.ts
288
284
  function resolveConfig(config) {
289
285
  return {
290
286
  password: {
@@ -1108,8 +1104,7 @@ function observeWrites(store, hooks) {
1108
1104
  return fn;
1109
1105
  } });
1110
1106
  }
1111
- //#endregion
1112
- //#region src/store/memory.ts
1107
+ // src/store/memory.ts
1113
1108
  var UserStoreMemory = class extends require_federated_identity_store.UserStore {
1114
1109
  /** Keyed by the stable surrogate `id` (the token subject). */
1115
1110
  store = /* @__PURE__ */ new Map();
@@ -1223,8 +1218,7 @@ var UserStoreMemory = class extends require_federated_identity_store.UserStore {
1223
1218
  throw new require_federated_identity_store.UserAuthError("CAS_EXHAUSTED");
1224
1219
  }
1225
1220
  };
1226
- //#endregion
1227
- //#region src/store/federated-identity-store-memory.ts
1221
+ // src/store/federated-identity-store-memory.ts
1228
1222
  /**
1229
1223
  * In-memory {@link FederatedIdentityStore} — the offline-testable reference
1230
1224
  * impl (RFC IDP.md §9). Keyed by the composite `(provider, subject)`;
@@ -1282,8 +1276,7 @@ var FederatedIdentityStoreMemory = class extends require_federated_identity_stor
1282
1276
  function compositeKey(provider, subject) {
1283
1277
  return `${provider}${subject}`;
1284
1278
  }
1285
- //#endregion
1286
- //#region src/password/policies.ts
1279
+ // src/password/policies.ts
1287
1280
  const ppHasMinLength = (min = 8) => definePasswordPolicy({
1288
1281
  rule: (v, min) => v.length >= min,
1289
1282
  args: [min],
@@ -1320,8 +1313,7 @@ const ppMaxRepeatedChars = (maxRepeated = 2) => definePasswordPolicy({
1320
1313
  description: `No more than ${maxRepeated} consecutive repeated characters`,
1321
1314
  errorMessage: `Password must not have more than ${maxRepeated} consecutive repeated characters`
1322
1315
  });
1323
- //#endregion
1324
- //#region src/mfa/codes.ts
1316
+ // src/mfa/codes.ts
1325
1317
  /**
1326
1318
  * SHA-256 hash of an MFA code (e.g. one-time email/SMS code or backup code).
1327
1319
  *
@@ -1346,7 +1338,6 @@ function verifyMfaCode(submitted, expectedHash) {
1346
1338
  if (a.length !== b.length) return false;
1347
1339
  return (0, node_crypto.timingSafeEqual)(a, b);
1348
1340
  }
1349
- //#endregion
1350
1341
  exports.FederatedIdentityStore = require_federated_identity_store.FederatedIdentityStore;
1351
1342
  exports.FederatedIdentityStoreMemory = FederatedIdentityStoreMemory;
1352
1343
  exports.PasswordHasher = PasswordHasher;
package/dist/index.d.cts CHANGED
@@ -1,14 +1,11 @@
1
- import { C as TotpConfig, D as UserCredentials, E as UserAuthErrorType, O as UserServiceConfig, S as PolicyCheckResult, T as TrustedDeviceRecord, _ as PasswordData, a as pickDefinedProfile, b as PasswordPolicyEvalFn, c as AccountData, d as LockoutConfig, f as LoginResult, g as PasswordConfig, h as MfaMethodInfo, i as NewFederatedIdentity, k as UserStoreUpdate, l as DeepPartial, m as MfaMethod, n as FederatedIdentityStore, o as UserStore, p as MfaData, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity, u as LockStatus, v as PasswordPolicyContext, w as TransferablePolicy, x as PasswordPolicyInstance, y as PasswordPolicyDef } from "./federated-identity-store-B_jEkl-a.cjs";
2
- //#region src/errors.d.ts
3
- declare class UserAuthError extends Error {
1
+ import { C as TotpConfig, D as UserCredentials, E as UserAuthErrorType, O as UserServiceConfig, S as PolicyCheckResult, T as TrustedDeviceRecord, _ as PasswordData, a as pickDefinedProfile, b as PasswordPolicyEvalFn, c as AccountData, d as LockoutConfig, f as LoginResult, g as PasswordConfig, h as MfaMethodInfo, i as NewFederatedIdentity, k as UserStoreUpdate, l as DeepPartial, m as MfaMethod, n as FederatedIdentityStore, o as UserStore, p as MfaData, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity, u as LockStatus, v as PasswordPolicyContext, w as TransferablePolicy, x as PasswordPolicyInstance, y as PasswordPolicyDef } from "./federated-identity-store-D10-BT9l.cjs";
2
+ export declare class UserAuthError extends Error {
4
3
  readonly type: UserAuthErrorType;
5
4
  readonly details?: Record<string, unknown> | undefined;
6
5
  readonly name = "UserAuthError";
7
6
  constructor(type: UserAuthErrorType, message?: string, details?: Record<string, unknown> | undefined);
8
7
  }
9
- //#endregion
10
- //#region src/password/hasher.d.ts
11
- declare class PasswordHasher {
8
+ export declare class PasswordHasher {
12
9
  private readonly pepper;
13
10
  private readonly N;
14
11
  private readonly r;
@@ -19,9 +16,7 @@ declare class PasswordHasher {
19
16
  verify(password: string, encoded: string): Promise<boolean>;
20
17
  generatePassword(length?: number): string;
21
18
  }
22
- //#endregion
23
- //#region src/password/policy.d.ts
24
- declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolicyInstance)[]): PasswordPolicy[];
19
+ export declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolicyInstance)[]): PasswordPolicy[];
25
20
  /**
26
21
  * Helper that builds a `PasswordPolicyDef` from a real backend function plus
27
22
  * its bound positional arguments. The function runs directly on the server
@@ -43,13 +38,13 @@ declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolic
43
38
  * `undefined` and `transferable` is false; frontend pre-validation skips it
44
39
  * and only the server check enforces the rule.
45
40
  */
46
- declare function definePasswordPolicy<A extends readonly unknown[]>(opts: {
41
+ export declare function definePasswordPolicy<A extends readonly unknown[]>(opts: {
47
42
  rule: (v: string, ...args: A) => boolean | Promise<boolean>;
48
43
  args?: A;
49
44
  description?: string;
50
45
  errorMessage?: string;
51
46
  }): PasswordPolicyDef;
52
- declare class PasswordPolicy implements PasswordPolicyInstance {
47
+ export declare class PasswordPolicy implements PasswordPolicyInstance {
53
48
  readonly rule: PasswordPolicyEvalFn;
54
49
  readonly serialized?: string;
55
50
  readonly description: string;
@@ -58,8 +53,6 @@ declare class PasswordPolicy implements PasswordPolicyInstance {
58
53
  evaluate(password: string, context?: PasswordPolicyContext): boolean | Promise<boolean>;
59
54
  get transferable(): boolean;
60
55
  }
61
- //#endregion
62
- //#region src/user-service.d.ts
63
56
  interface ResolvedConfig {
64
57
  password: Required<Omit<PasswordConfig, "policies">> & {
65
58
  policies: PasswordPolicy[];
@@ -71,7 +64,7 @@ interface ResolvedConfig {
71
64
  };
72
65
  emailField?: string;
73
66
  }
74
- declare const SEEN_DEVICES_DEFAULT_CAP = 5;
67
+ export declare const SEEN_DEVICES_DEFAULT_CAP = 5;
75
68
  /**
76
69
  * Orchestrates user credentials over a pluggable {@link UserStore}.
77
70
  *
@@ -81,7 +74,7 @@ declare const SEEN_DEVICES_DEFAULT_CAP = 5;
81
74
  * handle-driven entry points) take a `username`/`email` login handle, resolved
82
75
  * via `UserStore.findByHandle`.
83
76
  */
84
- declare class UserService<T extends object = object> {
77
+ export declare class UserService<T extends object = object> {
85
78
  protected readonly store: UserStore<T>;
86
79
  protected readonly config: ResolvedConfig;
87
80
  protected readonly hasher: PasswordHasher;
@@ -386,9 +379,7 @@ declare class UserService<T extends object = object> {
386
379
  */
387
380
  private incrementAndMaybeLock;
388
381
  }
389
- //#endregion
390
- //#region src/store/memory.d.ts
391
- declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
382
+ export declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
392
383
  /** Keyed by the stable surrogate `id` (the token subject). */
393
384
  private store;
394
385
  /**
@@ -427,8 +418,6 @@ declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
427
418
  delete(id: string): Promise<boolean>;
428
419
  withCas(id: string, mutator: (current: UserCredentials & T) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
429
420
  }
430
- //#endregion
431
- //#region src/store/federated-identity-store-memory.d.ts
432
421
  interface FederatedIdentityStoreMemoryOptions {
433
422
  /** Injectable clock for deterministic `linkedAt` / `lastLoginAt`. Defaults to `Date.now`. */
434
423
  clock?: () => number;
@@ -439,7 +428,7 @@ interface FederatedIdentityStoreMemoryOptions {
439
428
  * `structuredClone` on every read/write isolates callers from later mutation
440
429
  * (mirrors `UserStoreMemory`).
441
430
  */
442
- declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
431
+ export declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
443
432
  /** Keyed by `compositeKey(provider, subject)`. */
444
433
  private store;
445
434
  private clock;
@@ -451,28 +440,22 @@ declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
451
440
  touchLogin(provider: string, subject: string, profile?: FederatedProfileSnapshot): Promise<void>;
452
441
  deleteAllForUser(userId: string): Promise<number>;
453
442
  }
454
- //#endregion
455
- //#region src/password/policies.d.ts
456
- declare const ppHasMinLength: (min?: number) => PasswordPolicyDef;
457
- declare const ppHasUpperCase: (n?: number) => PasswordPolicyDef;
458
- declare const ppHasLowerCase: (n?: number) => PasswordPolicyDef;
459
- declare const ppHasNumber: (n?: number) => PasswordPolicyDef;
460
- declare const ppHasSpecialChar: (n?: number) => PasswordPolicyDef;
461
- declare const ppMaxRepeatedChars: (maxRepeated?: number) => PasswordPolicyDef;
462
- //#endregion
463
- //#region src/mfa/totp.d.ts
464
- declare function generateTotpSecret(bytes?: number): string;
465
- declare function generateTotpUri(secret: string, issuer: string, account: string, config?: Pick<TotpConfig, "period" | "digits">): string;
466
- declare function generateTotpCode(secret: string, config?: TotpConfig): string;
443
+ export declare const ppHasMinLength: (min?: number) => PasswordPolicyDef;
444
+ export declare const ppHasUpperCase: (n?: number) => PasswordPolicyDef;
445
+ export declare const ppHasLowerCase: (n?: number) => PasswordPolicyDef;
446
+ export declare const ppHasNumber: (n?: number) => PasswordPolicyDef;
447
+ export declare const ppHasSpecialChar: (n?: number) => PasswordPolicyDef;
448
+ export declare const ppMaxRepeatedChars: (maxRepeated?: number) => PasswordPolicyDef;
449
+ export declare function generateTotpSecret(bytes?: number): string;
450
+ export declare function generateTotpUri(secret: string, issuer: string, account: string, config?: Pick<TotpConfig, "period" | "digits">): string;
451
+ export declare function generateTotpCode(secret: string, config?: TotpConfig): string;
467
452
  /**
468
453
  * Returns the matched HOTP counter when `code` is valid within the verification
469
454
  * window, otherwise `null`. Returning the counter (not a bool) lets the caller
470
455
  * persist `lastUsedWindow` and reject same-window replays (RFC 6238 §5.2 SHOULD).
471
456
  */
472
- declare function verifyTotpCode(secret: string, code: string, config?: TotpConfig): number | null;
473
- declare function generateMfaCode(length?: number): string;
474
- //#endregion
475
- //#region src/mfa/codes.d.ts
457
+ export declare function verifyTotpCode(secret: string, code: string, config?: TotpConfig): number | null;
458
+ export declare function generateMfaCode(length?: number): string;
476
459
  /**
477
460
  * SHA-256 hash of an MFA code (e.g. one-time email/SMS code or backup code).
478
461
  *
@@ -480,7 +463,7 @@ declare function generateMfaCode(length?: number): string;
480
463
  * Use {@link verifyMfaCode} to compare a submitted plaintext code against the
481
464
  * stored hash in constant time.
482
465
  */
483
- declare function hashMfaCode(code: string): string;
466
+ export declare function hashMfaCode(code: string): string;
484
467
  /**
485
468
  * Constant-time comparison of a submitted plaintext code against an
486
469
  * expected SHA-256 hex hash (as produced by {@link hashMfaCode}).
@@ -488,12 +471,9 @@ declare function hashMfaCode(code: string): string;
488
471
  * Returns false for malformed/empty expected hashes (timingSafeEqual
489
472
  * requires equal-length, non-empty buffers).
490
473
  */
491
- declare function verifyMfaCode(submitted: string, expectedHash: string): boolean;
492
- //#endregion
493
- //#region src/utils.d.ts
494
- declare function maskEmail(email: string): string;
495
- declare function maskPhone(phone: string): string;
496
- declare function maskMfaValue(method: MfaMethod): string;
497
- declare function setAtPath(obj: object, path: string, value: unknown): void;
498
- //#endregion
499
- export { type AccountData, type DeepPartial, type FederatedIdentity, FederatedIdentityStore, FederatedIdentityStoreMemory, type FederatedIdentityStoreMemoryOptions, type FederatedProfileSnapshot, type LockStatus, type LockoutConfig, type LoginResult, type MfaData, type MfaMethod, type MfaMethodInfo, type NewFederatedIdentity, type PasswordConfig, type PasswordData, PasswordHasher, PasswordPolicy, type PasswordPolicyContext, type PasswordPolicyDef, type PasswordPolicyEvalFn, type PasswordPolicyInstance, type PolicyCheckResult, SEEN_DEVICES_DEFAULT_CAP, type TotpConfig, type TransferablePolicy, type TrustedDeviceRecord, UserAuthError, type UserAuthErrorType, type UserCredentials, UserService, type UserServiceConfig, UserStore, UserStoreMemory, type UserStoreUpdate, definePasswordPolicy, generateMfaCode, generateTotpCode, generateTotpSecret, generateTotpUri, hashMfaCode, maskEmail, maskMfaValue, maskPhone, normalizePolicies, pickDefinedProfile, ppHasLowerCase, ppHasMinLength, ppHasNumber, ppHasSpecialChar, ppHasUpperCase, ppMaxRepeatedChars, setAtPath, verifyMfaCode, verifyTotpCode };
474
+ export declare function verifyMfaCode(submitted: string, expectedHash: string): boolean;
475
+ export declare function maskEmail(email: string): string;
476
+ export declare function maskPhone(phone: string): string;
477
+ export declare function maskMfaValue(method: MfaMethod): string;
478
+ export declare function setAtPath(obj: object, path: string, value: unknown): void;
479
+ export { type AccountData, type DeepPartial, type FederatedIdentity, FederatedIdentityStore, type FederatedIdentityStoreMemoryOptions, type FederatedProfileSnapshot, type LockStatus, type LockoutConfig, type LoginResult, type MfaData, type MfaMethod, type MfaMethodInfo, type NewFederatedIdentity, type PasswordConfig, type PasswordData, type PasswordPolicyContext, type PasswordPolicyDef, type PasswordPolicyEvalFn, type PasswordPolicyInstance, type PolicyCheckResult, type TotpConfig, type TransferablePolicy, type TrustedDeviceRecord, type UserAuthErrorType, type UserCredentials, type UserServiceConfig, UserStore, type UserStoreUpdate, pickDefinedProfile };
package/dist/index.d.mts CHANGED
@@ -1,14 +1,11 @@
1
- import { C as TotpConfig, D as UserCredentials, E as UserAuthErrorType, O as UserServiceConfig, S as PolicyCheckResult, T as TrustedDeviceRecord, _ as PasswordData, a as pickDefinedProfile, b as PasswordPolicyEvalFn, c as AccountData, d as LockoutConfig, f as LoginResult, g as PasswordConfig, h as MfaMethodInfo, i as NewFederatedIdentity, k as UserStoreUpdate, l as DeepPartial, m as MfaMethod, n as FederatedIdentityStore, o as UserStore, p as MfaData, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity, u as LockStatus, v as PasswordPolicyContext, w as TransferablePolicy, x as PasswordPolicyInstance, y as PasswordPolicyDef } from "./federated-identity-store-B_jEkl-a.mjs";
2
- //#region src/errors.d.ts
3
- declare class UserAuthError extends Error {
1
+ import { C as TotpConfig, D as UserCredentials, E as UserAuthErrorType, O as UserServiceConfig, S as PolicyCheckResult, T as TrustedDeviceRecord, _ as PasswordData, a as pickDefinedProfile, b as PasswordPolicyEvalFn, c as AccountData, d as LockoutConfig, f as LoginResult, g as PasswordConfig, h as MfaMethodInfo, i as NewFederatedIdentity, k as UserStoreUpdate, l as DeepPartial, m as MfaMethod, n as FederatedIdentityStore, o as UserStore, p as MfaData, r as FederatedProfileSnapshot, s as WithCasOptions, t as FederatedIdentity, u as LockStatus, v as PasswordPolicyContext, w as TransferablePolicy, x as PasswordPolicyInstance, y as PasswordPolicyDef } from "./federated-identity-store-D10-BT9l.mjs";
2
+ export declare class UserAuthError extends Error {
4
3
  readonly type: UserAuthErrorType;
5
4
  readonly details?: Record<string, unknown> | undefined;
6
5
  readonly name = "UserAuthError";
7
6
  constructor(type: UserAuthErrorType, message?: string, details?: Record<string, unknown> | undefined);
8
7
  }
9
- //#endregion
10
- //#region src/password/hasher.d.ts
11
- declare class PasswordHasher {
8
+ export declare class PasswordHasher {
12
9
  private readonly pepper;
13
10
  private readonly N;
14
11
  private readonly r;
@@ -19,9 +16,7 @@ declare class PasswordHasher {
19
16
  verify(password: string, encoded: string): Promise<boolean>;
20
17
  generatePassword(length?: number): string;
21
18
  }
22
- //#endregion
23
- //#region src/password/policy.d.ts
24
- declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolicyInstance)[]): PasswordPolicy[];
19
+ export declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolicyInstance)[]): PasswordPolicy[];
25
20
  /**
26
21
  * Helper that builds a `PasswordPolicyDef` from a real backend function plus
27
22
  * its bound positional arguments. The function runs directly on the server
@@ -43,13 +38,13 @@ declare function normalizePolicies(policies?: (PasswordPolicyDef | PasswordPolic
43
38
  * `undefined` and `transferable` is false; frontend pre-validation skips it
44
39
  * and only the server check enforces the rule.
45
40
  */
46
- declare function definePasswordPolicy<A extends readonly unknown[]>(opts: {
41
+ export declare function definePasswordPolicy<A extends readonly unknown[]>(opts: {
47
42
  rule: (v: string, ...args: A) => boolean | Promise<boolean>;
48
43
  args?: A;
49
44
  description?: string;
50
45
  errorMessage?: string;
51
46
  }): PasswordPolicyDef;
52
- declare class PasswordPolicy implements PasswordPolicyInstance {
47
+ export declare class PasswordPolicy implements PasswordPolicyInstance {
53
48
  readonly rule: PasswordPolicyEvalFn;
54
49
  readonly serialized?: string;
55
50
  readonly description: string;
@@ -58,8 +53,6 @@ declare class PasswordPolicy implements PasswordPolicyInstance {
58
53
  evaluate(password: string, context?: PasswordPolicyContext): boolean | Promise<boolean>;
59
54
  get transferable(): boolean;
60
55
  }
61
- //#endregion
62
- //#region src/user-service.d.ts
63
56
  interface ResolvedConfig {
64
57
  password: Required<Omit<PasswordConfig, "policies">> & {
65
58
  policies: PasswordPolicy[];
@@ -71,7 +64,7 @@ interface ResolvedConfig {
71
64
  };
72
65
  emailField?: string;
73
66
  }
74
- declare const SEEN_DEVICES_DEFAULT_CAP = 5;
67
+ export declare const SEEN_DEVICES_DEFAULT_CAP = 5;
75
68
  /**
76
69
  * Orchestrates user credentials over a pluggable {@link UserStore}.
77
70
  *
@@ -81,7 +74,7 @@ declare const SEEN_DEVICES_DEFAULT_CAP = 5;
81
74
  * handle-driven entry points) take a `username`/`email` login handle, resolved
82
75
  * via `UserStore.findByHandle`.
83
76
  */
84
- declare class UserService<T extends object = object> {
77
+ export declare class UserService<T extends object = object> {
85
78
  protected readonly store: UserStore<T>;
86
79
  protected readonly config: ResolvedConfig;
87
80
  protected readonly hasher: PasswordHasher;
@@ -386,9 +379,7 @@ declare class UserService<T extends object = object> {
386
379
  */
387
380
  private incrementAndMaybeLock;
388
381
  }
389
- //#endregion
390
- //#region src/store/memory.d.ts
391
- declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
382
+ export declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
392
383
  /** Keyed by the stable surrogate `id` (the token subject). */
393
384
  private store;
394
385
  /**
@@ -427,8 +418,6 @@ declare class UserStoreMemory<T extends object = object> extends UserStore<T> {
427
418
  delete(id: string): Promise<boolean>;
428
419
  withCas(id: string, mutator: (current: UserCredentials & T) => UserStoreUpdate | null, opts?: WithCasOptions): Promise<void>;
429
420
  }
430
- //#endregion
431
- //#region src/store/federated-identity-store-memory.d.ts
432
421
  interface FederatedIdentityStoreMemoryOptions {
433
422
  /** Injectable clock for deterministic `linkedAt` / `lastLoginAt`. Defaults to `Date.now`. */
434
423
  clock?: () => number;
@@ -439,7 +428,7 @@ interface FederatedIdentityStoreMemoryOptions {
439
428
  * `structuredClone` on every read/write isolates callers from later mutation
440
429
  * (mirrors `UserStoreMemory`).
441
430
  */
442
- declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
431
+ export declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
443
432
  /** Keyed by `compositeKey(provider, subject)`. */
444
433
  private store;
445
434
  private clock;
@@ -451,28 +440,22 @@ declare class FederatedIdentityStoreMemory extends FederatedIdentityStore {
451
440
  touchLogin(provider: string, subject: string, profile?: FederatedProfileSnapshot): Promise<void>;
452
441
  deleteAllForUser(userId: string): Promise<number>;
453
442
  }
454
- //#endregion
455
- //#region src/password/policies.d.ts
456
- declare const ppHasMinLength: (min?: number) => PasswordPolicyDef;
457
- declare const ppHasUpperCase: (n?: number) => PasswordPolicyDef;
458
- declare const ppHasLowerCase: (n?: number) => PasswordPolicyDef;
459
- declare const ppHasNumber: (n?: number) => PasswordPolicyDef;
460
- declare const ppHasSpecialChar: (n?: number) => PasswordPolicyDef;
461
- declare const ppMaxRepeatedChars: (maxRepeated?: number) => PasswordPolicyDef;
462
- //#endregion
463
- //#region src/mfa/totp.d.ts
464
- declare function generateTotpSecret(bytes?: number): string;
465
- declare function generateTotpUri(secret: string, issuer: string, account: string, config?: Pick<TotpConfig, "period" | "digits">): string;
466
- declare function generateTotpCode(secret: string, config?: TotpConfig): string;
443
+ export declare const ppHasMinLength: (min?: number) => PasswordPolicyDef;
444
+ export declare const ppHasUpperCase: (n?: number) => PasswordPolicyDef;
445
+ export declare const ppHasLowerCase: (n?: number) => PasswordPolicyDef;
446
+ export declare const ppHasNumber: (n?: number) => PasswordPolicyDef;
447
+ export declare const ppHasSpecialChar: (n?: number) => PasswordPolicyDef;
448
+ export declare const ppMaxRepeatedChars: (maxRepeated?: number) => PasswordPolicyDef;
449
+ export declare function generateTotpSecret(bytes?: number): string;
450
+ export declare function generateTotpUri(secret: string, issuer: string, account: string, config?: Pick<TotpConfig, "period" | "digits">): string;
451
+ export declare function generateTotpCode(secret: string, config?: TotpConfig): string;
467
452
  /**
468
453
  * Returns the matched HOTP counter when `code` is valid within the verification
469
454
  * window, otherwise `null`. Returning the counter (not a bool) lets the caller
470
455
  * persist `lastUsedWindow` and reject same-window replays (RFC 6238 §5.2 SHOULD).
471
456
  */
472
- declare function verifyTotpCode(secret: string, code: string, config?: TotpConfig): number | null;
473
- declare function generateMfaCode(length?: number): string;
474
- //#endregion
475
- //#region src/mfa/codes.d.ts
457
+ export declare function verifyTotpCode(secret: string, code: string, config?: TotpConfig): number | null;
458
+ export declare function generateMfaCode(length?: number): string;
476
459
  /**
477
460
  * SHA-256 hash of an MFA code (e.g. one-time email/SMS code or backup code).
478
461
  *
@@ -480,7 +463,7 @@ declare function generateMfaCode(length?: number): string;
480
463
  * Use {@link verifyMfaCode} to compare a submitted plaintext code against the
481
464
  * stored hash in constant time.
482
465
  */
483
- declare function hashMfaCode(code: string): string;
466
+ export declare function hashMfaCode(code: string): string;
484
467
  /**
485
468
  * Constant-time comparison of a submitted plaintext code against an
486
469
  * expected SHA-256 hex hash (as produced by {@link hashMfaCode}).
@@ -488,12 +471,9 @@ declare function hashMfaCode(code: string): string;
488
471
  * Returns false for malformed/empty expected hashes (timingSafeEqual
489
472
  * requires equal-length, non-empty buffers).
490
473
  */
491
- declare function verifyMfaCode(submitted: string, expectedHash: string): boolean;
492
- //#endregion
493
- //#region src/utils.d.ts
494
- declare function maskEmail(email: string): string;
495
- declare function maskPhone(phone: string): string;
496
- declare function maskMfaValue(method: MfaMethod): string;
497
- declare function setAtPath(obj: object, path: string, value: unknown): void;
498
- //#endregion
499
- export { type AccountData, type DeepPartial, type FederatedIdentity, FederatedIdentityStore, FederatedIdentityStoreMemory, type FederatedIdentityStoreMemoryOptions, type FederatedProfileSnapshot, type LockStatus, type LockoutConfig, type LoginResult, type MfaData, type MfaMethod, type MfaMethodInfo, type NewFederatedIdentity, type PasswordConfig, type PasswordData, PasswordHasher, PasswordPolicy, type PasswordPolicyContext, type PasswordPolicyDef, type PasswordPolicyEvalFn, type PasswordPolicyInstance, type PolicyCheckResult, SEEN_DEVICES_DEFAULT_CAP, type TotpConfig, type TransferablePolicy, type TrustedDeviceRecord, UserAuthError, type UserAuthErrorType, type UserCredentials, UserService, type UserServiceConfig, UserStore, UserStoreMemory, type UserStoreUpdate, definePasswordPolicy, generateMfaCode, generateTotpCode, generateTotpSecret, generateTotpUri, hashMfaCode, maskEmail, maskMfaValue, maskPhone, normalizePolicies, pickDefinedProfile, ppHasLowerCase, ppHasMinLength, ppHasNumber, ppHasSpecialChar, ppHasUpperCase, ppMaxRepeatedChars, setAtPath, verifyMfaCode, verifyTotpCode };
474
+ export declare function verifyMfaCode(submitted: string, expectedHash: string): boolean;
475
+ export declare function maskEmail(email: string): string;
476
+ export declare function maskPhone(phone: string): string;
477
+ export declare function maskMfaValue(method: MfaMethod): string;
478
+ export declare function setAtPath(obj: object, path: string, value: unknown): void;
479
+ export { type AccountData, type DeepPartial, type FederatedIdentity, FederatedIdentityStore, type FederatedIdentityStoreMemoryOptions, type FederatedProfileSnapshot, type LockStatus, type LockoutConfig, type LoginResult, type MfaData, type MfaMethod, type MfaMethodInfo, type NewFederatedIdentity, type PasswordConfig, type PasswordData, type PasswordPolicyContext, type PasswordPolicyDef, type PasswordPolicyEvalFn, type PasswordPolicyInstance, type PolicyCheckResult, type TotpConfig, type TransferablePolicy, type TrustedDeviceRecord, type UserAuthErrorType, type UserCredentials, type UserServiceConfig, UserStore, type UserStoreUpdate, pickDefinedProfile };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { a as maskEmail, c as setAtPath, i as incrementAtPath, l as UserStore, n as pickDefinedProfile, o as maskMfaValue, r as deepMerge, s as maskPhone, t as FederatedIdentityStore, u as UserAuthError } from "./federated-identity-store-CRycYlMj.mjs";
1
+ import { a as maskEmail, c as setAtPath, i as incrementAtPath, l as UserStore, n as pickDefinedProfile, o as maskMfaValue, r as deepMerge, s as maskPhone, t as FederatedIdentityStore, u as UserAuthError } from "./federated-identity-store-BZRvw9Pz.mjs";
2
2
  import { createHash, createHmac, randomBytes, randomInt, randomUUID, scrypt, timingSafeEqual } from "node:crypto";
3
- //#region src/base-x/base32.ts
3
+ // src/base-x/base32.ts
4
4
  /**
5
5
  * Partially copied from "thirty-two" library, all credits to Chris Umbel.
6
6
  *
@@ -71,8 +71,7 @@ function decode(input) {
71
71
  }
72
72
  return output.subarray(0, index);
73
73
  }
74
- //#endregion
75
- //#region src/mfa/totp.ts
74
+ // src/mfa/totp.ts
76
75
  function generateTotpSecret(bytes = 20) {
77
76
  return encode(randomBytes(bytes)).toString().replace(/=+$/, "").toUpperCase();
78
77
  }
@@ -126,8 +125,7 @@ function hotpCode(key, counter, digits) {
126
125
  const offset = hmacResult[hmacResult.length - 1] & 15;
127
126
  return (((hmacResult[offset] & 127) << 24 | (hmacResult[offset + 1] & 255) << 16 | (hmacResult[offset + 2] & 255) << 8 | hmacResult[offset + 3] & 255) % 10 ** digits).toString().padStart(digits, "0");
128
127
  }
129
- //#endregion
130
- //#region src/password/hasher.ts
128
+ // src/password/hasher.ts
131
129
  const DEFAULTS = {
132
130
  N: 16384,
133
131
  r: 8,
@@ -137,11 +135,11 @@ const DEFAULTS = {
137
135
  };
138
136
  const PREFIX = "$scrypt$";
139
137
  /** Node's default scrypt memory cap (32 MiB) — kept as the floor. */
140
- const DEFAULT_MAXMEM = 32 * 1024 * 1024;
138
+ const DEFAULT_MAXMEM = 33554432;
141
139
  /** Upper bound for the memory a (possibly stored, untrusted) parameter set may ask for. */
142
- const MAX_MAXMEM = 1024 * 1024 * 1024;
140
+ const MAX_MAXMEM = 1073741824;
143
141
  function scryptAsync(password, salt, keyLength, options) {
144
- const maxmem = Math.min(MAX_MAXMEM, Math.max(DEFAULT_MAXMEM, 256 * options.N * options.r + 1024 * 1024));
142
+ const maxmem = Math.min(MAX_MAXMEM, Math.max(DEFAULT_MAXMEM, 256 * options.N * options.r + 1048576));
145
143
  return new Promise((resolve, reject) => {
146
144
  scrypt(password, salt, keyLength, {
147
145
  ...options,
@@ -211,7 +209,7 @@ var PasswordHasher = class {
211
209
  const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
212
210
  const digits = "0123456789";
213
211
  const special = "!@#$%^&*()-_=+";
214
- const all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+";
212
+ const all = lower + upper + digits + special;
215
213
  const bytes = randomBytes(minLen);
216
214
  const result = Array.from({ length: minLen });
217
215
  result[0] = lower[bytes[0] % 26];
@@ -227,8 +225,7 @@ var PasswordHasher = class {
227
225
  return result.join("");
228
226
  }
229
227
  };
230
- //#endregion
231
- //#region src/password/policy.ts
228
+ // src/password/policy.ts
232
229
  function normalizePolicies(policies) {
233
230
  return (policies || []).map((p) => p instanceof PasswordPolicy ? p : new PasswordPolicy(p));
234
231
  }
@@ -282,8 +279,7 @@ var PasswordPolicy = class {
282
279
  return this.serialized !== void 0;
283
280
  }
284
281
  };
285
- //#endregion
286
- //#region src/user-service.ts
282
+ // src/user-service.ts
287
283
  function resolveConfig(config) {
288
284
  return {
289
285
  password: {
@@ -1107,8 +1103,7 @@ function observeWrites(store, hooks) {
1107
1103
  return fn;
1108
1104
  } });
1109
1105
  }
1110
- //#endregion
1111
- //#region src/store/memory.ts
1106
+ // src/store/memory.ts
1112
1107
  var UserStoreMemory = class extends UserStore {
1113
1108
  /** Keyed by the stable surrogate `id` (the token subject). */
1114
1109
  store = /* @__PURE__ */ new Map();
@@ -1222,8 +1217,7 @@ var UserStoreMemory = class extends UserStore {
1222
1217
  throw new UserAuthError("CAS_EXHAUSTED");
1223
1218
  }
1224
1219
  };
1225
- //#endregion
1226
- //#region src/store/federated-identity-store-memory.ts
1220
+ // src/store/federated-identity-store-memory.ts
1227
1221
  /**
1228
1222
  * In-memory {@link FederatedIdentityStore} — the offline-testable reference
1229
1223
  * impl (RFC IDP.md §9). Keyed by the composite `(provider, subject)`;
@@ -1281,8 +1275,7 @@ var FederatedIdentityStoreMemory = class extends FederatedIdentityStore {
1281
1275
  function compositeKey(provider, subject) {
1282
1276
  return `${provider}${subject}`;
1283
1277
  }
1284
- //#endregion
1285
- //#region src/password/policies.ts
1278
+ // src/password/policies.ts
1286
1279
  const ppHasMinLength = (min = 8) => definePasswordPolicy({
1287
1280
  rule: (v, min) => v.length >= min,
1288
1281
  args: [min],
@@ -1319,8 +1312,7 @@ const ppMaxRepeatedChars = (maxRepeated = 2) => definePasswordPolicy({
1319
1312
  description: `No more than ${maxRepeated} consecutive repeated characters`,
1320
1313
  errorMessage: `Password must not have more than ${maxRepeated} consecutive repeated characters`
1321
1314
  });
1322
- //#endregion
1323
- //#region src/mfa/codes.ts
1315
+ // src/mfa/codes.ts
1324
1316
  /**
1325
1317
  * SHA-256 hash of an MFA code (e.g. one-time email/SMS code or backup code).
1326
1318
  *
@@ -1345,5 +1337,4 @@ function verifyMfaCode(submitted, expectedHash) {
1345
1337
  if (a.length !== b.length) return false;
1346
1338
  return timingSafeEqual(a, b);
1347
1339
  }
1348
- //#endregion
1349
1340
  export { FederatedIdentityStore, FederatedIdentityStoreMemory, PasswordHasher, PasswordPolicy, SEEN_DEVICES_DEFAULT_CAP, UserAuthError, UserService, UserStore, UserStoreMemory, definePasswordPolicy, generateMfaCode, generateTotpCode, generateTotpSecret, generateTotpUri, hashMfaCode, maskEmail, maskMfaValue, maskPhone, normalizePolicies, pickDefinedProfile, ppHasLowerCase, ppHasMinLength, ppHasNumber, ppHasSpecialChar, ppHasUpperCase, ppMaxRepeatedChars, setAtPath, verifyMfaCode, verifyTotpCode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aooth/user",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "User credential primitives for aoothjs",
5
5
  "keywords": [
6
6
  "aoothjs",
@@ -60,18 +60,18 @@
60
60
  "access": "public"
61
61
  },
62
62
  "devDependencies": {
63
- "@atscript/core": "^0.1.109",
64
- "@atscript/db": "^0.1.164",
65
- "@atscript/db-sql-tools": "^0.1.164",
66
- "@atscript/db-sqlite": "^0.1.164",
67
- "@atscript/typescript": "^0.1.109",
63
+ "@atscript/core": "^0.2.3",
64
+ "@atscript/db": "^0.1.167",
65
+ "@atscript/db-sql-tools": "^0.1.167",
66
+ "@atscript/db-sqlite": "^0.1.167",
67
+ "@atscript/typescript": "^0.2.3",
68
68
  "@types/better-sqlite3": "^7.6.13",
69
69
  "@uniqu/core": "^0.1.15",
70
70
  "better-sqlite3": "^12.6.2",
71
- "unplugin-atscript": "^0.1.109"
71
+ "unplugin-atscript": "^0.2.3"
72
72
  },
73
73
  "peerDependencies": {
74
- "@atscript/db": "^0.1.164"
74
+ "@atscript/db": "^0.1.167"
75
75
  },
76
76
  "peerDependenciesMeta": {
77
77
  "@atscript/db": {
@@ -7,7 +7,7 @@
7
7
  * Do not edit this file!
8
8
  */
9
9
 
10
- import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TAtscriptAnnotatedType, TMetadataMap, Validator, TValidatorOptions } from "@atscript/typescript/utils"
10
+ import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TAtscriptAnnotatedType, TAtscriptField, TMetadataMap, Validator, TValidatorOptions } from "@atscript/typescript/utils"
11
11
 
12
12
  /**
13
13
  * Atscript interface **AoothFederatedIdentity**
@@ -7,7 +7,7 @@
7
7
  * Do not edit this file!
8
8
  */
9
9
 
10
- import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TAtscriptAnnotatedType, TMetadataMap, Validator, TValidatorOptions } from "@atscript/typescript/utils"
10
+ import type { TAtscriptTypeObject, TAtscriptTypeComplex, TAtscriptTypeFinal, TAtscriptTypeArray, TAtscriptAnnotatedType, TAtscriptField, TMetadataMap, Validator, TValidatorOptions } from "@atscript/typescript/utils"
11
11
 
12
12
  /**
13
13
  * Atscript interface **AoothUserCredentials**