@nxgt/janus 0.20.0 → 0.22.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.
Files changed (39) hide show
  1. package/README.md +112 -12
  2. package/dist/auth/context/index.d.ts +1 -1
  3. package/dist/auth/context/index.d.ts.map +1 -1
  4. package/dist/auth/context/user.d.ts +7 -0
  5. package/dist/auth/context/user.d.ts.map +1 -1
  6. package/dist/auth/email-flows/prove-first.d.ts +23 -0
  7. package/dist/auth/email-flows/prove-first.d.ts.map +1 -0
  8. package/dist/auth/email-flows/verify-email.d.ts +6 -2
  9. package/dist/auth/email-flows/verify-email.d.ts.map +1 -1
  10. package/dist/auth/index.d.ts +1 -1
  11. package/dist/auth/index.d.ts.map +1 -1
  12. package/dist/auth/proven-sign-in.d.ts.map +1 -1
  13. package/dist/auth/types/email-flows.d.ts +43 -0
  14. package/dist/auth/types/email-flows.d.ts.map +1 -1
  15. package/dist/auth/types/find-by-email.d.ts +31 -0
  16. package/dist/auth/types/find-by-email.d.ts.map +1 -0
  17. package/dist/auth/types/index.d.ts +2 -1
  18. package/dist/auth/types/index.d.ts.map +1 -1
  19. package/dist/auth/types/janus.d.ts +2 -1
  20. package/dist/auth/types/janus.d.ts.map +1 -1
  21. package/dist/auth/users/any-type-api.d.ts +2 -2
  22. package/dist/auth/users/any-type-api.d.ts.map +1 -1
  23. package/dist/auth/users/find-by-email.d.ts +11 -0
  24. package/dist/auth/users/find-by-email.d.ts.map +1 -0
  25. package/dist/auth/users/type-api.d.ts +1 -1
  26. package/dist/auth/users/type-api.d.ts.map +1 -1
  27. package/dist/index.js +74 -41
  28. package/dist/index.js.map +10 -8
  29. package/docs/README.md +2 -2
  30. package/docs/guide/email-flows.md +60 -1
  31. package/docs/guide/errors.md +3 -3
  32. package/docs/guide/events.md +4 -4
  33. package/docs/guide/magic-link.md +7 -2
  34. package/docs/guide/sessions.md +37 -6
  35. package/docs/guide/users.md +70 -0
  36. package/docs/guide/vocabulary.md +1 -1
  37. package/docs/roadmap.md +16 -15
  38. package/docs/troubleshooting.md +56 -6
  39. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -612,6 +612,12 @@ function toUser(record) {
612
612
  };
613
613
  }
614
614
  var idOf = (user) => typeof user === "string" ? user : user.id;
615
+ function refId(user) {
616
+ if (typeof user === "string")
617
+ return user;
618
+ const id = typeof user === "object" && user !== null ? user.id : undefined;
619
+ return typeof id === "string" ? id : "";
620
+ }
615
621
 
616
622
  // src/auth/context/records.ts
617
623
  var notFound = (where, id, type) => new NotFoundError2(`${where}: no ${type ?? "user"} has this id`, type === null ? { userId: id, operation: where } : { userId: id, userType: type, operation: where });
@@ -1391,39 +1397,6 @@ async function confirmReset(context, type, secret, password, where) {
1391
1397
  return toUser(written);
1392
1398
  }
1393
1399
 
1394
- // src/auth/email-flows/verify-email.ts
1395
- function verifyEmailFlows(context, type, at) {
1396
- return {
1397
- async send(user) {
1398
- const where = at("verifyEmail.send");
1399
- const record = await getRecord(context, idOf(user), type.name, where);
1400
- await countMailByUser(context, type, "verifyEmail", record.id, where);
1401
- return issueEmailToken(context, type, "verifyEmail", record, where);
1402
- },
1403
- async confirm(secret) {
1404
- const where = at("verifyEmail.confirm");
1405
- const { token, user } = await redeemEmailToken(context, type, "verifyEmail", secret, where);
1406
- let newlyVerified = false;
1407
- const written = await writeUser(context, user.id, type, undefined, where, (record, now) => {
1408
- refuseStale(type, record, token, where, "token");
1409
- newlyVerified = record.emailVerifiedAt === null;
1410
- return { emailVerifiedAt: now };
1411
- });
1412
- if (newlyVerified) {
1413
- await emit(context, "user.emailVerified", written, written.updatedAt);
1414
- }
1415
- return toUser(written);
1416
- }
1417
- };
1418
- }
1419
-
1420
- // src/auth/email-flows/flows.ts
1421
- function emailFlows(context, type, at) {
1422
- return {
1423
- verifyEmail: verifyEmailFlows(context, type, at),
1424
- resetPassword: resetPasswordFlows(context, type, at)
1425
- };
1426
- }
1427
1400
  // src/auth/totp.ts
1428
1401
  import { createHmac as createHmac2, randomBytes as randomBytes5 } from "node:crypto";
1429
1402
  var TOTP = { digits: 6, stepMs: 30000, drift: 1 };
@@ -1558,6 +1531,59 @@ async function endWhatTheSquatterOpened(context, userId) {
1558
1531
  await endWhatThePasswordOpened(context, userId);
1559
1532
  }
1560
1533
 
