@blackcode_sa/metaestetics-api 1.14.2 → 1.14.4

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.d.mts CHANGED
@@ -8410,6 +8410,18 @@ declare class AuthService extends BaseService {
8410
8410
  user: User;
8411
8411
  practitioner: Practitioner;
8412
8412
  }>;
8413
+ /**
8414
+ * Claims draft practitioner profiles after Google Sign-In.
8415
+ * Similar to the token flow - creates User document and claims profiles in one transaction.
8416
+ *
8417
+ * @param idToken - The Google ID token
8418
+ * @param practitionerIds - Array of draft practitioner profile IDs to claim
8419
+ * @returns Object containing user and claimed practitioner
8420
+ */
8421
+ claimDraftProfilesWithGoogle(idToken: string, practitionerIds: string[]): Promise<{
8422
+ user: User;
8423
+ practitioner: Practitioner;
8424
+ }>;
8413
8425
  /**
8414
8426
  * Pre-validate all signup data before any mutations
8415
8427
  * Prevents partial creation by catching issues early
package/dist/index.d.ts CHANGED
@@ -8410,6 +8410,18 @@ declare class AuthService extends BaseService {
8410
8410
  user: User;
8411
8411
  practitioner: Practitioner;
8412
8412
  }>;
8413
+ /**
8414
+ * Claims draft practitioner profiles after Google Sign-In.
8415
+ * Similar to the token flow - creates User document and claims profiles in one transaction.
8416
+ *
8417
+ * @param idToken - The Google ID token
8418
+ * @param practitionerIds - Array of draft practitioner profile IDs to claim
8419
+ * @returns Object containing user and claimed practitioner
8420
+ */
8421
+ claimDraftProfilesWithGoogle(idToken: string, practitionerIds: string[]): Promise<{
8422
+ user: User;
8423
+ practitioner: Practitioner;
8424
+ }>;
8413
8425
  /**
8414
8426
  * Pre-validate all signup data before any mutations
8415
8427
  * Prevents partial creation by catching issues early
package/dist/index.js CHANGED
@@ -15908,6 +15908,83 @@ var AuthService = class extends BaseService {
15908
15908
  throw handleSignupError(error);
15909
15909
  }
15910
15910
  }
15911
+ /**
15912
+ * Claims draft practitioner profiles after Google Sign-In.
15913
+ * Similar to the token flow - creates User document and claims profiles in one transaction.
15914
+ *
15915
+ * @param idToken - The Google ID token
15916
+ * @param practitionerIds - Array of draft practitioner profile IDs to claim
15917
+ * @returns Object containing user and claimed practitioner
15918
+ */
15919
+ async claimDraftProfilesWithGoogle(idToken, practitionerIds) {
15920
+ try {
15921
+ console.log("[AUTH] Starting claim draft profiles with Google", {
15922
+ practitionerIdsCount: practitionerIds.length,
15923
+ practitionerIds
15924
+ });
15925
+ if (practitionerIds.length === 0) {
15926
+ throw new AuthError("No practitioner profiles selected to claim", "AUTH/NO_PROFILES_SELECTED", 400);
15927
+ }
15928
+ const credential = import_auth8.GoogleAuthProvider.credential(idToken);
15929
+ const { user: firebaseUser } = await (0, import_auth8.signInWithCredential)(this.auth, credential);
15930
+ console.log("[AUTH] Signed in with Google:", firebaseUser.uid);
15931
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
15932
+ let existingUser = null;
15933
+ try {
15934
+ existingUser = await this.userService.getUserById(firebaseUser.uid);
15935
+ console.log("[AUTH] User document already exists:", existingUser.uid);
15936
+ } catch (userError) {
15937
+ console.log("[AUTH] User document does not exist, will create it");
15938
+ }
15939
+ const transactionResult = await (0, import_firestore40.runTransaction)(this.db, async () => {
15940
+ console.log("[AUTH] Transaction started - creating user and claiming profiles");
15941
+ let user;
15942
+ if (existingUser) {
15943
+ user = existingUser;
15944
+ } else {
15945
+ console.log("[AUTH] Creating user document");
15946
+ user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
15947
+ skipProfileCreation: true
15948
+ });
15949
+ console.log("[AUTH] User document created:", user.uid);
15950
+ }
15951
+ let practitioner;
15952
+ if (practitionerIds.length === 1) {
15953
+ console.log("[AUTH] Claiming single draft profile");
15954
+ practitioner = await practitionerService.claimDraftProfileWithGoogle(
15955
+ practitionerIds[0],
15956
+ firebaseUser.uid
15957
+ );
15958
+ } else {
15959
+ console.log("[AUTH] Claiming multiple draft profiles");
15960
+ practitioner = await practitionerService.claimMultipleDraftProfilesWithGoogle(
15961
+ practitionerIds,
15962
+ firebaseUser.uid
15963
+ );
15964
+ }
15965
+ if (!user.practitionerProfile || user.practitionerProfile !== practitioner.id) {
15966
+ console.log("[AUTH] Linking practitioner to user");
15967
+ await this.userService.updateUser(firebaseUser.uid, {
15968
+ practitionerProfile: practitioner.id
15969
+ });
15970
+ }
15971
+ console.log("[AUTH] Transaction completed successfully");
15972
+ return { user, practitioner };
15973
+ });
15974
+ console.log("[AUTH] Draft profiles claimed successfully", {
15975
+ userId: transactionResult.user.uid,
15976
+ practitionerId: transactionResult.practitioner.id
15977
+ });
15978
+ const updatedUser = await this.userService.getUserById(firebaseUser.uid);
15979
+ return {
15980
+ user: updatedUser,
15981
+ practitioner: transactionResult.practitioner
15982
+ };
15983
+ } catch (error) {
15984
+ console.error("[AUTH] Error claiming draft profiles with Google:", error);
15985
+ throw handleSignupError(error);
15986
+ }
15987
+ }
15911
15988
  /**
15912
15989
  * Pre-validate all signup data before any mutations
15913
15990
  * Prevents partial creation by catching issues early
@@ -16117,30 +16194,14 @@ var AuthService = class extends BaseService {
16117
16194
  404
16118
16195
  );
16119
16196
  }
16120
- console.log("[AUTH] Draft profiles found, attempting to create user document");
16197
+ console.log("[AUTH] Draft profiles found, returning to client for selection");
16121
16198
  const draftProfilesFound = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16122
- try {
16123
- existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16124
- skipProfileCreation: true
16125
- });
16126
- console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
16127
- } catch (createError) {
16128
- console.error("[AUTH] Error creating user document:", {
16129
- error: createError,
16130
- code: createError == null ? void 0 : createError.code,
16131
- message: createError == null ? void 0 : createError.message
16132
- });
16133
- try {
16134
- await (0, import_auth8.signOut)(this.auth);
16135
- } catch (signOutError) {
16136
- console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
16137
- }
16138
- throw new AuthError(
16139
- "Unable to create account. Please use the token provided by your clinic to register, or contact support.",
16140
- "AUTH/USER_CREATION_FAILED",
16141
- 500
16142
- );
16143
- }
16199
+ return {
16200
+ user: null,
16201
+ // Will be created when claiming profiles
16202
+ practitioner: null,
16203
+ draftProfiles: draftProfilesFound
16204
+ };
16144
16205
  }
16145
16206
  if (!existingUser2) {
16146
16207
  await (0, import_auth8.signOut)(this.auth);
package/dist/index.mjs CHANGED
@@ -15995,6 +15995,83 @@ var AuthService = class extends BaseService {
15995
15995
  throw handleSignupError(error);
15996
15996
  }
15997
15997
  }
15998
+ /**
15999
+ * Claims draft practitioner profiles after Google Sign-In.
16000
+ * Similar to the token flow - creates User document and claims profiles in one transaction.
16001
+ *
16002
+ * @param idToken - The Google ID token
16003
+ * @param practitionerIds - Array of draft practitioner profile IDs to claim
16004
+ * @returns Object containing user and claimed practitioner
16005
+ */
16006
+ async claimDraftProfilesWithGoogle(idToken, practitionerIds) {
16007
+ try {
16008
+ console.log("[AUTH] Starting claim draft profiles with Google", {
16009
+ practitionerIdsCount: practitionerIds.length,
16010
+ practitionerIds
16011
+ });
16012
+ if (practitionerIds.length === 0) {
16013
+ throw new AuthError("No practitioner profiles selected to claim", "AUTH/NO_PROFILES_SELECTED", 400);
16014
+ }
16015
+ const credential = GoogleAuthProvider.credential(idToken);
16016
+ const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
16017
+ console.log("[AUTH] Signed in with Google:", firebaseUser.uid);
16018
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
16019
+ let existingUser = null;
16020
+ try {
16021
+ existingUser = await this.userService.getUserById(firebaseUser.uid);
16022
+ console.log("[AUTH] User document already exists:", existingUser.uid);
16023
+ } catch (userError) {
16024
+ console.log("[AUTH] User document does not exist, will create it");
16025
+ }
16026
+ const transactionResult = await runTransaction(this.db, async () => {
16027
+ console.log("[AUTH] Transaction started - creating user and claiming profiles");
16028
+ let user;
16029
+ if (existingUser) {
16030
+ user = existingUser;
16031
+ } else {
16032
+ console.log("[AUTH] Creating user document");
16033
+ user = await this.userService.createUser(firebaseUser, ["practitioner" /* PRACTITIONER */], {
16034
+ skipProfileCreation: true
16035
+ });
16036
+ console.log("[AUTH] User document created:", user.uid);
16037
+ }
16038
+ let practitioner;
16039
+ if (practitionerIds.length === 1) {
16040
+ console.log("[AUTH] Claiming single draft profile");
16041
+ practitioner = await practitionerService.claimDraftProfileWithGoogle(
16042
+ practitionerIds[0],
16043
+ firebaseUser.uid
16044
+ );
16045
+ } else {
16046
+ console.log("[AUTH] Claiming multiple draft profiles");
16047
+ practitioner = await practitionerService.claimMultipleDraftProfilesWithGoogle(
16048
+ practitionerIds,
16049
+ firebaseUser.uid
16050
+ );
16051
+ }
16052
+ if (!user.practitionerProfile || user.practitionerProfile !== practitioner.id) {
16053
+ console.log("[AUTH] Linking practitioner to user");
16054
+ await this.userService.updateUser(firebaseUser.uid, {
16055
+ practitionerProfile: practitioner.id
16056
+ });
16057
+ }
16058
+ console.log("[AUTH] Transaction completed successfully");
16059
+ return { user, practitioner };
16060
+ });
16061
+ console.log("[AUTH] Draft profiles claimed successfully", {
16062
+ userId: transactionResult.user.uid,
16063
+ practitionerId: transactionResult.practitioner.id
16064
+ });
16065
+ const updatedUser = await this.userService.getUserById(firebaseUser.uid);
16066
+ return {
16067
+ user: updatedUser,
16068
+ practitioner: transactionResult.practitioner
16069
+ };
16070
+ } catch (error) {
16071
+ console.error("[AUTH] Error claiming draft profiles with Google:", error);
16072
+ throw handleSignupError(error);
16073
+ }
16074
+ }
15998
16075
  /**
15999
16076
  * Pre-validate all signup data before any mutations
16000
16077
  * Prevents partial creation by catching issues early
@@ -16204,30 +16281,14 @@ var AuthService = class extends BaseService {
16204
16281
  404
16205
16282
  );
16206
16283
  }
16207
- console.log("[AUTH] Draft profiles found, attempting to create user document");
16284
+ console.log("[AUTH] Draft profiles found, returning to client for selection");
16208
16285
  const draftProfilesFound = await practitionerService2.getDraftProfilesByEmail(normalizedEmail);
16209
- try {
16210
- existingUser2 = await this.userService.createUser(firebaseUser2, ["practitioner" /* PRACTITIONER */], {
16211
- skipProfileCreation: true
16212
- });
16213
- console.log("[AUTH] Created user document for existing Firebase user with draft profiles:", existingUser2.uid);
16214
- } catch (createError) {
16215
- console.error("[AUTH] Error creating user document:", {
16216
- error: createError,
16217
- code: createError == null ? void 0 : createError.code,
16218
- message: createError == null ? void 0 : createError.message
16219
- });
16220
- try {
16221
- await firebaseSignOut(this.auth);
16222
- } catch (signOutError) {
16223
- console.warn("[AUTH] Error signing out Firebase user (non-critical):", signOutError);
16224
- }
16225
- throw new AuthError(
16226
- "Unable to create account. Please use the token provided by your clinic to register, or contact support.",
16227
- "AUTH/USER_CREATION_FAILED",
16228
- 500
16229
- );
16230
- }
16286
+ return {
16287
+ user: null,
16288
+ // Will be created when claiming profiles
16289
+ practitioner: null,
16290
+ draftProfiles: draftProfilesFound
16291
+ };
16231
16292
  }
