better-auth-studio 1.0.79-beta.35 → 1.0.79-beta.36

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.
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/png" href="/logo.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Better Auth Studio</title>
8
- <script type="module" crossorigin src="/assets/main-DAv-RHMo.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/main-R1O9iElM.css">
8
+ <script type="module" crossorigin src="/assets/main-BxLtFscV.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/main-BgI41EAt.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAU9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AA0GnE,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAqLhG;AAeD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,GAAG,EACtB,oBAAoB,CAAC,EAAE,GAAG,EAC1B,YAAY,CAAC,EAAE,kBAAkB,EACjC,YAAY,CAAC,EAAE,GAAG,GACjB,MAAM,CA+6LR;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,GAAG,CAAC;IACV,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAChE,CAAC,CA+FD"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAU9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AA0GnE,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAqLhG;AAeD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,gBAAgB,CAAC,EAAE,GAAG,EACtB,oBAAoB,CAAC,EAAE,GAAG,EAC1B,YAAY,CAAC,EAAE,kBAAkB,EACjC,YAAY,CAAC,EAAE,GAAG,GACjB,MAAM,CAkxMR;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,GAAG,CAAC;IACV,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;CAChE,CAAC,CA+FD"}
package/dist/routes.js CHANGED
@@ -320,6 +320,10 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
320
320
  // For self-hosted studio, wrap the preloaded adapter to match expected interface
321
321
  return {
322
322
  ...preloadedAdapter,
323
+ findUnique: preloadedAdapter.findUnique?.bind(preloadedAdapter),
324
+ findOne: preloadedAdapter.findOne?.bind(preloadedAdapter) ||
325
+ preloadedAdapter.findUnique?.bind(preloadedAdapter),
326
+ findFirst: preloadedAdapter.findFirst?.bind(preloadedAdapter),
323
327
  findMany: preloadedAdapter.findMany?.bind(preloadedAdapter),
324
328
  create: preloadedAdapter.create?.bind(preloadedAdapter),
325
329
  update: preloadedAdapter.update?.bind(preloadedAdapter),
@@ -2731,6 +2735,238 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
2731
2735
  res.status(500).json({ error: 'Failed to resend invitation' });
2732
2736
  }
2733
2737
  });
