@holo-js/auth-workos 0.3.16 → 0.3.18

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 (2) hide show
  1. package/dist/index.mjs +23 -162
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -370,19 +370,6 @@ function resolveGuardAndProvider(provider) {
370
370
  adapter
371
371
  };
372
372
  }
373
- function requireUserId(adapter, user, message) {
374
- const userId = adapter.getId(user);
375
- if (typeof userId !== "string" && typeof userId !== "number") {
376
- throw new Error(message);
377
- }
378
- return userId;
379
- }
380
- function requireUserRecord(user, message) {
381
- if (!user || typeof user !== "object") {
382
- throw new Error(message);
383
- }
384
- return user;
385
- }
386
373
  function createWorkosSessionPayload(authenticated, session) {
387
374
  const user = authenticated.user;
388
375
  return Object.freeze({
@@ -497,56 +484,6 @@ function normalizeHostedProfile(profile) {
497
484
  raw: profile.raw
498
485
  });
499
486
  }
500
- async function findUserByEmail(adapter, email) {
501
- const user = await adapter.findByCredentials({ email: email.trim() });
502
- return user ? requireUserRecord(user, "[@holo-js/auth-workos] Auth provider lookups must return object users.") : null;
503
- }
504
- async function updateLocalUser(adapter, user, input) {
505
- const current = user;
506
- const changed = Object.entries(input).some(([key, value]) => {
507
- if (key === "email_verified_at") {
508
- return value instanceof Date && !current.email_verified_at;
509
- }
510
- return !Object.is(value, user[key]);
511
- });
512
- if (!changed) {
513
- return { user, changed: false };
514
- }
515
- if (adapter.update) {
516
- return {
517
- user: requireUserRecord(
518
- await adapter.update(user, input),
519
- "[@holo-js/auth-workos] Auth provider updates must return object users."
520
- ),
521
- changed: true
522
- };
523
- }
524
- throw new Error(
525
- "[@holo-js/auth-workos] Auth provider adapters must implement update() to persist profile changes."
526
- );
527
- }
528
- async function ensureNoUnexpectedEmailCollision(adapter, providerName, profile, currentUserId) {
529
- const email = profile.email.trim();
530
- if (!email) {
531
- return;
532
- }
533
- const matched = await findUserByEmail(adapter, email);
534
- if (!matched) {
535
- return;
536
- }
537
- if (requireUserId(
538
- adapter,
539
- matched,
540
- "[@holo-js/auth-workos] Matched local users must expose a serializable id."
541
- ) !== currentUserId) {
542
- throw new WorkosAuthConflictError({
543
- provider: providerName,
544
- workosUserId: profile.id,
545
- email,
546
- message: `[@holo-js/auth-workos] WorkOS email "${email}" collides with a different local user.`
547
- });
548
- }
549
- }
550
487
  function isEmailVerificationRequired() {
551
488
  return authRuntimeInternals.getRuntimeBindings().config.emailVerification.required === true;
552
489
  }
@@ -711,116 +648,40 @@ async function syncIdentity(session, provider, options = {}) {
711
648
  if (verificationRequired && !verifiedEmail) {
712
649
  throw new Error(`[@holo-js/auth-workos] WorkOS identity "${profile.id}" must provide a verified email address.`);
713
650
  }
714
- const identityStore = getBindings().identityStore;
715
- const existingIdentity = await identityStore.findByProviderUserId(providerName, profile.id);
716
- if (existingIdentity) {
717
- const existingLinkedUser = await adapter.findById(existingIdentity.userId);
718
- let linkedUser = existingLinkedUser ? requireUserRecord(existingLinkedUser, "[@holo-js/auth-workos] Auth provider lookups must return object users.") : null;
719
- if (!linkedUser) {
720
- const emailMatchedUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
721
- if (emailMatchedUser) {
722
- throw new WorkosAuthConflictError({
723
- provider: providerName,
724
- workosUserId: profile.id,
725
- email: verifiedEmail,
726
- message: `[@holo-js/auth-workos] WorkOS email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
727
- });
728
- }
729
- linkedUser = requireUserRecord(
730
- await adapter.create(resolveCreateUserInput(profile, options.user)),
731
- "[@holo-js/auth-workos] Auth provider create() must return an object user."
732
- );
733
- const relinked = await updateLocalUser(adapter, linkedUser, resolveUpdateUserInput(profile, options.user));
734
- const relinkedUser = relinked.user;
735
- const identity3 = createIdentityRecord({
736
- provider: providerName,
737
- guard,
738
- authProvider,
739
- userId: requireUserId(
740
- adapter,
741
- relinkedUser,
742
- "[@holo-js/auth-workos] Relinked local users must expose a serializable id."
743
- ),
744
- profile,
745
- previous: existingIdentity
746
- });
747
- await identityStore.save(identity3);
748
- return Object.freeze({
749
- provider: providerName,
750
- guard,
751
- authProvider,
752
- status: "relinked",
753
- user: serializeLocalUser(adapter, relinkedUser, authProvider),
754
- identity: identity3,
755
- session
756
- });
757
- }
758
- await ensureNoUnexpectedEmailCollision(
759
- adapter,
760
- providerName,
761
- profile,
762
- requireUserId(
763
- adapter,
764
- linkedUser,
765
- "[@holo-js/auth-workos] Linked local users must expose a serializable id."
766
- )
767
- );
768
- const updated = await updateLocalUser(adapter, linkedUser, resolveUpdateUserInput(profile, options.user));
769
- const identity2 = createIdentityRecord({
651
+ const synchronized = await authRuntimeInternals.syncHostedIdentity({
652
+ provider: providerName,
653
+ providerUserId: profile.id,
654
+ adapter,
655
+ identityStore: getBindings().identityStore,
656
+ ownership: "save",
657
+ verifiedEmail,
658
+ email: profileEmail,
659
+ errorPrefix: "[@holo-js/auth-workos]",
660
+ identityLabel: "WorkOS",
661
+ createUserInput: () => resolveCreateUserInput(profile, options.user),
662
+ updateUserInput: () => resolveUpdateUserInput(profile, options.user),
663
+ createIdentity: (userId, previous) => createIdentityRecord({
770
664
  provider: providerName,
771
665
  guard,
772
666
  authProvider,
773
- userId: requireUserId(
774
- adapter,
775
- updated.user,
776
- "[@holo-js/auth-workos] Updated local users must expose a serializable id."
777
- ),
667
+ userId,
778
668
  profile,
779
- previous: existingIdentity
780
- });
781
- await identityStore.save(identity2);
782
- return Object.freeze({
783
- provider: providerName,
784
- guard,
785
- authProvider,
786
- status: updated.changed ? "updated" : "linked",
787
- user: serializeLocalUser(adapter, updated.user, authProvider),
788
- identity: identity2,
789
- session
790
- });
791
- }
792
- let localUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
793
- if (localUser) {
794
- throw new WorkosAuthConflictError({
669
+ previous
670
+ }),
671
+ conflict: (email, collision) => new WorkosAuthConflictError({
795
672
  provider: providerName,
796
673
  workosUserId: profile.id,
797
- email: verifiedEmail,
798
- message: `[@holo-js/auth-workos] WorkOS email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
799
- });
800
- }
801
- localUser = requireUserRecord(
802
- await adapter.create(resolveCreateUserInput(profile, options.user)),
803
- "[@holo-js/auth-workos] Auth provider create() must return an object user."
804
- );
805
- const identity = createIdentityRecord({
806
- provider: providerName,
807
- guard,
808
- authProvider,
809
- userId: requireUserId(
810
- adapter,
811
- localUser,
812
- "[@holo-js/auth-workos] Created local users must expose a serializable id."
813
- ),
814
- profile
674
+ email,
675
+ message: collision ? `[@holo-js/auth-workos] WorkOS email "${email}" collides with a different local user.` : `[@holo-js/auth-workos] WorkOS email "${email}" matches an existing local user and must be linked explicitly.`
676
+ })
815
677
  });
816
- await identityStore.save(identity);
817
678
  return Object.freeze({
818
679
  provider: providerName,
819
680
  guard,
820
681
  authProvider,
821
- status: "created",
822
- user: serializeLocalUser(adapter, localUser, authProvider),
823
- identity,
682
+ status: synchronized.status,
683
+ user: serializeLocalUser(adapter, synchronized.user, authProvider),
684
+ identity: synchronized.identity,
824
685
  session
825
686
  });
826
687
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holo-js/auth-workos",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "Holo-JS Framework - WorkOS auth integration contracts",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,8 +23,8 @@
23
23
  "test": "vitest --run"
24
24
  },
25
25
  "dependencies": {
26
- "@holo-js/auth": "^0.3.16",
27
- "@holo-js/session": "^0.3.16"
26
+ "@holo-js/auth": "^0.3.18",
27
+ "@holo-js/session": "^0.3.18"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.10.2",