@ezcoder.dev/sdk 1.1.0 → 1.2.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.
Files changed (41) hide show
  1. package/dist/analytics/index.js +7 -5
  2. package/dist/analytics/index.js.map +1 -1
  3. package/dist/auth/index.d.ts +1 -0
  4. package/dist/auth/index.js +25 -6
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/chunk-CQKYANAW.js +44 -0
  7. package/dist/chunk-CQKYANAW.js.map +1 -0
  8. package/dist/{chunk-GPF4AYNG.js → chunk-HJ2EIZ4S.js} +2 -2
  9. package/dist/{chunk-2WG4O4J2.js → chunk-I2YGB7Z6.js} +14 -50
  10. package/dist/chunk-I2YGB7Z6.js.map +1 -0
  11. package/dist/chunk-LIUE7M7K.js +72 -0
  12. package/dist/chunk-LIUE7M7K.js.map +1 -0
  13. package/dist/{chunk-AWU47M6N.js → chunk-QHB7LGCA.js} +91 -8
  14. package/dist/chunk-QHB7LGCA.js.map +1 -0
  15. package/dist/{chunk-7VGYFCQC.js → chunk-R4MDAYFO.js} +7 -5
  16. package/dist/{chunk-7VGYFCQC.js.map → chunk-R4MDAYFO.js.map} +1 -1
  17. package/dist/cms/index.js +4 -2
  18. package/dist/cms/index.js.map +1 -1
  19. package/dist/cron/index.d.ts +17 -0
  20. package/dist/cron/index.js +26 -12
  21. package/dist/cron/index.js.map +1 -1
  22. package/dist/database/index.js +4 -3
  23. package/dist/email/index.d.ts +18 -0
  24. package/dist/email/index.js +27 -12
  25. package/dist/email/index.js.map +1 -1
  26. package/dist/index.d.ts +167 -1
  27. package/dist/index.js +263 -7
  28. package/dist/index.js.map +1 -1
  29. package/dist/notifications/index.d.ts +27 -2
  30. package/dist/notifications/index.js +53 -18
  31. package/dist/notifications/index.js.map +1 -1
  32. package/dist/payments/index.js +6 -4
  33. package/dist/payments/index.js.map +1 -1
  34. package/dist/roles/index.js +6 -4
  35. package/dist/roles/index.js.map +1 -1
  36. package/dist/storage/index.js +7 -5
  37. package/dist/storage/index.js.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-2WG4O4J2.js.map +0 -1
  40. package/dist/chunk-AWU47M6N.js.map +0 -1
  41. /package/dist/{chunk-GPF4AYNG.js.map → chunk-HJ2EIZ4S.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/storage/useStorage.ts","../../src/storage/FileUpload.tsx","../../src/storage/ImagePreview.tsx"],"sourcesContent":["import { useState, useCallback, useContext } from 'react';\r\nimport { supabase } from '../core/supabase';\r\nimport { features, env } from '../core/config';\r\nimport { AuthContext } from '../auth/AuthProvider';\r\nimport type { StorageResult, StorageFile } from '../core/types';\r\n\r\ntype StorageProvider = 'supabase' | 'stub';\r\n\r\nconst TIER_RETENTION_DAYS: Record<string, number> = {\r\n free: 7,\r\n starter: 30,\r\n pro: 90,\r\n creator: 90,\r\n business: 365,\r\n enterprise: -1,\r\n};\r\n\r\ninterface UploadOptions {\r\n path?: string;\r\n public?: boolean;\r\n bucket?: string;\r\n}\r\n\r\ninterface UrlOptions {\r\n signed?: boolean;\r\n expiresIn?: number;\r\n}\r\n\r\ninterface UseStorageReturn {\r\n upload: (file: File, options?: UploadOptions) => Promise<StorageResult>;\r\n download: (path: string, bucket?: string) => Promise<Blob>;\r\n getUrl: (path: string, options?: UrlOptions & { bucket?: string }) => Promise<string>;\r\n list: (prefix?: string, bucket?: string) => Promise<StorageFile[]>;\r\n remove: (path: string, bucket?: string) => Promise<void>;\r\n isConfigured: boolean;\r\n provider: StorageProvider;\r\n retentionDays: number;\r\n}\r\n\r\nfunction getDefaultBucket(isPublic = false): string {\r\n if (isPublic && env.STORAGE_BUCKET_PUBLIC) return env.STORAGE_BUCKET_PUBLIC;\r\n if (!isPublic && env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;\r\n if (env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;\r\n return 'uploads';\r\n}\r\n\r\nexport function useStorage(): UseStorageReturn {\r\n const auth = useContext(AuthContext);\r\n const [provider] = useState<StorageProvider>(features.storage ? 'supabase' : 'stub');\r\n const tier = (auth?.profile as unknown as Record<string, unknown>)?.subscription_tier as string || 'free';\r\n const retentionDays = TIER_RETENTION_DAYS[tier] ?? 7;\r\n\r\n const getUserPath = useCallback((path?: string): string => {\r\n const userId = auth?.user?.id;\r\n const basePath = userId ? `user/${userId}` : 'public';\r\n return path ? `${basePath}/${path}` : basePath;\r\n }, [auth?.user?.id]);\r\n\r\n const upload = useCallback(async (file: File, options: UploadOptions = {}): Promise<StorageResult> => {\r\n if (!features.storage) {\r\n throw new Error('Storage is not configured. Set SUPABASE_URL to enable file storage.');\r\n }\r\n\r\n const bucket = options.bucket || getDefaultBucket(options.public);\r\n const filePath = getUserPath(options.path || `${Date.now()}_${file.name}`);\r\n\r\n const { data, error } = await supabase.storage\r\n .from(bucket)\r\n .upload(filePath, file, {\r\n cacheControl: '3600',\r\n upsert: false,\r\n });\r\n\r\n if (error) throw error;\r\n\r\n let url: string;\r\n if (options.public) {\r\n const { data: urlData } = supabase.storage.from(bucket).getPublicUrl(filePath);\r\n url = urlData.publicUrl;\r\n } else {\r\n const { data: signedData, error: signedError } = await supabase.storage\r\n .from(bucket)\r\n .createSignedUrl(filePath, 3600);\r\n if (signedError) throw signedError;\r\n url = signedData.signedUrl;\r\n }\r\n\r\n return {\r\n path: data.path,\r\n url,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n }, [getUserPath]);\r\n\r\n const download = useCallback(async (path: string, bucket = getDefaultBucket()): Promise<Blob> => {\r\n if (!features.storage) throw new Error('Storage is not configured');\r\n\r\n const { data, error } = await supabase.storage.from(bucket).download(path);\r\n if (error) throw error;\r\n return data;\r\n }, []);\r\n\r\n const getUrl = useCallback(async (path: string, options: UrlOptions & { bucket?: string } = {}): Promise<string> => {\r\n if (!features.storage) return '';\r\n\r\n const bucket = options.bucket || getDefaultBucket();\r\n\r\n if (options.signed !== false) {\r\n const { data, error } = await supabase.storage\r\n .from(bucket)\r\n .createSignedUrl(path, options.expiresIn || 3600);\r\n if (error) throw error;\r\n return data.signedUrl;\r\n }\r\n\r\n const { data } = supabase.storage.from(bucket).getPublicUrl(path);\r\n return data.publicUrl;\r\n }, []);\r\n\r\n const list = useCallback(async (prefix?: string, bucket = getDefaultBucket()): Promise<StorageFile[]> => {\r\n if (!features.storage) return [];\r\n\r\n const searchPath = prefix || getUserPath();\r\n const { data, error } = await supabase.storage.from(bucket).list(searchPath);\r\n if (error) throw error;\r\n\r\n return (data || []).map((item) => ({\r\n name: item.name,\r\n path: `${searchPath}/${item.name}`,\r\n size: (item.metadata as Record<string, unknown>)?.size as number || 0,\r\n type: (item.metadata as Record<string, unknown>)?.mimetype as string || '',\r\n created_at: item.created_at || '',\r\n updated_at: item.updated_at || item.created_at || '',\r\n }));\r\n }, [getUserPath]);\r\n\r\n const remove = useCallback(async (path: string, bucket = getDefaultBucket()): Promise<void> => {\r\n if (!features.storage) throw new Error('Storage is not configured');\r\n\r\n const { error } = await supabase.storage.from(bucket).remove([path]);\r\n if (error) throw error;\r\n }, []);\r\n\r\n return { upload, download, getUrl, list, remove, isConfigured: features.storage, provider, retentionDays };\r\n}\r\n","import { useState, useRef, useCallback } from 'react';\r\nimport { useStorage } from './useStorage';\r\nimport type { StorageResult } from '../core/types';\r\n\r\ninterface FileUploadProps {\r\n onUpload?: (result: StorageResult) => void;\r\n onError?: (error: Error) => void;\r\n accept?: string;\r\n maxSize?: number;\r\n multiple?: boolean;\r\n children?: React.ReactNode;\r\n className?: string;\r\n bucket?: string;\r\n public?: boolean;\r\n}\r\n\r\nexport function FileUpload({\r\n onUpload,\r\n onError,\r\n accept,\r\n maxSize = 10 * 1024 * 1024,\r\n multiple = false,\r\n children,\r\n className = '',\r\n bucket,\r\n public: isPublic = false,\r\n}: FileUploadProps) {\r\n const { upload, isConfigured } = useStorage();\r\n const [uploading, setUploading] = useState(false);\r\n const [dragOver, setDragOver] = useState(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleFiles = useCallback(async (files: FileList | null) => {\r\n if (!files || files.length === 0) return;\r\n\r\n setUploading(true);\r\n\r\n for (const file of Array.from(files)) {\r\n if (file.size > maxSize) {\r\n onError?.(new Error(`File ${file.name} exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`));\r\n continue;\r\n }\r\n\r\n try {\r\n const result = await upload(file, { bucket, public: isPublic });\r\n onUpload?.(result);\r\n } catch (err: unknown) {\r\n onError?.(err instanceof Error ? err : new Error('Upload failed'));\r\n }\r\n }\r\n\r\n setUploading(false);\r\n }, [upload, maxSize, onUpload, onError, bucket, isPublic]);\r\n\r\n const handleDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n setDragOver(false);\r\n handleFiles(e.dataTransfer.files);\r\n }, [handleFiles]);\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280', border: '1px dashed #d1d5db', borderRadius: '8px' }}>\r\n Storage is not configured\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={className}\r\n onDrop={handleDrop}\r\n onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}\r\n onDragLeave={() => setDragOver(false)}\r\n onClick={() => fileInputRef.current?.click()}\r\n style={{\r\n border: `2px dashed ${dragOver ? '#3b82f6' : '#d1d5db'}`,\r\n borderRadius: '8px',\r\n padding: '24px',\r\n textAlign: 'center',\r\n cursor: 'pointer',\r\n backgroundColor: dragOver ? '#eff6ff' : 'transparent',\r\n transition: 'all 0.2s',\r\n }}\r\n >\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n onChange={(e) => handleFiles(e.target.files)}\r\n style={{ display: 'none' }}\r\n />\r\n\r\n {children || (\r\n <div>\r\n {uploading ? (\r\n <p style={{ color: '#3b82f6' }}>Uploading...</p>\r\n ) : (\r\n <>\r\n <p style={{ fontWeight: 500, marginBottom: '4px' }}>Drop files here or click to upload</p>\r\n <p style={{ color: '#9ca3af', fontSize: '14px' }}>\r\n Max size: {Math.round(maxSize / 1024 / 1024)}MB\r\n </p>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { useStorage } from './useStorage';\r\n\r\ninterface ImagePreviewProps {\r\n path: string;\r\n alt?: string;\r\n className?: string;\r\n width?: number | string;\r\n height?: number | string;\r\n bucket?: string;\r\n signed?: boolean;\r\n}\r\n\r\nexport function ImagePreview({ path, alt = '', className = '', width, height, bucket, signed = true }: ImagePreviewProps) {\r\n const { getUrl, isConfigured } = useStorage();\r\n const [url, setUrl] = useState<string>('');\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n useEffect(() => {\r\n if (!isConfigured || !path) {\r\n setLoading(false);\r\n return;\r\n }\r\n\r\n getUrl(path, { signed, bucket })\r\n .then(setUrl)\r\n .catch(() => setError(true))\r\n .finally(() => setLoading(false));\r\n }, [path, signed, bucket, getUrl, isConfigured]);\r\n\r\n if (loading) {\r\n return (\r\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <span style={{ color: '#9ca3af' }}>Loading...</span>\r\n </div>\r\n );\r\n }\r\n\r\n if (error || !url) {\r\n return (\r\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <span style={{ color: '#9ca3af' }}>Image not available</span>\r\n </div>\r\n );\r\n }\r\n\r\n return <img src={url} alt={alt} className={className} style={{ width, height, objectFit: 'cover', borderRadius: '8px' }} />;\r\n}\r\n"],"mappings":"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","names":["data","useState","useCallback","useState","useCallback","useState","jsx","useState"]}
1
+ {"version":3,"sources":["../../src/storage/useStorage.ts","../../src/storage/FileUpload.tsx","../../src/storage/ImagePreview.tsx"],"sourcesContent":["import { useState, useCallback, useContext } from 'react';\r\nimport { supabase } from '../core/supabase';\r\nimport { features, env } from '../core/config';\r\nimport { AuthContext } from '../auth/AuthProvider';\r\nimport type { StorageResult, StorageFile } from '../core/types';\r\n\r\ntype StorageProvider = 'supabase' | 'stub';\r\n\r\nconst TIER_RETENTION_DAYS: Record<string, number> = {\r\n free: 7,\r\n starter: 30,\r\n pro: 90,\r\n creator: 90,\r\n business: 365,\r\n enterprise: -1,\r\n};\r\n\r\ninterface UploadOptions {\r\n path?: string;\r\n public?: boolean;\r\n bucket?: string;\r\n}\r\n\r\ninterface UrlOptions {\r\n signed?: boolean;\r\n expiresIn?: number;\r\n}\r\n\r\ninterface UseStorageReturn {\r\n upload: (file: File, options?: UploadOptions) => Promise<StorageResult>;\r\n download: (path: string, bucket?: string) => Promise<Blob>;\r\n getUrl: (path: string, options?: UrlOptions & { bucket?: string }) => Promise<string>;\r\n list: (prefix?: string, bucket?: string) => Promise<StorageFile[]>;\r\n remove: (path: string, bucket?: string) => Promise<void>;\r\n isConfigured: boolean;\r\n provider: StorageProvider;\r\n retentionDays: number;\r\n}\r\n\r\nfunction getDefaultBucket(isPublic = false): string {\r\n if (isPublic && env.STORAGE_BUCKET_PUBLIC) return env.STORAGE_BUCKET_PUBLIC;\r\n if (!isPublic && env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;\r\n if (env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;\r\n return 'uploads';\r\n}\r\n\r\nexport function useStorage(): UseStorageReturn {\r\n const auth = useContext(AuthContext);\r\n const [provider] = useState<StorageProvider>(features.storage ? 'supabase' : 'stub');\r\n const tier = (auth?.profile as unknown as Record<string, unknown>)?.subscription_tier as string || 'free';\r\n const retentionDays = TIER_RETENTION_DAYS[tier] ?? 7;\r\n\r\n const getUserPath = useCallback((path?: string): string => {\r\n const userId = auth?.user?.id;\r\n const basePath = userId ? `user/${userId}` : 'public';\r\n return path ? `${basePath}/${path}` : basePath;\r\n }, [auth?.user?.id]);\r\n\r\n const upload = useCallback(async (file: File, options: UploadOptions = {}): Promise<StorageResult> => {\r\n if (!features.storage) {\r\n throw new Error('Storage is not configured. Set SUPABASE_URL to enable file storage.');\r\n }\r\n\r\n const bucket = options.bucket || getDefaultBucket(options.public);\r\n const filePath = getUserPath(options.path || `${Date.now()}_${file.name}`);\r\n\r\n const { data, error } = await supabase.storage\r\n .from(bucket)\r\n .upload(filePath, file, {\r\n cacheControl: '3600',\r\n upsert: false,\r\n });\r\n\r\n if (error) throw error;\r\n\r\n let url: string;\r\n if (options.public) {\r\n const { data: urlData } = supabase.storage.from(bucket).getPublicUrl(filePath);\r\n url = urlData.publicUrl;\r\n } else {\r\n const { data: signedData, error: signedError } = await supabase.storage\r\n .from(bucket)\r\n .createSignedUrl(filePath, 3600);\r\n if (signedError) throw signedError;\r\n url = signedData.signedUrl;\r\n }\r\n\r\n return {\r\n path: data.path,\r\n url,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n }, [getUserPath]);\r\n\r\n const download = useCallback(async (path: string, bucket = getDefaultBucket()): Promise<Blob> => {\r\n if (!features.storage) throw new Error('Storage is not configured');\r\n\r\n const { data, error } = await supabase.storage.from(bucket).download(path);\r\n if (error) throw error;\r\n return data;\r\n }, []);\r\n\r\n const getUrl = useCallback(async (path: string, options: UrlOptions & { bucket?: string } = {}): Promise<string> => {\r\n if (!features.storage) return '';\r\n\r\n const bucket = options.bucket || getDefaultBucket();\r\n\r\n if (options.signed !== false) {\r\n const { data, error } = await supabase.storage\r\n .from(bucket)\r\n .createSignedUrl(path, options.expiresIn || 3600);\r\n if (error) throw error;\r\n return data.signedUrl;\r\n }\r\n\r\n const { data } = supabase.storage.from(bucket).getPublicUrl(path);\r\n return data.publicUrl;\r\n }, []);\r\n\r\n const list = useCallback(async (prefix?: string, bucket = getDefaultBucket()): Promise<StorageFile[]> => {\r\n if (!features.storage) return [];\r\n\r\n const searchPath = prefix || getUserPath();\r\n const { data, error } = await supabase.storage.from(bucket).list(searchPath);\r\n if (error) throw error;\r\n\r\n return (data || []).map((item) => ({\r\n name: item.name,\r\n path: `${searchPath}/${item.name}`,\r\n size: (item.metadata as Record<string, unknown>)?.size as number || 0,\r\n type: (item.metadata as Record<string, unknown>)?.mimetype as string || '',\r\n created_at: item.created_at || '',\r\n updated_at: item.updated_at || item.created_at || '',\r\n }));\r\n }, [getUserPath]);\r\n\r\n const remove = useCallback(async (path: string, bucket = getDefaultBucket()): Promise<void> => {\r\n if (!features.storage) throw new Error('Storage is not configured');\r\n\r\n const { error } = await supabase.storage.from(bucket).remove([path]);\r\n if (error) throw error;\r\n }, []);\r\n\r\n return { upload, download, getUrl, list, remove, isConfigured: features.storage, provider, retentionDays };\r\n}\r\n","import { useState, useRef, useCallback } from 'react';\r\nimport { useStorage } from './useStorage';\r\nimport type { StorageResult } from '../core/types';\r\n\r\ninterface FileUploadProps {\r\n onUpload?: (result: StorageResult) => void;\r\n onError?: (error: Error) => void;\r\n accept?: string;\r\n maxSize?: number;\r\n multiple?: boolean;\r\n children?: React.ReactNode;\r\n className?: string;\r\n bucket?: string;\r\n public?: boolean;\r\n}\r\n\r\nexport function FileUpload({\r\n onUpload,\r\n onError,\r\n accept,\r\n maxSize = 10 * 1024 * 1024,\r\n multiple = false,\r\n children,\r\n className = '',\r\n bucket,\r\n public: isPublic = false,\r\n}: FileUploadProps) {\r\n const { upload, isConfigured } = useStorage();\r\n const [uploading, setUploading] = useState(false);\r\n const [dragOver, setDragOver] = useState(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const handleFiles = useCallback(async (files: FileList | null) => {\r\n if (!files || files.length === 0) return;\r\n\r\n setUploading(true);\r\n\r\n for (const file of Array.from(files)) {\r\n if (file.size > maxSize) {\r\n onError?.(new Error(`File ${file.name} exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`));\r\n continue;\r\n }\r\n\r\n try {\r\n const result = await upload(file, { bucket, public: isPublic });\r\n onUpload?.(result);\r\n } catch (err: unknown) {\r\n onError?.(err instanceof Error ? err : new Error('Upload failed'));\r\n }\r\n }\r\n\r\n setUploading(false);\r\n }, [upload, maxSize, onUpload, onError, bucket, isPublic]);\r\n\r\n const handleDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n setDragOver(false);\r\n handleFiles(e.dataTransfer.files);\r\n }, [handleFiles]);\r\n\r\n if (!isConfigured) {\r\n return (\r\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280', border: '1px dashed #d1d5db', borderRadius: '8px' }}>\r\n Storage is not configured\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={className}\r\n onDrop={handleDrop}\r\n onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}\r\n onDragLeave={() => setDragOver(false)}\r\n onClick={() => fileInputRef.current?.click()}\r\n style={{\r\n border: `2px dashed ${dragOver ? '#3b82f6' : '#d1d5db'}`,\r\n borderRadius: '8px',\r\n padding: '24px',\r\n textAlign: 'center',\r\n cursor: 'pointer',\r\n backgroundColor: dragOver ? '#eff6ff' : 'transparent',\r\n transition: 'all 0.2s',\r\n }}\r\n >\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n onChange={(e) => handleFiles(e.target.files)}\r\n style={{ display: 'none' }}\r\n />\r\n\r\n {children || (\r\n <div>\r\n {uploading ? (\r\n <p style={{ color: '#3b82f6' }}>Uploading...</p>\r\n ) : (\r\n <>\r\n <p style={{ fontWeight: 500, marginBottom: '4px' }}>Drop files here or click to upload</p>\r\n <p style={{ color: '#9ca3af', fontSize: '14px' }}>\r\n Max size: {Math.round(maxSize / 1024 / 1024)}MB\r\n </p>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { useState, useEffect } from 'react';\r\nimport { useStorage } from './useStorage';\r\n\r\ninterface ImagePreviewProps {\r\n path: string;\r\n alt?: string;\r\n className?: string;\r\n width?: number | string;\r\n height?: number | string;\r\n bucket?: string;\r\n signed?: boolean;\r\n}\r\n\r\nexport function ImagePreview({ path, alt = '', className = '', width, height, bucket, signed = true }: ImagePreviewProps) {\r\n const { getUrl, isConfigured } = useStorage();\r\n const [url, setUrl] = useState<string>('');\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n useEffect(() => {\r\n if (!isConfigured || !path) {\r\n setLoading(false);\r\n return;\r\n }\r\n\r\n getUrl(path, { signed, bucket })\r\n .then(setUrl)\r\n .catch(() => setError(true))\r\n .finally(() => setLoading(false));\r\n }, [path, signed, bucket, getUrl, isConfigured]);\r\n\r\n if (loading) {\r\n return (\r\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <span style={{ color: '#9ca3af' }}>Loading...</span>\r\n </div>\r\n );\r\n }\r\n\r\n if (error || !url) {\r\n return (\r\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\r\n <span style={{ color: '#9ca3af' }}>Image not available</span>\r\n </div>\r\n );\r\n }\r\n\r\n return <img src={url} alt={alt} className={className} style={{ width, height, objectFit: 'cover', borderRadius: '8px' }} />;\r\n}\r\n"],"mappings":"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","names":["data","useState","useCallback","useState","useCallback","useState","jsx","useState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezcoder.dev/sdk",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "EzCoder Platform SDK — auth, payments, storage, analytics, and more with zero configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/config.ts","../src/core/supabase.ts"],"sourcesContent":["const getEnv = (viteKey: string, nextKey?: string): string => {\r\n try {\r\n if (typeof import.meta !== 'undefined' && import.meta.env) {\r\n return (import.meta.env[viteKey] as string) || '';\r\n }\r\n } catch {\r\n // import.meta not available\r\n }\r\n try {\r\n if (typeof process !== 'undefined' && process.env) {\r\n return process.env[nextKey || viteKey] || '';\r\n }\r\n } catch {\r\n // process not available\r\n }\r\n return '';\r\n};\r\n\r\nexport const env = {\r\n SUPABASE_URL: getEnv('VITE_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_URL'),\r\n SUPABASE_ANON_KEY: getEnv('VITE_SUPABASE_ANON_KEY', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'),\r\n EZCODER_AUTH_URL: getEnv('VITE_EZCODER_AUTH_URL', 'NEXT_PUBLIC_EZCODER_AUTH_URL'),\r\n EZCODER_AUTH_ANON_KEY: getEnv('VITE_EZCODER_AUTH_ANON_KEY', 'NEXT_PUBLIC_EZCODER_AUTH_ANON_KEY'),\r\n STRIPE_PUBLISHABLE_KEY: getEnv('VITE_STRIPE_PUBLISHABLE_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'),\r\n EZC_PROJECT_ID: getEnv('VITE_EZC_PROJECT_ID', 'NEXT_PUBLIC_EZC_PROJECT_ID'),\r\n EZCODER_API_URL: getEnv('VITE_EZCODER_API_URL', 'NEXT_PUBLIC_EZCODER_API_URL'),\r\n EZC_SECRET_KEY: getEnv('EZC_SECRET_KEY', 'EZC_SECRET_KEY'),\r\n S3_BUCKET: getEnv('VITE_S3_BUCKET', 'S3_BUCKET'),\r\n CLOUDINARY_URL: getEnv('VITE_CLOUDINARY_URL', 'CLOUDINARY_URL'),\r\n STORAGE_BUCKET_PUBLIC: getEnv('VITE_STORAGE_BUCKET_PUBLIC', 'NEXT_PUBLIC_STORAGE_BUCKET_PUBLIC'),\r\n STORAGE_BUCKET_PRIVATE: getEnv('VITE_STORAGE_BUCKET_PRIVATE', 'NEXT_PUBLIC_STORAGE_BUCKET_PRIVATE'),\r\n};\r\n\r\nexport const features = {\r\n auth: Boolean(\r\n (env.SUPABASE_URL && env.SUPABASE_ANON_KEY) ||\r\n (env.EZCODER_AUTH_URL && env.EZCODER_AUTH_ANON_KEY)\r\n ),\r\n payments: Boolean(env.STRIPE_PUBLISHABLE_KEY),\r\n analytics: Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID),\r\n storage: Boolean(env.SUPABASE_URL || env.EZCODER_AUTH_URL || env.S3_BUCKET || env.CLOUDINARY_URL),\r\n database: Boolean(\r\n (env.EZCODER_AUTH_URL || env.SUPABASE_URL) && env.EZC_PROJECT_ID\r\n ),\r\n};\r\n\r\nexport function isFeatureConfigured(feature: keyof typeof features): boolean {\r\n return features[feature];\r\n}\r\n","import { createClient, SupabaseClient } from '@supabase/supabase-js';\r\nimport { env, features } from './config';\r\n\r\nfunction createStubClient(): SupabaseClient {\r\n const notConfiguredError = new Error('Supabase not configured');\r\n\r\n function createQueryBuilder() {\r\n const builder: Record<string, unknown> = {\r\n select: () => builder,\r\n insert: () => builder,\r\n update: () => builder,\r\n upsert: () => builder,\r\n delete: () => builder,\r\n eq: () => builder,\r\n neq: () => builder,\r\n gt: () => builder,\r\n gte: () => builder,\r\n lt: () => builder,\r\n lte: () => builder,\r\n like: () => builder,\r\n ilike: () => builder,\r\n is: () => builder,\r\n in: () => builder,\r\n contains: () => builder,\r\n containedBy: () => builder,\r\n match: () => builder,\r\n not: () => builder,\r\n or: () => builder,\r\n filter: () => builder,\r\n order: () => builder,\r\n limit: () => builder,\r\n range: () => builder,\r\n textSearch: () => builder,\r\n csv: () => builder,\r\n single: () => Promise.resolve({ data: null, error: null }),\r\n maybeSingle: () => Promise.resolve({ data: null, error: null }),\r\n then: (resolve: (value: unknown) => void, reject?: (reason: unknown) => void) =>\r\n Promise.resolve({ data: [], error: null }).then(resolve, reject),\r\n catch: (fn: (reason: unknown) => void) =>\r\n Promise.resolve({ data: [], error: null }).catch(fn),\r\n };\r\n return builder;\r\n }\r\n\r\n return {\r\n auth: {\r\n getSession: async () => ({ data: { session: null }, error: null }),\r\n getUser: async () => ({ data: { user: null }, error: null }),\r\n signUp: async () => ({ data: null, error: notConfiguredError }),\r\n signInWithPassword: async () => ({ data: null, error: notConfiguredError }),\r\n signInWithOAuth: async () => ({ data: null, error: notConfiguredError }),\r\n signOut: async () => ({ error: null }),\r\n resetPasswordForEmail: async () => ({ data: null, error: notConfiguredError }),\r\n updateUser: async () => ({ data: null, error: notConfiguredError }),\r\n onAuthStateChange: (callback: (event: string, session: null) => void) => {\r\n if (typeof window !== 'undefined') {\r\n setTimeout(() => callback('INITIAL_SESSION', null), 0);\r\n }\r\n return { data: { subscription: { unsubscribe: () => {} } } };\r\n },\r\n },\r\n from: () => createQueryBuilder(),\r\n rpc: async () => ({ data: null, error: notConfiguredError }),\r\n channel: (_name: string) => ({\r\n on: (_event: string, _filter: unknown, _callback: unknown) => ({\r\n subscribe: (cb?: (status: string) => void) => {\r\n if (cb) cb('SUBSCRIBED');\r\n return { unsubscribe: () => {} };\r\n },\r\n }),\r\n subscribe: (cb?: (status: string) => void) => {\r\n if (cb) cb('SUBSCRIBED');\r\n return { unsubscribe: () => {} };\r\n },\r\n }),\r\n removeChannel: () => Promise.resolve('ok'),\r\n removeAllChannels: () => Promise.resolve([]),\r\n storage: {\r\n from: () => ({\r\n upload: async () => ({ data: null, error: notConfiguredError }),\r\n download: async () => ({ data: null, error: notConfiguredError }),\r\n getPublicUrl: () => ({ data: { publicUrl: '' } }),\r\n createSignedUrl: async () => ({ data: null, error: notConfiguredError }),\r\n list: async () => ({ data: [], error: null }),\r\n remove: async () => ({ data: [], error: null }),\r\n }),\r\n },\r\n } as unknown as SupabaseClient;\r\n}\r\n\r\nconst authUrl = env.EZCODER_AUTH_URL || env.SUPABASE_URL;\r\nconst authKey = env.EZCODER_AUTH_ANON_KEY || env.SUPABASE_ANON_KEY;\r\n\r\nconst isConfigured = Boolean(authUrl && authKey);\r\n\r\nif (!isConfigured && typeof window !== 'undefined') {\r\n console.warn(\r\n '[EzCoder SDK] Supabase not configured — auth, database, and storage features are disabled. ' +\r\n 'Set VITE_EZCODER_AUTH_URL and VITE_EZCODER_AUTH_ANON_KEY (or NEXT_PUBLIC_ equivalents) to enable.'\r\n );\r\n}\r\n\r\nexport const supabase: SupabaseClient = isConfigured\r\n ? createClient(authUrl!, authKey!, {\r\n auth: {\r\n autoRefreshToken: true,\r\n persistSession: true,\r\n detectSessionInUrl: true,\r\n },\r\n })\r\n : createStubClient();\r\n\r\nexport const isSupabaseConfigured: boolean = isConfigured;\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/auth/AuthProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\r\nimport type { User, Session } from '@supabase/supabase-js';\r\nimport { supabase, isSupabaseConfigured } from '../core/supabase';\r\nimport { env } from '../core/config';\r\nimport { ezcoder, ezcoderAuthIntegration } from '../core/platform';\r\nimport type { UserProfile } from '../core/types';\r\n\r\ninterface AuthResult<T = unknown> {\r\n data: T | null;\r\n error: Error | null;\r\n}\r\n\r\ninterface SignUpOptions {\r\n metadata?: Record<string, unknown>;\r\n}\r\n\r\ninterface SignInWithProviderOptions {\r\n redirectTo?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface AuthContextType {\r\n user: User | null;\r\n profile: UserProfile | null;\r\n session: Session | null;\r\n loading: boolean;\r\n isConfigured: boolean;\r\n signUp: (email: string, password: string, options?: SignUpOptions) => Promise<AuthResult>;\r\n signIn: (email: string, password: string) => Promise<AuthResult>;\r\n signInWithProvider: (provider: string, options?: SignInWithProviderOptions) => Promise<AuthResult>;\r\n signOut: () => Promise<{ error: Error | null }>;\r\n resetPassword: (email: string) => Promise<AuthResult>;\r\n updateProfile: (updates: Partial<UserProfile>) => Promise<AuthResult>;\r\n refetchProfile: (userId: string) => Promise<UserProfile | null>;\r\n}\r\n\r\nconst NOT_CONFIGURED_MSG = 'Authentication is not configured. Ensure EzCoder platform credentials are injected, or connect your own Supabase database in Settings → Databases.';\r\nfunction notConfiguredError() {\r\n return new Error(NOT_CONFIGURED_MSG);\r\n}\r\n\r\nexport const AuthContext = createContext<AuthContextType>({\r\n user: null,\r\n profile: null,\r\n session: null,\r\n loading: true,\r\n isConfigured: false,\r\n signUp: async () => ({ data: null, error: null }),\r\n signIn: async () => ({ data: null, error: null }),\r\n signInWithProvider: async () => ({ data: null, error: null }),\r\n signOut: async () => ({ error: null }),\r\n resetPassword: async () => ({ data: null, error: null }),\r\n updateProfile: async () => ({ data: null, error: null }),\r\n refetchProfile: async () => null,\r\n});\r\n\r\nexport function AuthProvider({ children }: { children: React.ReactNode }) {\r\n const [user, setUser] = useState<User | null>(null);\r\n const [profile, setProfile] = useState<UserProfile | null>(null);\r\n const [session, setSession] = useState<Session | null>(null);\r\n const [loading, setLoading] = useState<boolean>(true);\r\n const previousUserIdRef = useRef<string | null>(null);\r\n\r\n const fetchProfile = useCallback(async (userId: string): Promise<UserProfile | null> => {\r\n if (!userId) return null;\r\n\r\n try {\r\n let query = supabase\r\n .from('user_profiles')\r\n .select('*')\r\n .eq('id', userId);\r\n\r\n if (env.EZC_PROJECT_ID) {\r\n query = query.eq('project_id', env.EZC_PROJECT_ID);\r\n }\r\n\r\n const result = await query.single();\r\n\r\n const { data, error } = result || { data: null, error: null };\r\n\r\n if (error) {\r\n return null;\r\n }\r\n\r\n setProfile(data as UserProfile);\r\n return data as UserProfile;\r\n } catch {\r\n return null;\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n supabase.auth.getSession().then(async ({ data: { session: initialSession } }) => {\r\n setSession(initialSession);\r\n setUser(initialSession?.user ?? null);\r\n\r\n if (initialSession?.user) {\r\n await fetchProfile(initialSession.user.id);\r\n }\r\n\r\n setLoading(false);\r\n });\r\n\r\n const {\r\n data: { subscription },\r\n } = supabase.auth.onAuthStateChange(async (event, currentSession) => {\r\n setSession(currentSession);\r\n setUser(currentSession?.user ?? null);\r\n\r\n if (event === 'SIGNED_IN' && currentSession?.user) {\r\n await fetchProfile(currentSession.user.id);\r\n ezcoderAuthIntegration.onLogin(currentSession.user);\r\n previousUserIdRef.current = currentSession.user.id;\r\n } else if (event === 'SIGNED_OUT') {\r\n setProfile(null);\r\n if (previousUserIdRef.current) {\r\n ezcoderAuthIntegration.onLogout(previousUserIdRef.current);\r\n previousUserIdRef.current = null;\r\n }\r\n } else if (event === 'USER_UPDATED' && currentSession?.user) {\r\n ezcoder.analytics.identify(currentSession.user.id, {\r\n email: currentSession.user.email,\r\n name: currentSession.user.user_metadata?.full_name,\r\n });\r\n }\r\n });\r\n\r\n return () => subscription.unsubscribe();\r\n }, [fetchProfile]);\r\n\r\n const signUp = useCallback(async (email: string, password: string, options: SignUpOptions = {}): Promise<AuthResult> => {\r\n if (!isSupabaseConfigured) {\r\n return { data: null, error: notConfiguredError() };\r\n }\r\n const { metadata = {} } = options;\r\n\r\n try {\r\n const signUpMetadata = { ...metadata };\r\n if (env.EZC_PROJECT_ID) {\r\n signUpMetadata.project_id = env.EZC_PROJECT_ID;\r\n signUpMetadata.bound_project_id = env.EZC_PROJECT_ID;\r\n }\r\n\r\n const result = await supabase.auth.signUp({\r\n email,\r\n password,\r\n options: { data: signUpMetadata },\r\n });\r\n\r\n const { data, error } = result || { data: null, error: new Error('Sign up failed') };\r\n\r\n if (error) {\r\n return { data: null, error };\r\n }\r\n\r\n if (data?.user) {\r\n const profileData: Record<string, unknown> = {\r\n id: data.user.id,\r\n email,\r\n };\r\n if (metadata.display_name) {\r\n profileData.display_name = metadata.display_name;\r\n }\r\n if (env.EZC_PROJECT_ID) {\r\n profileData.project_id = env.EZC_PROJECT_ID;\r\n }\r\n if (metadata.display_name || env.EZC_PROJECT_ID) {\r\n await supabase.from('user_profiles').upsert(profileData);\r\n }\r\n try {\r\n await supabase.rpc('assign_default_role', { user_uuid: data.user.id });\r\n } catch {\r\n // Non-blocking — role tables may not exist in all projects\r\n }\r\n ezcoderAuthIntegration.onSignup(data.user);\r\n }\r\n\r\n return { data, error: null };\r\n } catch (err: unknown) {\r\n return { data: null, error: err instanceof Error ? err : new Error('Sign up failed') };\r\n }\r\n }, []);\r\n\r\n const signIn = useCallback(async (email: string, password: string): Promise<AuthResult> => {\r\n if (!isSupabaseConfigured) {\r\n return { data: null, error: notConfiguredError() };\r\n }\r\n try {\r\n const result = await supabase.auth.signInWithPassword({ email, password });\r\n const { data, error } = result || { data: null, error: new Error('Sign in failed') };\r\n return { data, error };\r\n } catch (err: unknown) {\r\n return { data: null, error: err instanceof Error ? err : new Error('Sign in failed') };\r\n }\r\n }, []);\r\n\r\n const signInWithProvider = useCallback(async (provider: string, options: SignInWithProviderOptions = {}): Promise<AuthResult> => {\r\n if (!isSupabaseConfigured) {\r\n return { data: null, error: notConfiguredError() };\r\n }\r\n try {\r\n const result = await supabase.auth.signInWithOAuth({\r\n provider: provider as 'google' | 'github' | 'facebook' | 'apple' | 'twitter',\r\n options: {\r\n redirectTo: options.redirectTo || (typeof window !== 'undefined' ? window.location.origin : ''),\r\n ...options,\r\n },\r\n });\r\n const { data, error } = result || { data: null, error: new Error('OAuth sign in failed') };\r\n return { data, error };\r\n } catch (err: unknown) {\r\n return { data: null, error: err instanceof Error ? err : new Error('OAuth sign in failed') };\r\n }\r\n }, []);\r\n\r\n const signOut = useCallback(async (): Promise<{ error: Error | null }> => {\r\n const userId = user?.id;\r\n try {\r\n const result = await supabase.auth.signOut();\r\n const { error } = result || { error: null };\r\n if (!error && userId) {\r\n ezcoder.users.trackLogout(userId);\r\n }\r\n return { error };\r\n } catch (err: unknown) {\r\n return { error: err instanceof Error ? err : new Error('Sign out failed') };\r\n }\r\n }, [user]);\r\n\r\n const resetPassword = useCallback(async (email: string): Promise<AuthResult> => {\r\n try {\r\n const result = await supabase.auth.resetPasswordForEmail(email, {\r\n redirectTo: `${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`,\r\n });\r\n const { data, error } = result || { data: null, error: new Error('Password reset failed') };\r\n return { data, error };\r\n } catch (err: unknown) {\r\n return { data: null, error: err instanceof Error ? err : new Error('Password reset failed') };\r\n }\r\n }, []);\r\n\r\n const updateProfile = useCallback(\r\n async (updates: Partial<UserProfile>): Promise<AuthResult> => {\r\n if (!user) {\r\n return { data: null, error: new Error('Not authenticated') };\r\n }\r\n try {\r\n let query = supabase\r\n .from('user_profiles')\r\n .update(updates)\r\n .eq('id', user.id);\r\n\r\n if (env.EZC_PROJECT_ID) {\r\n query = query.eq('project_id', env.EZC_PROJECT_ID);\r\n }\r\n\r\n const result = await query.select().single();\r\n const { data, error } = result || { data: null, error: null };\r\n return { data, error };\r\n } catch (err: unknown) {\r\n return { data: null, error: err instanceof Error ? err : new Error('Update failed') };\r\n }\r\n },\r\n [user]\r\n );\r\n\r\n const value: AuthContextType = {\r\n user,\r\n profile,\r\n session,\r\n loading,\r\n isConfigured: isSupabaseConfigured,\r\n signUp,\r\n signIn,\r\n signInWithProvider,\r\n signOut,\r\n resetPassword,\r\n updateProfile,\r\n refetchProfile: fetchProfile,\r\n };\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n\r\nexport function useAuth(): AuthContextType {\r\n const context = useContext(AuthContext);\r\n if (context === undefined) {\r\n throw new Error('useAuth must be used within an AuthProvider');\r\n }\r\n return context;\r\n}\r\n\r\nexport type { AuthResult, SignUpOptions, SignInWithProviderOptions };\r\n"],"mappings":"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","names":[]}