1534
+ // src/auth/email-flows/prove-first.ts
1535
+ function proveFirstFlow(context, type, at) {
1536
+ return async (user) => {
1537
+ const where = at("verifyEmail.proveFirst");
1538
+ const record = await getRecord(context, refId(user), type.name, where);
1539
+ if (!record.active) {
1540
+ throw new UserInactiveError2(`${where}: the user is inactive`, {
1541
+ userId: record.id,
1542
+ userType: type.name
1543
+ });
1544
+ }
1545
+ if (record.emailVerifiedAt !== null) {
1546
+ return { user: toUser(record), proved: false };
1547
+ }
1548
+ const proved = await proveFirstEmail(context, type, record, where);
1549
+ return { user: toUser(proved), proved: true };
1550
+ };
1551
+ }
1552
+
1553
+ // src/auth/email-flows/verify-email.ts
1554
+ function verifyEmailFlows(context, type, at) {
1555
+ return {
1556
+ async send(user) {
1557
+ const where = at("verifyEmail.send");
1558
+ const record = await getRecord(context, idOf(user), type.name, where);
1559
+ await countMailByUser(context, type, "verifyEmail", record.id, where);
1560
+ return issueEmailToken(context, type, "verifyEmail", record, where);
1561
+ },
1562
+ async confirm(secret) {
1563
+ const where = at("verifyEmail.confirm");
1564
+ const { token, user } = await redeemEmailToken(context, type, "verifyEmail", secret, where);
1565
+ let newlyVerified = false;
1566
+ const written = await writeUser(context, user.id, type, undefined, where, (record, now) => {
1567
+ refuseStale(type, record, token, where, "token");
1568
+ newlyVerified = record.emailVerifiedAt === null;
1569
+ return { emailVerifiedAt: now };
1570
+ });
1571
+ if (newlyVerified) {
1572
+ await emit(context, "user.emailVerified", written, written.updatedAt);
1573
+ }
1574
+ return toUser(written);
1575
+ },
1576
+ proveFirst: proveFirstFlow(context, type, at)
1577
+ };
1578
+ }
1579
+
1580
+ // src/auth/email-flows/flows.ts
1581
+ function emailFlows(context, type, at) {
1582
+ return {
1583
+ verifyEmail: verifyEmailFlows(context, type, at),
1584
+ resetPassword: resetPasswordFlows(context, type, at)
1585
+ };
1586
+ }
1561
1587
  // src/auth/email-sign-in.ts
1562
1588
  async function signInHolder(context, type, email) {
1563
1589
  const record = await holderOfEmail(context, type, email);
@@ -1636,7 +1662,7 @@ function provenSignInFlows(context, type, at, finish) {
1636
1662
  async signInProven(user, options) {
1637
1663
  const where = at("signInProven");
1638
1664
  const device = deviceHint(context, options, where);
1639
- const record = await getRecord(context, idOf2(user), type.name, where);
1665
+ const record = await getRecord(context, refId(user), type.name, where);
1640
1666
  if (!record.active) {
1641
1667
  throw new UserInactiveError2(`${where}: the user is inactive`, {
1642
1668
  userId: record.id,
@@ -1649,12 +1675,6 @@ function provenSignInFlows(context, type, at, finish) {
1649
1675
  }
1650
1676
  };
1651
1677
  }
1652
- function idOf2(user) {
1653
- if (typeof user === "string")
1654
- return user;
1655
- const id = typeof user === "object" && user !== null ? user.id : undefined;
1656
- return typeof id === "string" ? id : "";
1657
- }
1658
1678
 
1659
1679
  // src/auth/sign-in-attempts.ts
1660
1680
  var PURPOSE3 = "janus/sign-in/attempts/v1";
@@ -2238,6 +2258,18 @@ async function confirmStepUp(context, type, request, secret, code, where) {
2238
2258
  return toSession(confirmed);
2239
2259
  }
2240
2260
 
2261
+ // src/auth/users/find-by-email.ts
2262
+ function findByEmailFlows(context, type) {
2263
+ return {
2264
+ async findByEmail(email) {
2265
+ if (typeof email !== "string" || email.trim() === "")
2266
+ return null;
2267
+ const record = await holderOfEmail(context, type, email);
2268
+ return record === null ? null : toUser(record);
2269
+ }
2270
+ };
2271
+ }
2272
+
2241
2273
  // src/auth/users/by-login.ts
2242
2274
  var byLogin = async (context, type, login) => isStorable(login) ? context.store.users.findUserByLogin(type.name, login) : null;
2243
2275
 
@@ -2527,6 +2559,7 @@ function typeApi(context, type) {
2527
2559
  signInCode,
2528
2560
  magicLink: magicLinkFlows(context, type, at, secondFactor.finish),
2529
2561
  stepUp: stepUpFlows(context, type, at),
2562
+ ...findByEmailFlows(context, type),
2530
2563
  ...emailFlows(context, type, at)
2531
2564
  };
2532
2565
  }
@@ -2615,5 +2648,5 @@ export {
2615
2648
  systemClock
2616
2649
  };
2617
2650
 
2618
- //# debugId=58DD1D230B6CE48B64756E2164756E21
2651
+ //# debugId=D104C8FB67042A0864756E2164756E21
2619
2652
  //# sourceMappingURL=index.js.map