@ezcoder.dev/sdk 1.0.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.
- package/dist/analytics/index.d.ts +18 -0
- package/dist/analytics/index.js +76 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/animation/index.d.ts +172 -0
- package/dist/animation/index.js +81 -0
- package/dist/animation/index.js.map +1 -0
- package/dist/auth/index.d.ts +80 -0
- package/dist/auth/index.js +463 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/chunk-5XIZHBKE.js +372 -0
- package/dist/chunk-5XIZHBKE.js.map +1 -0
- package/dist/chunk-G7XDUN3Z.js +141 -0
- package/dist/chunk-G7XDUN3Z.js.map +1 -0
- package/dist/chunk-YNDCD53D.js +212 -0
- package/dist/chunk-YNDCD53D.js.map +1 -0
- package/dist/cms/index.d.ts +44 -0
- package/dist/cms/index.js +106 -0
- package/dist/cms/index.js.map +1 -0
- package/dist/errors/index.d.ts +20 -0
- package/dist/errors/index.js +61 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications/index.d.ts +30 -0
- package/dist/notifications/index.js +191 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/payments/index.d.ts +89 -0
- package/dist/payments/index.js +408 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/roles/index.d.ts +37 -0
- package/dist/roles/index.js +120 -0
- package/dist/roles/index.js.map +1 -0
- package/dist/seo/index.d.ts +39 -0
- package/dist/seo/index.js +89 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/server/index.d.ts +72 -0
- package/dist/server/index.js +191 -0
- package/dist/server/index.js.map +1 -0
- package/dist/storage/index.d.ts +52 -0
- package/dist/storage/index.js +212 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types-DtY5lp3P.d.ts +90 -0
- package/package.json +105 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ezcoder,
|
|
3
|
+
ezcoderAuthIntegration
|
|
4
|
+
} from "./chunk-5XIZHBKE.js";
|
|
5
|
+
import {
|
|
6
|
+
isSupabaseConfigured,
|
|
7
|
+
supabase
|
|
8
|
+
} from "./chunk-G7XDUN3Z.js";
|
|
9
|
+
|
|
10
|
+
// src/auth/AuthProvider.tsx
|
|
11
|
+
import { createContext, useContext, useState, useEffect, useCallback, useRef } from "react";
|
|
12
|
+
import { jsx } from "react/jsx-runtime";
|
|
13
|
+
var NOT_CONFIGURED_MSG = "Authentication is not configured. Connect a Supabase database in Settings \u2192 Databases to enable login and signup.";
|
|
14
|
+
function notConfiguredError() {
|
|
15
|
+
return new Error(NOT_CONFIGURED_MSG);
|
|
16
|
+
}
|
|
17
|
+
var AuthContext = createContext({
|
|
18
|
+
user: null,
|
|
19
|
+
profile: null,
|
|
20
|
+
session: null,
|
|
21
|
+
loading: true,
|
|
22
|
+
isConfigured: false,
|
|
23
|
+
signUp: async () => ({ data: null, error: null }),
|
|
24
|
+
signIn: async () => ({ data: null, error: null }),
|
|
25
|
+
signInWithProvider: async () => ({ data: null, error: null }),
|
|
26
|
+
signOut: async () => ({ error: null }),
|
|
27
|
+
resetPassword: async () => ({ data: null, error: null }),
|
|
28
|
+
updateProfile: async () => ({ data: null, error: null }),
|
|
29
|
+
refetchProfile: async () => null
|
|
30
|
+
});
|
|
31
|
+
function AuthProvider({ children }) {
|
|
32
|
+
const [user, setUser] = useState(null);
|
|
33
|
+
const [profile, setProfile] = useState(null);
|
|
34
|
+
const [session, setSession] = useState(null);
|
|
35
|
+
const [loading, setLoading] = useState(true);
|
|
36
|
+
const previousUserIdRef = useRef(null);
|
|
37
|
+
const fetchProfile = useCallback(async (userId) => {
|
|
38
|
+
if (!userId) return null;
|
|
39
|
+
try {
|
|
40
|
+
const result = await supabase.from("user_profiles").select("*").eq("id", userId).single();
|
|
41
|
+
const { data, error } = result || { data: null, error: null };
|
|
42
|
+
if (error) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
setProfile(data);
|
|
46
|
+
return data;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
supabase.auth.getSession().then(async ({ data: { session: initialSession } }) => {
|
|
53
|
+
setSession(initialSession);
|
|
54
|
+
setUser(initialSession?.user ?? null);
|
|
55
|
+
if (initialSession?.user) {
|
|
56
|
+
await fetchProfile(initialSession.user.id);
|
|
57
|
+
}
|
|
58
|
+
setLoading(false);
|
|
59
|
+
});
|
|
60
|
+
const {
|
|
61
|
+
data: { subscription }
|
|
62
|
+
} = supabase.auth.onAuthStateChange(async (event, currentSession) => {
|
|
63
|
+
setSession(currentSession);
|
|
64
|
+
setUser(currentSession?.user ?? null);
|
|
65
|
+
if (event === "SIGNED_IN" && currentSession?.user) {
|
|
66
|
+
await fetchProfile(currentSession.user.id);
|
|
67
|
+
ezcoderAuthIntegration.onLogin(currentSession.user);
|
|
68
|
+
previousUserIdRef.current = currentSession.user.id;
|
|
69
|
+
} else if (event === "SIGNED_OUT") {
|
|
70
|
+
setProfile(null);
|
|
71
|
+
if (previousUserIdRef.current) {
|
|
72
|
+
ezcoderAuthIntegration.onLogout(previousUserIdRef.current);
|
|
73
|
+
previousUserIdRef.current = null;
|
|
74
|
+
}
|
|
75
|
+
} else if (event === "USER_UPDATED" && currentSession?.user) {
|
|
76
|
+
ezcoder.analytics.identify(currentSession.user.id, {
|
|
77
|
+
email: currentSession.user.email,
|
|
78
|
+
name: currentSession.user.user_metadata?.full_name
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
return () => subscription.unsubscribe();
|
|
83
|
+
}, [fetchProfile]);
|
|
84
|
+
const signUp = useCallback(async (email, password, options = {}) => {
|
|
85
|
+
if (!isSupabaseConfigured) {
|
|
86
|
+
return { data: null, error: notConfiguredError() };
|
|
87
|
+
}
|
|
88
|
+
const { metadata = {} } = options;
|
|
89
|
+
try {
|
|
90
|
+
const result = await supabase.auth.signUp({
|
|
91
|
+
email,
|
|
92
|
+
password,
|
|
93
|
+
options: { data: metadata }
|
|
94
|
+
});
|
|
95
|
+
const { data, error } = result || { data: null, error: new Error("Sign up failed") };
|
|
96
|
+
if (error) {
|
|
97
|
+
return { data: null, error };
|
|
98
|
+
}
|
|
99
|
+
if (data?.user) {
|
|
100
|
+
if (metadata.display_name) {
|
|
101
|
+
await supabase.from("user_profiles").upsert({
|
|
102
|
+
id: data.user.id,
|
|
103
|
+
email,
|
|
104
|
+
display_name: metadata.display_name
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
ezcoderAuthIntegration.onSignup(data.user);
|
|
108
|
+
}
|
|
109
|
+
return { data, error: null };
|
|
110
|
+
} catch (err) {
|
|
111
|
+
return { data: null, error: err instanceof Error ? err : new Error("Sign up failed") };
|
|
112
|
+
}
|
|
113
|
+
}, []);
|
|
114
|
+
const signIn = useCallback(async (email, password) => {
|
|
115
|
+
if (!isSupabaseConfigured) {
|
|
116
|
+
return { data: null, error: notConfiguredError() };
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const result = await supabase.auth.signInWithPassword({ email, password });
|
|
120
|
+
const { data, error } = result || { data: null, error: new Error("Sign in failed") };
|
|
121
|
+
return { data, error };
|
|
122
|
+
} catch (err) {
|
|
123
|
+
return { data: null, error: err instanceof Error ? err : new Error("Sign in failed") };
|
|
124
|
+
}
|
|
125
|
+
}, []);
|
|
126
|
+
const signInWithProvider = useCallback(async (provider, options = {}) => {
|
|
127
|
+
if (!isSupabaseConfigured) {
|
|
128
|
+
return { data: null, error: notConfiguredError() };
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const result = await supabase.auth.signInWithOAuth({
|
|
132
|
+
provider,
|
|
133
|
+
options: {
|
|
134
|
+
redirectTo: options.redirectTo || (typeof window !== "undefined" ? window.location.origin : ""),
|
|
135
|
+
...options
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
const { data, error } = result || { data: null, error: new Error("OAuth sign in failed") };
|
|
139
|
+
return { data, error };
|
|
140
|
+
} catch (err) {
|
|
141
|
+
return { data: null, error: err instanceof Error ? err : new Error("OAuth sign in failed") };
|
|
142
|
+
}
|
|
143
|
+
}, []);
|
|
144
|
+
const signOut = useCallback(async () => {
|
|
145
|
+
const userId = user?.id;
|
|
146
|
+
try {
|
|
147
|
+
const result = await supabase.auth.signOut();
|
|
148
|
+
const { error } = result || { error: null };
|
|
149
|
+
if (!error && userId) {
|
|
150
|
+
ezcoder.users.trackLogout(userId);
|
|
151
|
+
}
|
|
152
|
+
return { error };
|
|
153
|
+
} catch (err) {
|
|
154
|
+
return { error: err instanceof Error ? err : new Error("Sign out failed") };
|
|
155
|
+
}
|
|
156
|
+
}, [user]);
|
|
157
|
+
const resetPassword = useCallback(async (email) => {
|
|
158
|
+
try {
|
|
159
|
+
const result = await supabase.auth.resetPasswordForEmail(email, {
|
|
160
|
+
redirectTo: `${typeof window !== "undefined" ? window.location.origin : ""}/auth/reset-password`
|
|
161
|
+
});
|
|
162
|
+
const { data, error } = result || { data: null, error: new Error("Password reset failed") };
|
|
163
|
+
return { data, error };
|
|
164
|
+
} catch (err) {
|
|
165
|
+
return { data: null, error: err instanceof Error ? err : new Error("Password reset failed") };
|
|
166
|
+
}
|
|
167
|
+
}, []);
|
|
168
|
+
const updateProfile = useCallback(
|
|
169
|
+
async (updates) => {
|
|
170
|
+
if (!user) {
|
|
171
|
+
return { data: null, error: new Error("Not authenticated") };
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const result = await supabase.from("user_profiles").update(updates).eq("id", user.id).select().single();
|
|
175
|
+
const { data, error } = result || { data: null, error: null };
|
|
176
|
+
return { data, error };
|
|
177
|
+
} catch (err) {
|
|
178
|
+
return { data: null, error: err instanceof Error ? err : new Error("Update failed") };
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
[user]
|
|
182
|
+
);
|
|
183
|
+
const value = {
|
|
184
|
+
user,
|
|
185
|
+
profile,
|
|
186
|
+
session,
|
|
187
|
+
loading,
|
|
188
|
+
isConfigured: isSupabaseConfigured,
|
|
189
|
+
signUp,
|
|
190
|
+
signIn,
|
|
191
|
+
signInWithProvider,
|
|
192
|
+
signOut,
|
|
193
|
+
resetPassword,
|
|
194
|
+
updateProfile,
|
|
195
|
+
refetchProfile: fetchProfile
|
|
196
|
+
};
|
|
197
|
+
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
198
|
+
}
|
|
199
|
+
function useAuth() {
|
|
200
|
+
const context = useContext(AuthContext);
|
|
201
|
+
if (context === void 0) {
|
|
202
|
+
throw new Error("useAuth must be used within an AuthProvider");
|
|
203
|
+
}
|
|
204
|
+
return context;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
AuthContext,
|
|
209
|
+
AuthProvider,
|
|
210
|
+
useAuth
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=chunk-YNDCD53D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth/AuthProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\nimport type { User, Session } from '@supabase/supabase-js';\nimport { supabase, isSupabaseConfigured } from '../core/supabase';\nimport { ezcoder, ezcoderAuthIntegration } from '../core/platform';\nimport type { UserProfile } from '../core/types';\n\ninterface AuthResult<T = unknown> {\n data: T | null;\n error: Error | null;\n}\n\ninterface SignUpOptions {\n metadata?: Record<string, unknown>;\n}\n\ninterface SignInWithProviderOptions {\n redirectTo?: string;\n [key: string]: unknown;\n}\n\nexport interface AuthContextType {\n user: User | null;\n profile: UserProfile | null;\n session: Session | null;\n loading: boolean;\n isConfigured: boolean;\n signUp: (email: string, password: string, options?: SignUpOptions) => Promise<AuthResult>;\n signIn: (email: string, password: string) => Promise<AuthResult>;\n signInWithProvider: (provider: string, options?: SignInWithProviderOptions) => Promise<AuthResult>;\n signOut: () => Promise<{ error: Error | null }>;\n resetPassword: (email: string) => Promise<AuthResult>;\n updateProfile: (updates: Partial<UserProfile>) => Promise<AuthResult>;\n refetchProfile: (userId: string) => Promise<UserProfile | null>;\n}\n\nconst NOT_CONFIGURED_MSG = 'Authentication is not configured. Connect a Supabase database in Settings → Databases to enable login and signup.';\nfunction notConfiguredError() {\n return new Error(NOT_CONFIGURED_MSG);\n}\n\nexport const AuthContext = createContext<AuthContextType>({\n user: null,\n profile: null,\n session: null,\n loading: true,\n isConfigured: false,\n signUp: async () => ({ data: null, error: null }),\n signIn: async () => ({ data: null, error: null }),\n signInWithProvider: async () => ({ data: null, error: null }),\n signOut: async () => ({ error: null }),\n resetPassword: async () => ({ data: null, error: null }),\n updateProfile: async () => ({ data: null, error: null }),\n refetchProfile: async () => null,\n});\n\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\n const [user, setUser] = useState<User | null>(null);\n const [profile, setProfile] = useState<UserProfile | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState<boolean>(true);\n const previousUserIdRef = useRef<string | null>(null);\n\n const fetchProfile = useCallback(async (userId: string): Promise<UserProfile | null> => {\n if (!userId) return null;\n\n try {\n const result = await supabase\n .from('user_profiles')\n .select('*')\n .eq('id', userId)\n .single();\n\n const { data, error } = result || { data: null, error: null };\n\n if (error) {\n return null;\n }\n\n setProfile(data as UserProfile);\n return data as UserProfile;\n } catch {\n return null;\n }\n }, []);\n\n useEffect(() => {\n supabase.auth.getSession().then(async ({ data: { session: initialSession } }) => {\n setSession(initialSession);\n setUser(initialSession?.user ?? null);\n\n if (initialSession?.user) {\n await fetchProfile(initialSession.user.id);\n }\n\n setLoading(false);\n });\n\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange(async (event, currentSession) => {\n setSession(currentSession);\n setUser(currentSession?.user ?? null);\n\n if (event === 'SIGNED_IN' && currentSession?.user) {\n await fetchProfile(currentSession.user.id);\n ezcoderAuthIntegration.onLogin(currentSession.user);\n previousUserIdRef.current = currentSession.user.id;\n } else if (event === 'SIGNED_OUT') {\n setProfile(null);\n if (previousUserIdRef.current) {\n ezcoderAuthIntegration.onLogout(previousUserIdRef.current);\n previousUserIdRef.current = null;\n }\n } else if (event === 'USER_UPDATED' && currentSession?.user) {\n ezcoder.analytics.identify(currentSession.user.id, {\n email: currentSession.user.email,\n name: currentSession.user.user_metadata?.full_name,\n });\n }\n });\n\n return () => subscription.unsubscribe();\n }, [fetchProfile]);\n\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n const { metadata = {} } = options;\n\n try {\n const result = await supabase.auth.signUp({\n email,\n password,\n options: { data: metadata },\n });\n\n const { data, error } = result || { data: null, error: new Error('Sign up failed') };\n\n if (error) {\n return { data: null, error };\n }\n\n if (data?.user) {\n if (metadata.display_name) {\n await supabase.from('user_profiles').upsert({\n id: data.user.id,\n email,\n display_name: metadata.display_name,\n });\n }\n ezcoderAuthIntegration.onSignup(data.user);\n }\n\n return { data, error: null };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\n }\n }, []);\n\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.signInWithPassword({ email, password });\n const { data, error } = result || { data: null, error: new Error('Sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\n }\n }, []);\n\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\n if (!isSupabaseConfigured) {\n return { data: null, error: notConfiguredError() };\n }\n try {\n const result = await supabase.auth.signInWithOAuth({\n provider: provider as 'google' | 'github',\n options: {\n redirectTo: options.redirectTo || (typeof window !== 'undefined' ? window.location.origin : ''),\n ...options,\n },\n });\n const { data, error } = result || { data: null, error: new Error('OAuth sign in failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\n }\n }, []);\n\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\n const userId = user?.id;\n try {\n const result = await supabase.auth.signOut();\n const { error } = result || { error: null };\n if (!error && userId) {\n ezcoder.users.trackLogout(userId);\n }\n return { error };\n } catch (err: unknown) {\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\n }\n }, [user]);\n\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\n try {\n const result = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo: `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`,\n });\n const { data, error } = result || { data: null, error: new Error('Password reset failed') };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\n }\n }, []);\n\n const updateProfile = useCallback(\n async (updates: Partial<UserProfile>): Promise<AuthResult> => {\n if (!user) {\n return { data: null, error: new Error('Not authenticated') };\n }\n try {\n const result = await supabase\n .from('user_profiles')\n .update(updates)\n .eq('id', user.id)\n .select()\n .single();\n const { data, error } = result || { data: null, error: null };\n return { data, error };\n } catch (err: unknown) {\n return { data: null, error: err instanceof Error ? err : new Error('Update failed') };\n }\n },\n [user]\n );\n\n const value: AuthContextType = {\n user,\n profile,\n session,\n loading,\n isConfigured: isSupabaseConfigured,\n signUp,\n signIn,\n signInWithProvider,\n signOut,\n resetPassword,\n updateProfile,\n refetchProfile: fetchProfile,\n };\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\nexport function useAuth(): AuthContextType {\n const context = useContext(AuthContext);\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport type { AuthResult, SignUpOptions, SignInWithProviderOptions };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
interface ContentItem {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
content: string;
|
|
6
|
+
type: string;
|
|
7
|
+
status: string;
|
|
8
|
+
author_id?: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
published_at?: string;
|
|
11
|
+
created_at: string;
|
|
12
|
+
updated_at: string;
|
|
13
|
+
}
|
|
14
|
+
interface ContentListOptions {
|
|
15
|
+
type?: string;
|
|
16
|
+
status?: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
}
|
|
19
|
+
declare const cmsClient: {
|
|
20
|
+
list(options?: ContentListOptions): Promise<ContentItem[]>;
|
|
21
|
+
getBySlug(slug: string): Promise<ContentItem | null>;
|
|
22
|
+
getById(id: string): Promise<ContentItem | null>;
|
|
23
|
+
create(item: Partial<ContentItem>): Promise<ContentItem>;
|
|
24
|
+
update(id: string, updates: Partial<ContentItem>): Promise<ContentItem>;
|
|
25
|
+
delete(id: string): Promise<void>;
|
|
26
|
+
publish(id: string): Promise<ContentItem>;
|
|
27
|
+
unpublish(id: string): Promise<ContentItem>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
interface UseContentListReturn {
|
|
31
|
+
content: ContentItem[];
|
|
32
|
+
loading: boolean;
|
|
33
|
+
error: string | null;
|
|
34
|
+
refetch: () => Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
interface UseContentReturn {
|
|
37
|
+
content: ContentItem | null;
|
|
38
|
+
loading: boolean;
|
|
39
|
+
error: string | null;
|
|
40
|
+
}
|
|
41
|
+
declare function useContentList(options?: ContentListOptions): UseContentListReturn;
|
|
42
|
+
declare function useContent(slug: string): UseContentReturn;
|
|
43
|
+
|
|
44
|
+
export { type ContentItem, type ContentListOptions, cmsClient, useContent, useContentList };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
features,
|
|
3
|
+
supabase
|
|
4
|
+
} from "../chunk-G7XDUN3Z.js";
|
|
5
|
+
|
|
6
|
+
// src/cms/cmsClient.ts
|
|
7
|
+
function slugify(text) {
|
|
8
|
+
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
9
|
+
}
|
|
10
|
+
var cmsClient = {
|
|
11
|
+
async list(options = {}) {
|
|
12
|
+
if (!features.database) return [];
|
|
13
|
+
let query = supabase.from("cms_content").select("*");
|
|
14
|
+
if (options.type) query = query.eq("type", options.type);
|
|
15
|
+
if (options.status) query = query.eq("status", options.status);
|
|
16
|
+
query = query.order("created_at", { ascending: false });
|
|
17
|
+
if (options.limit) query = query.limit(options.limit);
|
|
18
|
+
const { data, error } = await query;
|
|
19
|
+
if (error) throw error;
|
|
20
|
+
return data || [];
|
|
21
|
+
},
|
|
22
|
+
async getBySlug(slug) {
|
|
23
|
+
if (!features.database) return null;
|
|
24
|
+
const { data, error } = await supabase.from("cms_content").select("*").eq("slug", slug).single();
|
|
25
|
+
if (error) return null;
|
|
26
|
+
return data;
|
|
27
|
+
},
|
|
28
|
+
async getById(id) {
|
|
29
|
+
if (!features.database) return null;
|
|
30
|
+
const { data, error } = await supabase.from("cms_content").select("*").eq("id", id).single();
|
|
31
|
+
if (error) return null;
|
|
32
|
+
return data;
|
|
33
|
+
},
|
|
34
|
+
async create(item) {
|
|
35
|
+
if (!features.database) throw new Error("Database not configured");
|
|
36
|
+
const slug = item.slug || slugify(item.title || "");
|
|
37
|
+
const { data, error } = await supabase.from("cms_content").insert({ ...item, slug, status: item.status || "draft" }).select().single();
|
|
38
|
+
if (error) throw error;
|
|
39
|
+
return data;
|
|
40
|
+
},
|
|
41
|
+
async update(id, updates) {
|
|
42
|
+
if (!features.database) throw new Error("Database not configured");
|
|
43
|
+
const { data, error } = await supabase.from("cms_content").update({ ...updates, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id).select().single();
|
|
44
|
+
if (error) throw error;
|
|
45
|
+
return data;
|
|
46
|
+
},
|
|
47
|
+
async delete(id) {
|
|
48
|
+
if (!features.database) throw new Error("Database not configured");
|
|
49
|
+
const { error } = await supabase.from("cms_content").delete().eq("id", id);
|
|
50
|
+
if (error) throw error;
|
|
51
|
+
},
|
|
52
|
+
async publish(id) {
|
|
53
|
+
return cmsClient.update(id, { status: "published", published_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
54
|
+
},
|
|
55
|
+
async unpublish(id) {
|
|
56
|
+
return cmsClient.update(id, { status: "draft" });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/cms/useContent.ts
|
|
61
|
+
import { useState, useEffect, useCallback } from "react";
|
|
62
|
+
function useContentList(options = {}) {
|
|
63
|
+
const [content, setContent] = useState([]);
|
|
64
|
+
const [loading, setLoading] = useState(true);
|
|
65
|
+
const [error, setError] = useState(null);
|
|
66
|
+
const fetch = useCallback(async () => {
|
|
67
|
+
try {
|
|
68
|
+
setLoading(true);
|
|
69
|
+
const data = await cmsClient.list(options);
|
|
70
|
+
setContent(data);
|
|
71
|
+
setError(null);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
setError(err instanceof Error ? err.message : "Failed to fetch content");
|
|
74
|
+
} finally {
|
|
75
|
+
setLoading(false);
|
|
76
|
+
}
|
|
77
|
+
}, [options.type, options.status, options.limit]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
fetch();
|
|
80
|
+
}, [fetch]);
|
|
81
|
+
return { content, loading, error, refetch: fetch };
|
|
82
|
+
}
|
|
83
|
+
function useContent(slug) {
|
|
84
|
+
const [content, setContent] = useState(null);
|
|
85
|
+
const [loading, setLoading] = useState(true);
|
|
86
|
+
const [error, setError] = useState(null);
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (!slug) {
|
|
89
|
+
setLoading(false);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
cmsClient.getBySlug(slug).then((data) => {
|
|
93
|
+
setContent(data);
|
|
94
|
+
setError(null);
|
|
95
|
+
}).catch((err) => {
|
|
96
|
+
setError(err instanceof Error ? err.message : "Failed to fetch content");
|
|
97
|
+
}).finally(() => setLoading(false));
|
|
98
|
+
}, [slug]);
|
|
99
|
+
return { content, loading, error };
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
cmsClient,
|
|
103
|
+
useContent,
|
|
104
|
+
useContentList
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cms/cmsClient.ts","../../src/cms/useContent.ts"],"sourcesContent":["import { supabase } from '../core/supabase';\nimport { features } from '../core/config';\n\ninterface ContentItem {\n id: string;\n title: string;\n slug: string;\n content: string;\n type: string;\n status: string;\n author_id?: string;\n metadata?: Record<string, unknown>;\n published_at?: string;\n created_at: string;\n updated_at: string;\n}\n\ninterface ContentListOptions {\n type?: string;\n status?: string;\n limit?: number;\n}\n\nfunction slugify(text: string): string {\n return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');\n}\n\nexport const cmsClient = {\n async list(options: ContentListOptions = {}): Promise<ContentItem[]> {\n if (!features.database) return [];\n\n let query = supabase.from('cms_content').select('*');\n if (options.type) query = query.eq('type', options.type);\n if (options.status) query = query.eq('status', options.status);\n query = query.order('created_at', { ascending: false });\n if (options.limit) query = query.limit(options.limit);\n\n const { data, error } = await query;\n if (error) throw error;\n return (data as ContentItem[]) || [];\n },\n\n async getBySlug(slug: string): Promise<ContentItem | null> {\n if (!features.database) return null;\n\n const { data, error } = await supabase\n .from('cms_content')\n .select('*')\n .eq('slug', slug)\n .single();\n\n if (error) return null;\n return data as ContentItem;\n },\n\n async getById(id: string): Promise<ContentItem | null> {\n if (!features.database) return null;\n\n const { data, error } = await supabase\n .from('cms_content')\n .select('*')\n .eq('id', id)\n .single();\n\n if (error) return null;\n return data as ContentItem;\n },\n\n async create(item: Partial<ContentItem>): Promise<ContentItem> {\n if (!features.database) throw new Error('Database not configured');\n\n const slug = item.slug || slugify(item.title || '');\n const { data, error } = await supabase\n .from('cms_content')\n .insert({ ...item, slug, status: item.status || 'draft' })\n .select()\n .single();\n\n if (error) throw error;\n return data as ContentItem;\n },\n\n async update(id: string, updates: Partial<ContentItem>): Promise<ContentItem> {\n if (!features.database) throw new Error('Database not configured');\n\n const { data, error } = await supabase\n .from('cms_content')\n .update({ ...updates, updated_at: new Date().toISOString() })\n .eq('id', id)\n .select()\n .single();\n\n if (error) throw error;\n return data as ContentItem;\n },\n\n async delete(id: string): Promise<void> {\n if (!features.database) throw new Error('Database not configured');\n const { error } = await supabase.from('cms_content').delete().eq('id', id);\n if (error) throw error;\n },\n\n async publish(id: string): Promise<ContentItem> {\n return cmsClient.update(id, { status: 'published', published_at: new Date().toISOString() });\n },\n\n async unpublish(id: string): Promise<ContentItem> {\n return cmsClient.update(id, { status: 'draft' });\n },\n};\n\nexport type { ContentItem, ContentListOptions };\n","import { useState, useEffect, useCallback } from 'react';\nimport { cmsClient } from './cmsClient';\nimport type { ContentItem, ContentListOptions } from './cmsClient';\n\ninterface UseContentListReturn {\n content: ContentItem[];\n loading: boolean;\n error: string | null;\n refetch: () => Promise<void>;\n}\n\ninterface UseContentReturn {\n content: ContentItem | null;\n loading: boolean;\n error: string | null;\n}\n\nexport function useContentList(options: ContentListOptions = {}): UseContentListReturn {\n const [content, setContent] = useState<ContentItem[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetch = useCallback(async () => {\n try {\n setLoading(true);\n const data = await cmsClient.list(options);\n setContent(data);\n setError(null);\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : 'Failed to fetch content');\n } finally {\n setLoading(false);\n }\n }, [options.type, options.status, options.limit]);\n\n useEffect(() => {\n fetch();\n }, [fetch]);\n\n return { content, loading, error, refetch: fetch };\n}\n\nexport function useContent(slug: string): UseContentReturn {\n const [content, setContent] = useState<ContentItem | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (!slug) {\n setLoading(false);\n return;\n }\n\n cmsClient.getBySlug(slug)\n .then((data) => {\n setContent(data);\n setError(null);\n })\n .catch((err: unknown) => {\n setError(err instanceof Error ? err.message : 'Failed to fetch content');\n })\n .finally(() => setLoading(false));\n }, [slug]);\n\n return { content, loading, error };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Component, ReactNode, ErrorInfo } from 'react';
|
|
3
|
+
|
|
4
|
+
interface ErrorBoundaryProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
fallback?: ReactNode | ((error: Error) => ReactNode);
|
|
7
|
+
}
|
|
8
|
+
interface ErrorBoundaryState {
|
|
9
|
+
hasError: boolean;
|
|
10
|
+
error: Error | null;
|
|
11
|
+
}
|
|
12
|
+
declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
13
|
+
constructor(props: ErrorBoundaryProps);
|
|
14
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
15
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
16
|
+
render(): string | number | boolean | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
17
|
+
}
|
|
18
|
+
declare function NotFoundPage(): react_jsx_runtime.JSX.Element;
|
|
19
|
+
|
|
20
|
+
export { ErrorBoundary, NotFoundPage };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/errors/ErrorBoundary.tsx
|
|
2
|
+
import { Component } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var ErrorBoundary = class extends Component {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props);
|
|
7
|
+
this.state = { hasError: false, error: null };
|
|
8
|
+
}
|
|
9
|
+
static getDerivedStateFromError(error) {
|
|
10
|
+
return { hasError: true, error };
|
|
11
|
+
}
|
|
12
|
+
componentDidCatch(error, errorInfo) {
|
|
13
|
+
void errorInfo;
|
|
14
|
+
void error;
|
|
15
|
+
}
|
|
16
|
+
render() {
|
|
17
|
+
if (this.state.hasError && this.state.error) {
|
|
18
|
+
if (typeof this.props.fallback === "function") {
|
|
19
|
+
return this.props.fallback(this.state.error);
|
|
20
|
+
}
|
|
21
|
+
if (this.props.fallback) {
|
|
22
|
+
return this.props.fallback;
|
|
23
|
+
}
|
|
24
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "40px", textAlign: "center" }, children: [
|
|
25
|
+
/* @__PURE__ */ jsx("h2", { style: { fontSize: "1.5rem", fontWeight: 600, color: "#dc2626", marginBottom: "8px" }, children: "Something went wrong" }),
|
|
26
|
+
/* @__PURE__ */ jsx("p", { style: { color: "#6b7280", marginBottom: "16px" }, children: this.state.error.message }),
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
"button",
|
|
29
|
+
{
|
|
30
|
+
onClick: () => this.setState({ hasError: false, error: null }),
|
|
31
|
+
style: {
|
|
32
|
+
padding: "8px 16px",
|
|
33
|
+
backgroundColor: "#3b82f6",
|
|
34
|
+
color: "white",
|
|
35
|
+
border: "none",
|
|
36
|
+
borderRadius: "6px",
|
|
37
|
+
cursor: "pointer",
|
|
38
|
+
marginRight: "8px"
|
|
39
|
+
},
|
|
40
|
+
children: "Try Again"
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
/* @__PURE__ */ jsx("a", { href: "/", style: { padding: "8px 16px", color: "#3b82f6", textDecoration: "none" }, children: "Go Home" })
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
return this.props.children;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function NotFoundPage() {
|
|
50
|
+
return /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "80px 20px" }, children: [
|
|
51
|
+
/* @__PURE__ */ jsx("h1", { style: { fontSize: "4rem", fontWeight: 700, color: "#d1d5db", marginBottom: "8px" }, children: "404" }),
|
|
52
|
+
/* @__PURE__ */ jsx("h2", { style: { fontSize: "1.5rem", fontWeight: 600, marginBottom: "8px" }, children: "Page Not Found" }),
|
|
53
|
+
/* @__PURE__ */ jsx("p", { style: { color: "#6b7280", marginBottom: "24px" }, children: "The page you're looking for doesn't exist." }),
|
|
54
|
+
/* @__PURE__ */ jsx("a", { href: "/", style: { color: "#3b82f6", textDecoration: "none", fontWeight: 500 }, children: "Go Home" })
|
|
55
|
+
] });
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
ErrorBoundary,
|
|
59
|
+
NotFoundPage
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/errors/ErrorBoundary.tsx"],"sourcesContent":["import { Component } from 'react';\nimport type { ErrorInfo, ReactNode } from 'react';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error) => ReactNode);\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n void errorInfo;\n void error;\n }\n\n render() {\n if (this.state.hasError && this.state.error) {\n if (typeof this.props.fallback === 'function') {\n return this.props.fallback(this.state.error);\n }\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div style={{ padding: '40px', textAlign: 'center' }}>\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, color: '#dc2626', marginBottom: '8px' }}>\n Something went wrong\n </h2>\n <p style={{ color: '#6b7280', marginBottom: '16px' }}>\n {this.state.error.message}\n </p>\n <button\n onClick={() => this.setState({ hasError: false, error: null })}\n style={{\n padding: '8px 16px', backgroundColor: '#3b82f6', color: 'white',\n border: 'none', borderRadius: '6px', cursor: 'pointer', marginRight: '8px',\n }}\n >\n Try Again\n </button>\n <a href=\"/\" style={{ padding: '8px 16px', color: '#3b82f6', textDecoration: 'none' }}>\n Go Home\n </a>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\nexport function NotFoundPage() {\n return (\n <div style={{ textAlign: 'center', padding: '80px 20px' }}>\n <h1 style={{ fontSize: '4rem', fontWeight: 700, color: '#d1d5db', marginBottom: '8px' }}>404</h1>\n <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '8px' }}>Page Not Found</h2>\n <p style={{ color: '#6b7280', marginBottom: '24px' }}>The page you're looking for doesn't exist.</p>\n <a href=\"/\" style={{ color: '#3b82f6', textDecoration: 'none', fontWeight: 500 }}>Go Home</a>\n </div>\n );\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAsClB,SACE,KADF;AAzBD,IAAM,gBAAN,cAA4B,UAAkD;AAAA,EACnF,YAAY,OAA2B;AACrC,UAAM,KAAK;AACX,SAAK,QAAQ,EAAE,UAAU,OAAO,OAAO,KAAK;AAAA,EAC9C;AAAA,EAEA,OAAO,yBAAyB,OAAkC;AAChE,WAAO,EAAE,UAAU,MAAM,MAAM;AAAA,EACjC;AAAA,EAEA,kBAAkB,OAAc,WAA4B;AAC1D,SAAK;AACL,SAAK;AAAA,EACP;AAAA,EAEA,SAAS;AACP,QAAI,KAAK,MAAM,YAAY,KAAK,MAAM,OAAO;AAC3C,UAAI,OAAO,KAAK,MAAM,aAAa,YAAY;AAC7C,eAAO,KAAK,MAAM,SAAS,KAAK,MAAM,KAAK;AAAA,MAC7C;AACA,UAAI,KAAK,MAAM,UAAU;AACvB,eAAO,KAAK,MAAM;AAAA,MACpB;AAEA,aACE,qBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,WAAW,SAAS,GACjD;AAAA,4BAAC,QAAG,OAAO,EAAE,UAAU,UAAU,YAAY,KAAK,OAAO,WAAW,cAAc,MAAM,GAAG,kCAE3F;AAAA,QACA,oBAAC,OAAE,OAAO,EAAE,OAAO,WAAW,cAAc,OAAO,GAChD,eAAK,MAAM,MAAM,SACpB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,KAAK,SAAS,EAAE,UAAU,OAAO,OAAO,KAAK,CAAC;AAAA,YAC7D,OAAO;AAAA,cACL,SAAS;AAAA,cAAY,iBAAiB;AAAA,cAAW,OAAO;AAAA,cACxD,QAAQ;AAAA,cAAQ,cAAc;AAAA,cAAO,QAAQ;AAAA,cAAW,aAAa;AAAA,YACvE;AAAA,YACD;AAAA;AAAA,QAED;AAAA,QACA,oBAAC,OAAE,MAAK,KAAI,OAAO,EAAE,SAAS,YAAY,OAAO,WAAW,gBAAgB,OAAO,GAAG,qBAEtF;AAAA,SACF;AAAA,IAEJ;AAEA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAEO,SAAS,eAAe;AAC7B,SACE,qBAAC,SAAI,OAAO,EAAE,WAAW,UAAU,SAAS,YAAY,GACtD;AAAA,wBAAC,QAAG,OAAO,EAAE,UAAU,QAAQ,YAAY,KAAK,OAAO,WAAW,cAAc,MAAM,GAAG,iBAAG;AAAA,IAC5F,oBAAC,QAAG,OAAO,EAAE,UAAU,UAAU,YAAY,KAAK,cAAc,MAAM,GAAG,4BAAc;AAAA,IACvF,oBAAC,OAAE,OAAO,EAAE,OAAO,WAAW,cAAc,OAAO,GAAG,wDAAoD;AAAA,IAC1G,oBAAC,OAAE,MAAK,KAAI,OAAO,EAAE,OAAO,WAAW,gBAAgB,QAAQ,YAAY,IAAI,GAAG,qBAAO;AAAA,KAC3F;AAEJ;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
import { E as EzcoderClient, A as AuthIntegration } from './types-DtY5lp3P.js';
|
|
3
|
+
export { a as AnalyticsResult, b as AuthUser, C as CheckoutOptions, S as StorageFile, c as StorageResult, d as SubscriptionStatus, e as SubscriptionTier, U as UserProfile } from './types-DtY5lp3P.js';
|
|
4
|
+
|
|
5
|
+
declare const env: {
|
|
6
|
+
SUPABASE_URL: string;
|
|
7
|
+
SUPABASE_ANON_KEY: string;
|
|
8
|
+
STRIPE_PUBLISHABLE_KEY: string;
|
|
9
|
+
EZC_PROJECT_ID: string;
|
|
10
|
+
EZCODER_API_URL: string;
|
|
11
|
+
EZC_SECRET_KEY: string;
|
|
12
|
+
S3_BUCKET: string;
|
|
13
|
+
CLOUDINARY_URL: string;
|
|
14
|
+
};
|
|
15
|
+
declare const features: {
|
|
16
|
+
auth: boolean;
|
|
17
|
+
payments: boolean;
|
|
18
|
+
analytics: boolean;
|
|
19
|
+
storage: boolean;
|
|
20
|
+
database: boolean;
|
|
21
|
+
};
|
|
22
|
+
declare function isFeatureConfigured(feature: keyof typeof features): boolean;
|
|
23
|
+
|
|
24
|
+
declare const supabase: SupabaseClient;
|
|
25
|
+
declare const isSupabaseConfigured: boolean;
|
|
26
|
+
|
|
27
|
+
declare const ezcoder: EzcoderClient;
|
|
28
|
+
declare const ezcoderAuthIntegration: AuthIntegration;
|
|
29
|
+
|
|
30
|
+
export { AuthIntegration, EzcoderClient, env, ezcoder, ezcoderAuthIntegration, features, isFeatureConfigured, isSupabaseConfigured, supabase };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ezcoder,
|
|
3
|
+
ezcoderAuthIntegration
|
|
4
|
+
} from "./chunk-5XIZHBKE.js";
|
|
5
|
+
import {
|
|
6
|
+
env,
|
|
7
|
+
features,
|
|
8
|
+
isFeatureConfigured,
|
|
9
|
+
isSupabaseConfigured,
|
|
10
|
+
supabase
|
|
11
|
+
} from "./chunk-G7XDUN3Z.js";
|
|
12
|
+
export {
|
|
13
|
+
env,
|
|
14
|
+
ezcoder,
|
|
15
|
+
ezcoderAuthIntegration,
|
|
16
|
+
features,
|
|
17
|
+
isFeatureConfigured,
|
|
18
|
+
isSupabaseConfigured,
|
|
19
|
+
supabase
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface Notification {
|
|
4
|
+
id: string;
|
|
5
|
+
type: string;
|
|
6
|
+
title: string;
|
|
7
|
+
message: string;
|
|
8
|
+
data?: Record<string, unknown>;
|
|
9
|
+
read: boolean;
|
|
10
|
+
read_at?: string;
|
|
11
|
+
created_at: string;
|
|
12
|
+
}
|
|
13
|
+
interface UseNotificationsReturn {
|
|
14
|
+
notifications: Notification[];
|
|
15
|
+
unreadCount: number;
|
|
16
|
+
loading: boolean;
|
|
17
|
+
isConfigured: boolean;
|
|
18
|
+
markAsRead: (notificationId: string) => Promise<void>;
|
|
19
|
+
markAllAsRead: () => Promise<void>;
|
|
20
|
+
deleteNotification: (notificationId: string) => Promise<void>;
|
|
21
|
+
refetch: () => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
declare function useNotifications(): UseNotificationsReturn;
|
|
24
|
+
|
|
25
|
+
interface NotificationCenterProps {
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
declare function NotificationCenter({ className }: NotificationCenterProps): react_jsx_runtime.JSX.Element;
|
|
29
|
+
|
|
30
|
+
export { NotificationCenter, useNotifications };
|