@holo-js/auth-clerk 0.3.16 → 0.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +31 -219
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -58,7 +58,6 @@ function normalizeClerkRequest(input) {
|
|
|
58
58
|
// src/index.ts
|
|
59
59
|
var CLERK_RUNTIME_STATE_KEY = "__holoJsAuthClerkRuntime";
|
|
60
60
|
var clerkDefaultProviderRuntimeCache = /* @__PURE__ */ new Map();
|
|
61
|
-
var clerkIdentitySyncLocks = /* @__PURE__ */ new Map();
|
|
62
61
|
var AUTH_PROVIDER_MARKER = /* @__PURE__ */ Symbol.for("holo-js.auth.provider");
|
|
63
62
|
function getRuntimeState() {
|
|
64
63
|
const runtimeGlobal = globalThis;
|
|
@@ -345,19 +344,6 @@ function resolveGuardAndProvider(provider) {
|
|
|
345
344
|
adapter
|
|
346
345
|
};
|
|
347
346
|
}
|
|
348
|
-
function requireUserId(adapter, user, message) {
|
|
349
|
-
const userId = adapter.getId(user);
|
|
350
|
-
if (typeof userId !== "string" && typeof userId !== "number") {
|
|
351
|
-
throw new Error(message);
|
|
352
|
-
}
|
|
353
|
-
return userId;
|
|
354
|
-
}
|
|
355
|
-
function requireUserRecord(user, message) {
|
|
356
|
-
if (!user || typeof user !== "object") {
|
|
357
|
-
throw new Error(message);
|
|
358
|
-
}
|
|
359
|
-
return user;
|
|
360
|
-
}
|
|
361
347
|
function createClerkSessionPayload(authenticated, session) {
|
|
362
348
|
const user = authenticated.user;
|
|
363
349
|
return Object.freeze({
|
|
@@ -485,56 +471,6 @@ function normalizeHostedProfile(profile) {
|
|
|
485
471
|
raw: profile.raw
|
|
486
472
|
});
|
|
487
473
|
}
|
|
488
|
-
async function findUserByEmail(adapter, email) {
|
|
489
|
-
const user = await adapter.findByCredentials({ email: email.trim() });
|
|
490
|
-
return user ? requireUserRecord(user, "[@holo-js/auth-clerk] Auth provider lookups must return object users.") : null;
|
|
491
|
-
}
|
|
492
|
-
async function updateLocalUser(adapter, user, input) {
|
|
493
|
-
const current = user;
|
|
494
|
-
const changed = Object.entries(input).some(([key, value]) => {
|
|
495
|
-
if (key === "email_verified_at") {
|
|
496
|
-
return value instanceof Date && !current.email_verified_at;
|
|
497
|
-
}
|
|
498
|
-
return !Object.is(value, user[key]);
|
|
499
|
-
});
|
|
500
|
-
if (!changed) {
|
|
501
|
-
return { user, changed: false };
|
|
502
|
-
}
|
|
503
|
-
if (adapter.update) {
|
|
504
|
-
return {
|
|
505
|
-
user: requireUserRecord(
|
|
506
|
-
await adapter.update(user, input),
|
|
507
|
-
"[@holo-js/auth-clerk] Auth provider updates must return object users."
|
|
508
|
-
),
|
|
509
|
-
changed: true
|
|
510
|
-
};
|
|
511
|
-
}
|
|
512
|
-
throw new Error(
|
|
513
|
-
"[@holo-js/auth-clerk] Auth provider adapters must implement update() to persist profile changes."
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
|
-
async function ensureNoUnexpectedEmailCollision(adapter, providerName, profile, currentUserId) {
|
|
517
|
-
const resolvedEmail = resolvePrimaryEmail(profile).email;
|
|
518
|
-
if (!resolvedEmail) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
const matched = await findUserByEmail(adapter, resolvedEmail);
|
|
522
|
-
if (!matched) {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
if (requireUserId(
|
|
526
|
-
adapter,
|
|
527
|
-
matched,
|
|
528
|
-
"[@holo-js/auth-clerk] Matched local users must expose a serializable id."
|
|
529
|
-
) !== currentUserId) {
|
|
530
|
-
throw new ClerkAuthConflictError({
|
|
531
|
-
provider: providerName,
|
|
532
|
-
clerkUserId: profile.id,
|
|
533
|
-
email: resolvedEmail,
|
|
534
|
-
message: `[@holo-js/auth-clerk] Clerk email "${resolvedEmail}" collides with a different local user.`
|
|
535
|
-
});
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
474
|
function isEmailVerificationRequired() {
|
|
539
475
|
return authRuntimeInternals3.getRuntimeBindings().config.emailVerification.required === true;
|
|
540
476
|
}
|
|
@@ -554,47 +490,6 @@ function createIdentityRecord(input) {
|
|
|
554
490
|
updatedAt: now
|
|
555
491
|
});
|
|
556
492
|
}
|
|
557
|
-
async function withIdentitySyncLock(key, callback) {
|
|
558
|
-
const previous = clerkIdentitySyncLocks.get(key) ?? Promise.resolve();
|
|
559
|
-
let release;
|
|
560
|
-
const gate = new Promise((resolve) => {
|
|
561
|
-
release = resolve;
|
|
562
|
-
});
|
|
563
|
-
const current = previous.then(() => gate);
|
|
564
|
-
clerkIdentitySyncLocks.set(key, current);
|
|
565
|
-
await previous;
|
|
566
|
-
try {
|
|
567
|
-
return await callback();
|
|
568
|
-
} finally {
|
|
569
|
-
release();
|
|
570
|
-
if (clerkIdentitySyncLocks.get(key) === current) {
|
|
571
|
-
clerkIdentitySyncLocks.delete(key);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
async function claimNewIdentity(identityStore, identity) {
|
|
576
|
-
if (identityStore.claim) {
|
|
577
|
-
return await identityStore.claim(identity);
|
|
578
|
-
}
|
|
579
|
-
await identityStore.save(identity);
|
|
580
|
-
return identity;
|
|
581
|
-
}
|
|
582
|
-
function sameUserId(left, right) {
|
|
583
|
-
return String(left) === String(right);
|
|
584
|
-
}
|
|
585
|
-
async function resolveClaimedIdentityUser(adapter, identity, fallback) {
|
|
586
|
-
if (sameUserId(identity.userId, fallback.userId)) {
|
|
587
|
-
return fallback.user;
|
|
588
|
-
}
|
|
589
|
-
const claimedUser = requireUserRecord(
|
|
590
|
-
await adapter.findById(identity.userId),
|
|
591
|
-
"[@holo-js/auth-clerk] Claimed Clerk identities must reference an existing local user."
|
|
592
|
-
);
|
|
593
|
-
if (adapter.delete) {
|
|
594
|
-
await adapter.delete(fallback.userId);
|
|
595
|
-
}
|
|
596
|
-
return claimedUser;
|
|
597
|
-
}
|
|
598
493
|
function getSessionTokenFromRequest(request, sessionCookie) {
|
|
599
494
|
const authorization = request.headers.get("authorization")?.trim();
|
|
600
495
|
if (authorization) {
|
|
@@ -803,124 +698,41 @@ async function syncIdentity(session, provider, options = {}) {
|
|
|
803
698
|
if (verificationRequired && !verifiedEmail) {
|
|
804
699
|
throw new Error(`[@holo-js/auth-clerk] Clerk identity "${profile.id}" must provide a verified email address.`);
|
|
805
700
|
}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
message: `[@holo-js/auth-clerk] Clerk email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
linkedUser = requireUserRecord(
|
|
823
|
-
await adapter.create(resolveCreateUserInput(profile, options.user)),
|
|
824
|
-
"[@holo-js/auth-clerk] Auth provider create() must return an object user."
|
|
825
|
-
);
|
|
826
|
-
const relinked = await updateLocalUser(adapter, linkedUser, resolveUpdateUserInput(profile, options.user));
|
|
827
|
-
const relinkedUser = relinked.user;
|
|
828
|
-
const identity3 = createIdentityRecord({
|
|
829
|
-
provider: providerName,
|
|
830
|
-
guard,
|
|
831
|
-
authProvider,
|
|
832
|
-
userId: requireUserId(
|
|
833
|
-
adapter,
|
|
834
|
-
relinkedUser,
|
|
835
|
-
"[@holo-js/auth-clerk] Relinked local users must expose a serializable id."
|
|
836
|
-
),
|
|
837
|
-
profile,
|
|
838
|
-
previous: existingIdentity
|
|
839
|
-
});
|
|
840
|
-
await identityStore.save(identity3);
|
|
841
|
-
return Object.freeze({
|
|
842
|
-
provider: providerName,
|
|
843
|
-
guard,
|
|
844
|
-
authProvider,
|
|
845
|
-
status: "relinked",
|
|
846
|
-
user: serializeLocalUser(adapter, relinkedUser, authProvider),
|
|
847
|
-
identity: identity3,
|
|
848
|
-
session
|
|
849
|
-
});
|
|
850
|
-
}
|
|
851
|
-
await ensureNoUnexpectedEmailCollision(
|
|
852
|
-
adapter,
|
|
853
|
-
providerName,
|
|
854
|
-
profile,
|
|
855
|
-
requireUserId(
|
|
856
|
-
adapter,
|
|
857
|
-
linkedUser,
|
|
858
|
-
"[@holo-js/auth-clerk] Linked local users must expose a serializable id."
|
|
859
|
-
)
|
|
860
|
-
);
|
|
861
|
-
const updated = await updateLocalUser(adapter, linkedUser, resolveUpdateUserInput(profile, options.user));
|
|
862
|
-
const identity2 = createIdentityRecord({
|
|
863
|
-
provider: providerName,
|
|
864
|
-
guard,
|
|
865
|
-
authProvider,
|
|
866
|
-
userId: requireUserId(
|
|
867
|
-
adapter,
|
|
868
|
-
updated.user,
|
|
869
|
-
"[@holo-js/auth-clerk] Updated local users must expose a serializable id."
|
|
870
|
-
),
|
|
871
|
-
profile,
|
|
872
|
-
previous: existingIdentity
|
|
873
|
-
});
|
|
874
|
-
await identityStore.save(identity2);
|
|
875
|
-
return Object.freeze({
|
|
876
|
-
provider: providerName,
|
|
877
|
-
guard,
|
|
878
|
-
authProvider,
|
|
879
|
-
status: updated.changed ? "updated" : "linked",
|
|
880
|
-
user: serializeLocalUser(adapter, updated.user, authProvider),
|
|
881
|
-
identity: identity2,
|
|
882
|
-
session
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
let localUser = verifiedEmail ? await findUserByEmail(adapter, verifiedEmail) : null;
|
|
886
|
-
if (localUser) {
|
|
887
|
-
throw new ClerkAuthConflictError({
|
|
888
|
-
provider: providerName,
|
|
889
|
-
clerkUserId: profile.id,
|
|
890
|
-
email: verifiedEmail,
|
|
891
|
-
message: `[@holo-js/auth-clerk] Clerk email "${verifiedEmail}" matches an existing local user and must be linked explicitly.`
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
localUser = requireUserRecord(
|
|
895
|
-
await adapter.create(resolveCreateUserInput(profile, options.user)),
|
|
896
|
-
"[@holo-js/auth-clerk] Auth provider create() must return an object user."
|
|
897
|
-
);
|
|
898
|
-
const identity = createIdentityRecord({
|
|
701
|
+
const synchronized = await authRuntimeInternals3.syncHostedIdentity({
|
|
702
|
+
provider: providerName,
|
|
703
|
+
providerUserId: profile.id,
|
|
704
|
+
adapter,
|
|
705
|
+
identityStore: getBindings().identityStore,
|
|
706
|
+
ownership: "serialized-claim",
|
|
707
|
+
verifiedEmail,
|
|
708
|
+
email: resolvedEmail.email,
|
|
709
|
+
errorPrefix: "[@holo-js/auth-clerk]",
|
|
710
|
+
identityLabel: "Clerk",
|
|
711
|
+
createUserInput: () => resolveCreateUserInput(profile, options.user),
|
|
712
|
+
updateUserInput: () => resolveUpdateUserInput(profile, options.user),
|
|
713
|
+
createIdentity: (userId, previous) => createIdentityRecord({
|
|
899
714
|
provider: providerName,
|
|
900
715
|
guard,
|
|
901
716
|
authProvider,
|
|
902
|
-
userId
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
profile
|
|
908
|
-
});
|
|
909
|
-
const claimedIdentity = await claimNewIdentity(identityStore, identity);
|
|
910
|
-
const claimedUser = await resolveClaimedIdentityUser(adapter, claimedIdentity, {
|
|
911
|
-
user: localUser,
|
|
912
|
-
userId: identity.userId
|
|
913
|
-
});
|
|
914
|
-
const claimedStatus = sameUserId(claimedIdentity.userId, identity.userId) ? "created" : "linked";
|
|
915
|
-
return Object.freeze({
|
|
717
|
+
userId,
|
|
718
|
+
profile,
|
|
719
|
+
previous
|
|
720
|
+
}),
|
|
721
|
+
conflict: (email, collision) => new ClerkAuthConflictError({
|
|
916
722
|
provider: providerName,
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
723
|
+
clerkUserId: profile.id,
|
|
724
|
+
email,
|
|
725
|
+
message: collision ? `[@holo-js/auth-clerk] Clerk email "${email}" collides with a different local user.` : `[@holo-js/auth-clerk] Clerk email "${email}" matches an existing local user and must be linked explicitly.`
|
|
726
|
+
})
|
|
727
|
+
});
|
|
728
|
+
return Object.freeze({
|
|
729
|
+
provider: providerName,
|
|
730
|
+
guard,
|
|
731
|
+
authProvider,
|
|
732
|
+
status: synchronized.status,
|
|
733
|
+
user: serializeLocalUser(adapter, synchronized.user, authProvider),
|
|
734
|
+
identity: synchronized.identity,
|
|
735
|
+
session
|
|
924
736
|
});
|
|
925
737
|
}
|
|
926
738
|
async function authenticate(input, provider) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holo-js/auth-clerk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.17",
|
|
4
4
|
"description": "Holo-JS Framework - Clerk auth integration contracts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@clerk/backend": "^3.4.7",
|
|
27
|
-
"@holo-js/auth": "^0.3.
|
|
28
|
-
"@holo-js/session": "^0.3.
|
|
27
|
+
"@holo-js/auth": "^0.3.17",
|
|
28
|
+
"@holo-js/session": "^0.3.17"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.2",
|