2738
+ router.get('/api/users/:userId/invitations', async (req, res) => {
2739
+ try {
2740
+ const { userId } = req.params;
2741
+ const adapter = await getAuthAdapterWithConfig();
2742
+ if (!adapter) {
2743
+ return res.status(500).json({ error: 'Auth adapter not available' });
2744
+ }
2745
+ let user;
2746
+ try {
2747
+ user = await adapter.findOne({
2748
+ model: 'user',
2749
+ where: [{ field: 'id', value: userId }],
2750
+ });
2751
+ }
2752
+ catch (error) {
2753
+ console.error('Error fetching user:', error);
2754
+ return res.status(500).json({
2755
+ error: 'Failed to fetch user',
2756
+ details: error?.message || String(error),
2757
+ });
2758
+ }
2759
+ if (!user || !user.email) {
2760
+ return res.json({ success: true, invitations: [] });
2761
+ }
2762
+ if (typeof adapter.findMany !== 'function') {
2763
+ return res.json({ success: true, invitations: [] });
2764
+ }
2765
+ let invitations;
2766
+ try {
2767
+ invitations = await adapter.findMany({
2768
+ model: 'invitation',
2769
+ where: [{ field: 'email', value: user.email }],
2770
+ });
2771
+ }
2772
+ catch (error) {
2773
+ console.error('Error fetching invitations:', error);
2774
+ return res.json({ success: true, invitations: [] });
2775
+ }
2776
+ if (!invitations || invitations.length === 0) {
2777
+ return res.json({ success: true, invitations: [] });
2778
+ }
2779
+ const transformedInvitations = await Promise.all(invitations.map(async (invitation) => {
2780
+ let organizationName = 'Unknown';
2781
+ let teamName;
2782
+ try {
2783
+ if (invitation.organizationId &&
2784
+ (typeof adapter.findOne === 'function' || typeof adapter.findUnique === 'function')) {
2785
+ try {
2786
+ const findMethod = adapter.findOne || adapter.findUnique;
2787
+ const org = await findMethod({
2788
+ model: 'organization',
2789
+ where: [{ field: 'id', value: invitation.organizationId }],
2790
+ });
2791
+ organizationName = org?.name || 'Unknown';
2792
+ }
2793
+ catch (_orgError) {
2794
+ // Ignore org fetch errors
2795
+ }
2796
+ }
2797
+ if (invitation.teamId &&
2798
+ (typeof adapter.findOne === 'function' || typeof adapter.findUnique === 'function')) {
2799
+ try {
2800
+ const findMethod = adapter.findOne || adapter.findUnique;
2801
+ const team = await findMethod({
2802
+ model: 'team',
2803
+ where: [{ field: 'id', value: invitation.teamId }],
2804
+ });
2805
+ teamName = team?.name;
2806
+ }
2807
+ catch (_teamError) { }
2808
+ }
2809
+ }
2810
+ catch (_error) { }
2811
+ return {
2812
+ id: invitation.id,
2813
+ email: invitation.email,
2814
+ role: invitation.role || 'member',
2815
+ status: invitation.status || 'pending',
2816
+ organizationId: invitation.organizationId,
2817
+ organizationName,
2818
+ teamId: invitation.teamId,
2819
+ teamName,
2820
+ inviterId: invitation.inviterId,
2821
+ expiresAt: invitation.expiresAt,
2822
+ createdAt: invitation.createdAt,
2823
+ };
2824
+ }));
2825
+ res.json({ success: true, invitations: transformedInvitations });
2826
+ }
2827
+ catch (error) {
2828
+ console.error('Error in /api/users/:userId/invitations:', error);
2829
+ res.status(500).json({
2830
+ error: 'Failed to fetch invitations',
2831
+ details: error?.message || String(error),
2832
+ });
2833
+ }
2834
+ });
2835
+ router.post('/api/invitations/:id/accept', async (req, res) => {
2836
+ try {
2837
+ const { id } = req.params;
2838
+ const { userId } = req.body;
2839
+ const adapter = await getAuthAdapterWithConfig();
2840
+ if (!adapter) {
2841
+ return res.status(500).json({ error: 'Auth adapter not available' });
2842
+ }
2843
+ if (!userId) {
2844
+ return res.status(400).json({ error: 'User ID is required' });
2845
+ }
2846
+ const invitation = await adapter.findOne({
2847
+ model: 'invitation',
2848
+ where: [{ field: 'id', value: id }],
2849
+ });
2850
+ if (!invitation) {
2851
+ return res.status(404).json({ error: 'Invitation not found' });
2852
+ }
2853
+ if (invitation.status !== 'pending') {
2854
+ return res.status(400).json({ error: 'Invitation is not pending' });
2855
+ }
2856
+ await adapter.update({
2857
+ model: 'invitation',
2858
+ where: [{ field: 'id', value: id }],
2859
+ update: {
2860
+ status: 'accepted',
2861
+ updatedAt: new Date().toISOString(),
2862
+ },
2863
+ });
2864
+ if (invitation.organizationId) {
2865
+ try {
2866
+ // Check if member already exists
2867
+ let existingMember = null;
2868
+ if (typeof adapter.findFirst === 'function') {
2869
+ existingMember = await adapter.findFirst({
2870
+ model: 'member',
2871
+ where: [
2872
+ { field: 'organizationId', value: invitation.organizationId },
2873
+ { field: 'userId', value: userId },
2874
+ ],
2875
+ });
2876
+ }
2877
+ else if (typeof adapter.findMany === 'function') {
2878
+ const members = await adapter.findMany({
2879
+ model: 'member',
2880
+ where: [
2881
+ { field: 'organizationId', value: invitation.organizationId },
2882
+ { field: 'userId', value: userId },
2883
+ ],
2884
+ });
2885
+ existingMember = members && members.length > 0 ? members[0] : null;
2886
+ }
2887
+ if (!existingMember) {
2888
+ await adapter.create({
2889
+ model: 'member',
2890
+ data: {
2891
+ organizationId: invitation.organizationId,
2892
+ userId: userId,
2893
+ role: invitation.role || 'member',
2894
+ createdAt: new Date().toISOString(),
2895
+ },
2896
+ });
2897
+ }
2898
+ }
2899
+ catch (error) {
2900
+ console.error('Error creating member:', error);
2901
+ // Ignore errors creating membership
2902
+ }
2903
+ }
2904
+ if (invitation.teamId) {
2905
+ try {
2906
+ let existingMember = null;
2907
+ if (typeof adapter.findFirst === 'function') {
2908
+ existingMember = await adapter.findFirst({
2909
+ model: 'teamMember',
2910
+ where: [
2911
+ { field: 'teamId', value: invitation.teamId },
2912
+ { field: 'userId', value: userId },
2913
+ ],
2914
+ });
2915
+ }
2916
+ else if (typeof adapter.findMany === 'function') {
2917
+ const members = await adapter.findMany({
2918
+ model: 'teamMember',
2919
+ where: [
2920
+ { field: 'teamId', value: invitation.teamId },
2921
+ { field: 'userId', value: userId },
2922
+ ],
2923
+ });
2924
+ existingMember = members && members.length > 0 ? members[0] : null;
2925
+ }
2926
+ if (!existingMember) {
2927
+ await adapter.create({
2928
+ model: 'teamMember',
2929
+ data: {
2930
+ teamId: invitation.teamId,
2931
+ userId: userId,
2932
+ createdAt: new Date().toISOString(),
2933
+ },
2934
+ });
2935
+ }
2936
+ }
2937
+ catch (error) {
2938
+ console.error('Error creating team member:', error);
2939
+ // Ignore errors creating team membership
2940
+ }
2941
+ }
2942
+ res.json({ success: true });
2943
+ }
2944
+ catch (error) {
2945
+ console.error('Failed to accept invitation:', error);
2946
+ res.status(500).json({ error: 'Failed to accept invitation' });
2947
+ }
2948
+ });
2949
+ router.post('/api/invitations/:id/reject', async (req, res) => {
2950
+ try {
2951
+ const { id } = req.params;
2952
+ const adapter = await getAuthAdapterWithConfig();
2953
+ if (!adapter) {
2954
+ return res.status(500).json({ error: 'Auth adapter not available' });
2955
+ }
2956
+ await adapter.update({
2957
+ model: 'invitation',
2958
+ where: [{ field: 'id', value: id }],
2959
+ update: {
2960
+ status: 'rejected',
2961
+ updatedAt: new Date().toISOString(),
2962
+ },
2963
+ });
2964
+ res.json({ success: true });
2965
+ }
2966
+ catch (_error) {
2967
+ res.status(500).json({ error: 'Failed to reject invitation' });
2968
+ }
2969
+ });
2734
2970
  router.delete('/api/invitations/:id', async (req, res) => {
2735
2971
  try {
2736
2972
  const { id } = req.params;
@@ -3661,6 +3897,92 @@ export function createRoutes(authConfig, configPath, geoDbPath, preloadedAdapter
3661
3897
  res.status(500).json({ success: false, error: 'Failed to fetch OAuth providers' });
3662
3898
  }
3663
3899
  });
3900
+ router.get('/api/tools/oauth/credentials', async (req, res) => {
3901
+ try {
3902
+ const { provider, origin } = req.query;
3903
+ if (!provider || typeof provider !== 'string') {
3904
+ return res.status(400).json({
3905
+ success: false,
3906
+ error: 'Provider is required',
3907
+ });
3908
+ }
3909
+ if (!origin || typeof origin !== 'string') {
3910
+ return res.status(400).json({
3911
+ success: false,
3912
+ error: 'Origin is required',
3913
+ });
3914
+ }
3915
+ // TODO: Import getOAuthCredentials at the top of this file:
3916
+ // import { getOAuthCredentials } from './path/to/your/oauth-config';
3917
+ // For now, we'll access it from a function that should be provided
3918
+ // This assumes getOAuthCredentials is available in the scope
3919
+ // You need to import it: import { getOAuthCredentials } from './your-oauth-config-file';
3920
+ // Placeholder - replace this with actual import at top of file
3921
+ const getOAuthCredentials = global.getOAuthCredentials;
3922
+ if (typeof getOAuthCredentials !== 'function') {
3923
+ return res.status(500).json({
3924
+ success: false,
3925
+ error: 'OAuth credentials function not configured. Please import getOAuthCredentials function.',
3926
+ });
3927
+ }
3928
+ const credentialsResult = getOAuthCredentials(provider, origin);
3929
+ // Handle null return (provider not found)
3930
+ if (credentialsResult === null) {
3931
+ return res.status(404).json({
3932
+ success: false,
3933
+ error: 'No credential found',
3934
+ });
3935
+ }
3936
+ // Handle error cases with proper messages as requested
3937
+ if (credentialsResult.error) {
3938
+ if (credentialsResult.error === 'NO_CREDENTIALS_FOUND') {
3939
+ return res.status(404).json({
3940
+ success: false,
3941
+ error: 'No credential found',
3942
+ });
3943
+ }
3944
+ else if (credentialsResult.error === 'INVALID_ORIGIN') {
3945
+ return res.status(400).json({
3946
+ success: false,
3947
+ error: 'Invalid origin. OAuth credentials are only available for localhost origins.',
3948
+ });
3949
+ }
3950
+ else {
3951
+ return res.status(400).json({
3952
+ success: false,
3953
+ error: credentialsResult.error || 'Failed to get OAuth credentials',
3954
+ });
3955
+ }
3956
+ }
3957
+ // Check if result exists and has required fields
3958
+ if (!credentialsResult.result) {
3959
+ return res.status(404).json({
3960
+ success: false,
3961
+ error: 'No credential found',
3962
+ });
3963
+ }
3964
+ const { clientId, clientSecret } = credentialsResult.result;
3965
+ if (!clientId || !clientSecret) {
3966
+ return res.status(404).json({
3967
+ success: false,
3968
+ error: 'No credential found',
3969
+ });
3970
+ }
3971
+ res.json({
3972
+ success: true,
3973
+ clientId,
3974
+ clientSecret,
3975
+ });
3976
+ }
3977
+ catch (error) {
3978
+ console.error('Failed to fetch OAuth credentials:', error);
3979
+ res.status(500).json({
3980
+ success: false,
3981
+ error: 'Failed to fetch OAuth credentials',
3982
+ details: error instanceof Error ? error.message : String(error),
3983
+ });
3984
+ }
3985
+ });
3664
3986
  router.post('/api/tools/oauth/test', async (req, res) => {
3665
3987
  try {
3666
3988
  const { provider } = req.body;