16232
16293
  if (!existingUser2) {
16233
16294
  await firebaseSignOut(this.auth);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.14.2",
4
+ "version": "1.14.4",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -811,6 +811,109 @@ export class AuthService extends BaseService {
811
811
  }
812
812
  }
813
813
 
814
+ /**
815
+ * Claims draft practitioner profiles after Google Sign-In.
816
+ * Similar to the token flow - creates User document and claims profiles in one transaction.
817
+ *
818
+ * @param idToken - The Google ID token
819
+ * @param practitionerIds - Array of draft practitioner profile IDs to claim
820
+ * @returns Object containing user and claimed practitioner
821
+ */
822
+ async claimDraftProfilesWithGoogle(
823
+ idToken: string,
824
+ practitionerIds: string[]
825
+ ): Promise<{
826
+ user: User;
827
+ practitioner: Practitioner;
828
+ }> {
829
+ try {
830
+ console.log('[AUTH] Starting claim draft profiles with Google', {
831
+ practitionerIdsCount: practitionerIds.length,
832
+ practitionerIds,
833
+ });
834
+
835
+ if (practitionerIds.length === 0) {
836
+ throw new AuthError('No practitioner profiles selected to claim', 'AUTH/NO_PROFILES_SELECTED', 400);
837
+ }
838
+
839
+ // Sign in with Google credential
840
+ const credential = GoogleAuthProvider.credential(idToken);
841
+ const { user: firebaseUser } = await signInWithCredential(this.auth, credential);
842
+ console.log('[AUTH] Signed in with Google:', firebaseUser.uid);
843
+
844
+ const practitionerService = new PractitionerService(this.db, this.auth, this.app);
845
+
846
+ // Check if User document already exists
847
+ let existingUser: User | null = null;
848
+ try {
849
+ existingUser = await this.userService.getUserById(firebaseUser.uid);
850
+ console.log('[AUTH] User document already exists:', existingUser.uid);
851
+ } catch (userError) {
852
+ console.log('[AUTH] User document does not exist, will create it');
853
+ }
854
+
855
+ // Execute all operations in a transaction (similar to token flow)
856
+ const transactionResult = await runTransaction(this.db, async () => {
857
+ console.log('[AUTH] Transaction started - creating user and claiming profiles');
858
+
859
+ // Create user document if it doesn't exist
860
+ let user: User;
861
+ if (existingUser) {
862
+ user = existingUser;
863
+ } else {
864
+ console.log('[AUTH] Creating user document');
865
+ user = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
866
+ skipProfileCreation: true,
867
+ });
868
+ console.log('[AUTH] User document created:', user.uid);
869
+ }
870
+
871
+ // Claim the draft profiles
872
+ let practitioner: Practitioner;
873
+ if (practitionerIds.length === 1) {
874
+ console.log('[AUTH] Claiming single draft profile');
875
+ practitioner = await practitionerService.claimDraftProfileWithGoogle(
876
+ practitionerIds[0],
877
+ firebaseUser.uid
878
+ );
879
+ } else {
880
+ console.log('[AUTH] Claiming multiple draft profiles');
881
+ practitioner = await practitionerService.claimMultipleDraftProfilesWithGoogle(
882
+ practitionerIds,
883
+ firebaseUser.uid
884
+ );
885
+ }
886
+
887
+ // Link practitioner to user (if not already linked)
888
+ if (!user.practitionerProfile || user.practitionerProfile !== practitioner.id) {
889
+ console.log('[AUTH] Linking practitioner to user');
890
+ await this.userService.updateUser(firebaseUser.uid, {
891
+ practitionerProfile: practitioner.id,
892
+ });
893
+ }
894
+
895
+ console.log('[AUTH] Transaction completed successfully');
896
+ return { user, practitioner };
897
+ });
898
+
899
+ console.log('[AUTH] Draft profiles claimed successfully', {
900
+ userId: transactionResult.user.uid,
901
+ practitionerId: transactionResult.practitioner.id,
902
+ });
903
+
904
+ // Fetch updated user (with practitionerProfile reference)
905
+ const updatedUser = await this.userService.getUserById(firebaseUser.uid);
906
+
907
+ return {
908
+ user: updatedUser,
909
+ practitioner: transactionResult.practitioner,
910
+ };
911
+ } catch (error: any) {
912
+ console.error('[AUTH] Error claiming draft profiles with Google:', error);
913
+ throw handleSignupError(error);
914
+ }
915
+ }
916
+
814
917
  /**
815
918
  * Pre-validate all signup data before any mutations
816
919
  * Prevents partial creation by catching issues early
@@ -1099,35 +1202,19 @@ export class AuthService extends BaseService {
1099
1202
  );
1100
1203
  }
1101
1204
 
1102
- // Draft profiles exist - try to create User document
1103
- // Firestore rules should allow authenticated users to create their own User document
1104
- console.log('[AUTH] Draft profiles found, attempting to create user document');
1205
+ // Draft profiles exist - return them to client
1206
+ // User document creation will happen server-side when claiming profiles
1207
+ // This avoids permission issues with client-side User document creation
1208
+ console.log('[AUTH] Draft profiles found, returning to client for selection');
1105
1209
  const draftProfilesFound = await practitionerService.getDraftProfilesByEmail(normalizedEmail);
1106
1210
 
1107
- try {
1108
- existingUser = await this.userService.createUser(firebaseUser, [UserRole.PRACTITIONER], {
1109
- skipProfileCreation: true,
1110
- });
1111
- console.log('[AUTH] Created user document for existing Firebase user with draft profiles:', existingUser.uid);
1112
- } catch (createError: any) {
1113
- console.error('[AUTH] Error creating user document:', {
1114
- error: createError,
1115
- code: createError?.code,
1116
- message: createError?.message,
1117
- });
1118
- // If creation fails, sign out and throw error
1119
- // User will need to use token flow or contact support
1120
- try {
1121
- await firebaseSignOut(this.auth);
1122
- } catch (signOutError) {
1123
- console.warn('[AUTH] Error signing out Firebase user (non-critical):', signOutError);
1124
- }
1125
- throw new AuthError(
1126
- 'Unable to create account. Please use the token provided by your clinic to register, or contact support.',
1127
- 'AUTH/USER_CREATION_FAILED',
1128
- 500,
1129
- );
1130
- }
1211
+ // Return draft profiles without creating User document
1212
+ // The User document will be created server-side via Cloud Function when claiming profiles
1213
+ return {
1214
+ user: null, // Will be created when claiming profiles
1215
+ practitioner: null,
1216
+ draftProfiles: draftProfilesFound,
1217
+ };
1131
1218
  }
1132
1219
 
1133
1220
  // User document exists - check for practitioner profile and draft profiles