@ezcoder.dev/sdk 1.0.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.
- package/dist/DatabaseProvider-DalP-KHC.d.ts +167 -0
- package/dist/analytics/index.d.ts +22 -1
- package/dist/analytics/index.js +79 -4
- package/dist/analytics/index.js.map +1 -1
- package/dist/animation/index.js.map +1 -1
- package/dist/auth/index.d.ts +2 -1
- package/dist/auth/index.js +25 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/chunk-CQKYANAW.js +44 -0
- package/dist/chunk-CQKYANAW.js.map +1 -0
- package/dist/{chunk-5XIZHBKE.js → chunk-HJ2EIZ4S.js} +23 -6
- package/dist/chunk-HJ2EIZ4S.js.map +1 -0
- package/dist/{chunk-G7XDUN3Z.js → chunk-I2YGB7Z6.js} +24 -44
- package/dist/chunk-I2YGB7Z6.js.map +1 -0
- package/dist/chunk-LIUE7M7K.js +72 -0
- package/dist/chunk-LIUE7M7K.js.map +1 -0
- package/dist/{chunk-YNDCD53D.js → chunk-QHB7LGCA.js} +123 -16
- package/dist/chunk-QHB7LGCA.js.map +1 -0
- package/dist/chunk-R4MDAYFO.js +642 -0
- package/dist/chunk-R4MDAYFO.js.map +1 -0
- package/dist/cms/index.js +4 -2
- package/dist/cms/index.js.map +1 -1
- package/dist/cron/index.d.ts +32 -0
- package/dist/cron/index.js +63 -0
- package/dist/cron/index.js.map +1 -0
- package/dist/database/index.d.ts +37 -0
- package/dist/database/index.js +32 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/index.d.ts +29 -0
- package/dist/email/index.js +60 -0
- package/dist/email/index.js.map +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +176 -3
- package/dist/index.js +270 -6
- package/dist/index.js.map +1 -1
- package/dist/notifications/index.d.ts +35 -1
- package/dist/notifications/index.js +61 -4
- package/dist/notifications/index.js.map +1 -1
- package/dist/payments/index.d.ts +11 -3
- package/dist/payments/index.js +101 -7
- package/dist/payments/index.js.map +1 -1
- package/dist/roles/index.js +6 -4
- package/dist/roles/index.js.map +1 -1
- package/dist/seo/index.js.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +18 -9
- package/dist/storage/index.js.map +1 -1
- package/dist/{types-DtY5lp3P.d.ts → types-1uP3V_pe.d.ts} +5 -0
- package/package.json +120 -105
- package/dist/chunk-5XIZHBKE.js.map +0 -1
- package/dist/chunk-G7XDUN3Z.js.map +0 -1
- package/dist/chunk-YNDCD53D.js.map +0 -1
package/dist/storage/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-QHB7LGCA.js";
|
|
4
|
+
import "../chunk-HJ2EIZ4S.js";
|
|
5
5
|
import {
|
|
6
|
-
features,
|
|
7
6
|
supabase
|
|
8
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-I2YGB7Z6.js";
|
|
8
|
+
import {
|
|
9
|
+
env,
|
|
10
|
+
features
|
|
11
|
+
} from "../chunk-LIUE7M7K.js";
|
|
9
12
|
|
|
10
13
|
// src/storage/useStorage.ts
|
|
11
14
|
import { useState, useCallback, useContext } from "react";
|
|
@@ -17,6 +20,12 @@ var TIER_RETENTION_DAYS = {
|
|
|
17
20
|
business: 365,
|
|
18
21
|
enterprise: -1
|
|
19
22
|
};
|
|
23
|
+
function getDefaultBucket(isPublic = false) {
|
|
24
|
+
if (isPublic && env.STORAGE_BUCKET_PUBLIC) return env.STORAGE_BUCKET_PUBLIC;
|
|
25
|
+
if (!isPublic && env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;
|
|
26
|
+
if (env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;
|
|
27
|
+
return "uploads";
|
|
28
|
+
}
|
|
20
29
|
function useStorage() {
|
|
21
30
|
const auth = useContext(AuthContext);
|
|
22
31
|
const [provider] = useState(features.storage ? "supabase" : "stub");
|
|
@@ -31,7 +40,7 @@ function useStorage() {
|
|
|
31
40
|
if (!features.storage) {
|
|
32
41
|
throw new Error("Storage is not configured. Set SUPABASE_URL to enable file storage.");
|
|
33
42
|
}
|
|
34
|
-
const bucket = options.bucket ||
|
|
43
|
+
const bucket = options.bucket || getDefaultBucket(options.public);
|
|
35
44
|
const filePath = getUserPath(options.path || `${Date.now()}_${file.name}`);
|
|
36
45
|
const { data, error } = await supabase.storage.from(bucket).upload(filePath, file, {
|
|
37
46
|
cacheControl: "3600",
|
|
@@ -54,7 +63,7 @@ function useStorage() {
|
|
|
54
63
|
type: file.type
|
|
55
64
|
};
|
|
56
65
|
}, [getUserPath]);
|
|
57
|
-
const download = useCallback(async (path, bucket =
|
|
66
|
+
const download = useCallback(async (path, bucket = getDefaultBucket()) => {
|
|
58
67
|
if (!features.storage) throw new Error("Storage is not configured");
|
|
59
68
|
const { data, error } = await supabase.storage.from(bucket).download(path);
|
|
60
69
|
if (error) throw error;
|
|
@@ -62,7 +71,7 @@ function useStorage() {
|
|
|
62
71
|
}, []);
|
|
63
72
|
const getUrl = useCallback(async (path, options = {}) => {
|
|
64
73
|
if (!features.storage) return "";
|
|
65
|
-
const bucket = options.bucket ||
|
|
74
|
+
const bucket = options.bucket || getDefaultBucket();
|
|
66
75
|
if (options.signed !== false) {
|
|
67
76
|
const { data: data2, error } = await supabase.storage.from(bucket).createSignedUrl(path, options.expiresIn || 3600);
|
|
68
77
|
if (error) throw error;
|
|
@@ -71,7 +80,7 @@ function useStorage() {
|
|
|
71
80
|
const { data } = supabase.storage.from(bucket).getPublicUrl(path);
|
|
72
81
|
return data.publicUrl;
|
|
73
82
|
}, []);
|
|
74
|
-
const list = useCallback(async (prefix, bucket =
|
|
83
|
+
const list = useCallback(async (prefix, bucket = getDefaultBucket()) => {
|
|
75
84
|
if (!features.storage) return [];
|
|
76
85
|
const searchPath = prefix || getUserPath();
|
|
77
86
|
const { data, error } = await supabase.storage.from(bucket).list(searchPath);
|
|
@@ -85,7 +94,7 @@ function useStorage() {
|
|
|
85
94
|
updated_at: item.updated_at || item.created_at || ""
|
|
86
95
|
}));
|
|
87
96
|
}, [getUserPath]);
|
|
88
|
-
const remove = useCallback(async (path, bucket =
|
|
97
|
+
const remove = useCallback(async (path, bucket = getDefaultBucket()) => {
|
|
89
98
|
if (!features.storage) throw new Error("Storage is not configured");
|
|
90
99
|
const { error } = await supabase.storage.from(bucket).remove([path]);
|
|
91
100
|
if (error) throw error;
|
|
@@ -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';\nimport { supabase } from '../core/supabase';\nimport { features } from '../core/config';\nimport { AuthContext } from '../auth/AuthProvider';\nimport type { StorageResult, StorageFile } from '../core/types';\n\ntype StorageProvider = 'supabase' | 'stub';\n\nconst TIER_RETENTION_DAYS: Record<string, number> = {\n free: 7,\n starter: 30,\n pro: 90,\n creator: 90,\n business: 365,\n enterprise: -1,\n};\n\ninterface UploadOptions {\n path?: string;\n public?: boolean;\n bucket?: string;\n}\n\ninterface UrlOptions {\n signed?: boolean;\n expiresIn?: number;\n}\n\ninterface UseStorageReturn {\n upload: (file: File, options?: UploadOptions) => Promise<StorageResult>;\n download: (path: string, bucket?: string) => Promise<Blob>;\n getUrl: (path: string, options?: UrlOptions & { bucket?: string }) => Promise<string>;\n list: (prefix?: string, bucket?: string) => Promise<StorageFile[]>;\n remove: (path: string, bucket?: string) => Promise<void>;\n isConfigured: boolean;\n provider: StorageProvider;\n retentionDays: number;\n}\n\nexport function useStorage(): UseStorageReturn {\n const auth = useContext(AuthContext);\n const [provider] = useState<StorageProvider>(features.storage ? 'supabase' : 'stub');\n const tier = (auth?.profile as unknown as Record<string, unknown>)?.subscription_tier as string || 'free';\n const retentionDays = TIER_RETENTION_DAYS[tier] ?? 7;\n\n const getUserPath = useCallback((path?: string): string => {\n const userId = auth?.user?.id;\n const basePath = userId ? `user/${userId}` : 'public';\n return path ? `${basePath}/${path}` : basePath;\n }, [auth?.user?.id]);\n\n const upload = useCallback(async (file: File, options: UploadOptions = {}): Promise<StorageResult> => {\n if (!features.storage) {\n throw new Error('Storage is not configured. Set SUPABASE_URL to enable file storage.');\n }\n\n const bucket = options.bucket || 'uploads';\n const filePath = getUserPath(options.path || `${Date.now()}_${file.name}`);\n\n const { data, error } = await supabase.storage\n .from(bucket)\n .upload(filePath, file, {\n cacheControl: '3600',\n upsert: false,\n });\n\n if (error) throw error;\n\n let url: string;\n if (options.public) {\n const { data: urlData } = supabase.storage.from(bucket).getPublicUrl(filePath);\n url = urlData.publicUrl;\n } else {\n const { data: signedData, error: signedError } = await supabase.storage\n .from(bucket)\n .createSignedUrl(filePath, 3600);\n if (signedError) throw signedError;\n url = signedData.signedUrl;\n }\n\n return {\n path: data.path,\n url,\n size: file.size,\n type: file.type,\n };\n }, [getUserPath]);\n\n const download = useCallback(async (path: string, bucket = 'uploads'): Promise<Blob> => {\n if (!features.storage) throw new Error('Storage is not configured');\n\n const { data, error } = await supabase.storage.from(bucket).download(path);\n if (error) throw error;\n return data;\n }, []);\n\n const getUrl = useCallback(async (path: string, options: UrlOptions & { bucket?: string } = {}): Promise<string> => {\n if (!features.storage) return '';\n\n const bucket = options.bucket || 'uploads';\n\n if (options.signed !== false) {\n const { data, error } = await supabase.storage\n .from(bucket)\n .createSignedUrl(path, options.expiresIn || 3600);\n if (error) throw error;\n return data.signedUrl;\n }\n\n const { data } = supabase.storage.from(bucket).getPublicUrl(path);\n return data.publicUrl;\n }, []);\n\n const list = useCallback(async (prefix?: string, bucket = 'uploads'): Promise<StorageFile[]> => {\n if (!features.storage) return [];\n\n const searchPath = prefix || getUserPath();\n const { data, error } = await supabase.storage.from(bucket).list(searchPath);\n if (error) throw error;\n\n return (data || []).map((item) => ({\n name: item.name,\n path: `${searchPath}/${item.name}`,\n size: (item.metadata as Record<string, unknown>)?.size as number || 0,\n type: (item.metadata as Record<string, unknown>)?.mimetype as string || '',\n created_at: item.created_at || '',\n updated_at: item.updated_at || item.created_at || '',\n }));\n }, [getUserPath]);\n\n const remove = useCallback(async (path: string, bucket = 'uploads'): Promise<void> => {\n if (!features.storage) throw new Error('Storage is not configured');\n\n const { error } = await supabase.storage.from(bucket).remove([path]);\n if (error) throw error;\n }, []);\n\n return { upload, download, getUrl, list, remove, isConfigured: features.storage, provider, retentionDays };\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { useStorage } from './useStorage';\nimport type { StorageResult } from '../core/types';\n\ninterface FileUploadProps {\n onUpload?: (result: StorageResult) => void;\n onError?: (error: Error) => void;\n accept?: string;\n maxSize?: number;\n multiple?: boolean;\n children?: React.ReactNode;\n className?: string;\n bucket?: string;\n public?: boolean;\n}\n\nexport function FileUpload({\n onUpload,\n onError,\n accept,\n maxSize = 10 * 1024 * 1024,\n multiple = false,\n children,\n className = '',\n bucket,\n public: isPublic = false,\n}: FileUploadProps) {\n const { upload, isConfigured } = useStorage();\n const [uploading, setUploading] = useState(false);\n const [dragOver, setDragOver] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFiles = useCallback(async (files: FileList | null) => {\n if (!files || files.length === 0) return;\n\n setUploading(true);\n\n for (const file of Array.from(files)) {\n if (file.size > maxSize) {\n onError?.(new Error(`File ${file.name} exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`));\n continue;\n }\n\n try {\n const result = await upload(file, { bucket, public: isPublic });\n onUpload?.(result);\n } catch (err: unknown) {\n onError?.(err instanceof Error ? err : new Error('Upload failed'));\n }\n }\n\n setUploading(false);\n }, [upload, maxSize, onUpload, onError, bucket, isPublic]);\n\n const handleDrop = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setDragOver(false);\n handleFiles(e.dataTransfer.files);\n }, [handleFiles]);\n\n if (!isConfigured) {\n return (\n <div style={{ padding: '20px', textAlign: 'center', color: '#6b7280', border: '1px dashed #d1d5db', borderRadius: '8px' }}>\n Storage is not configured\n </div>\n );\n }\n\n return (\n <div\n className={className}\n onDrop={handleDrop}\n onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}\n onDragLeave={() => setDragOver(false)}\n onClick={() => fileInputRef.current?.click()}\n style={{\n border: `2px dashed ${dragOver ? '#3b82f6' : '#d1d5db'}`,\n borderRadius: '8px',\n padding: '24px',\n textAlign: 'center',\n cursor: 'pointer',\n backgroundColor: dragOver ? '#eff6ff' : 'transparent',\n transition: 'all 0.2s',\n }}\n >\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={(e) => handleFiles(e.target.files)}\n style={{ display: 'none' }}\n />\n\n {children || (\n <div>\n {uploading ? (\n <p style={{ color: '#3b82f6' }}>Uploading...</p>\n ) : (\n <>\n <p style={{ fontWeight: 500, marginBottom: '4px' }}>Drop files here or click to upload</p>\n <p style={{ color: '#9ca3af', fontSize: '14px' }}>\n Max size: {Math.round(maxSize / 1024 / 1024)}MB\n </p>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useStorage } from './useStorage';\n\ninterface ImagePreviewProps {\n path: string;\n alt?: string;\n className?: string;\n width?: number | string;\n height?: number | string;\n bucket?: string;\n signed?: boolean;\n}\n\nexport function ImagePreview({ path, alt = '', className = '', width, height, bucket, signed = true }: ImagePreviewProps) {\n const { getUrl, isConfigured } = useStorage();\n const [url, setUrl] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(false);\n\n useEffect(() => {\n if (!isConfigured || !path) {\n setLoading(false);\n return;\n }\n\n getUrl(path, { signed, bucket })\n .then(setUrl)\n .catch(() => setError(true))\n .finally(() => setLoading(false));\n }, [path, signed, bucket, getUrl, isConfigured]);\n\n if (loading) {\n return (\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <span style={{ color: '#9ca3af' }}>Loading...</span>\n </div>\n );\n }\n\n if (error || !url) {\n return (\n <div style={{ width: width || '100%', height: height || '200px', backgroundColor: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>\n <span style={{ color: '#9ca3af' }}>Image not available</span>\n </div>\n );\n }\n\n return <img src={url} alt={alt} className={className} style={{ width, height, objectFit: 'cover', borderRadius: '8px' }} />;\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,UAAU,aAAa,kBAAkB;AAQlD,IAAM,sBAA8C;AAAA,EAClD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,KAAK;AAAA,EACL,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AACd;AAwBO,SAAS,aAA+B;AAC7C,QAAM,OAAO,WAAW,WAAW;AACnC,QAAM,CAAC,QAAQ,IAAI,SAA0B,SAAS,UAAU,aAAa,MAAM;AACnF,QAAM,OAAQ,MAAM,SAAgD,qBAA+B;AACnG,QAAM,gBAAgB,oBAAoB,IAAI,KAAK;AAEnD,QAAM,cAAc,YAAY,CAAC,SAA0B;AACzD,UAAM,SAAS,MAAM,MAAM;AAC3B,UAAM,WAAW,SAAS,QAAQ,MAAM,KAAK;AAC7C,WAAO,OAAO,GAAG,QAAQ,IAAI,IAAI,KAAK;AAAA,EACxC,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC;AAEnB,QAAM,SAAS,YAAY,OAAO,MAAY,UAAyB,CAAC,MAA8B;AACpG,QAAI,CAAC,SAAS,SAAS;AACrB,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AAEA,UAAM,SAAS,QAAQ,UAAU;AACjC,UAAM,WAAW,YAAY,QAAQ,QAAQ,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;AAEzE,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QACpC,KAAK,MAAM,EACX,OAAO,UAAU,MAAM;AAAA,MACtB,cAAc;AAAA,MACd,QAAQ;AAAA,IACV,CAAC;AAEH,QAAI,MAAO,OAAM;AAEjB,QAAI;AACJ,QAAI,QAAQ,QAAQ;AAClB,YAAM,EAAE,MAAM,QAAQ,IAAI,SAAS,QAAQ,KAAK,MAAM,EAAE,aAAa,QAAQ;AAC7E,YAAM,QAAQ;AAAA,IAChB,OAAO;AACL,YAAM,EAAE,MAAM,YAAY,OAAO,YAAY,IAAI,MAAM,SAAS,QAC7D,KAAK,MAAM,EACX,gBAAgB,UAAU,IAAI;AACjC,UAAI,YAAa,OAAM;AACvB,YAAM,WAAW;AAAA,IACnB;AAEA,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,WAAW,YAAY,OAAO,MAAc,SAAS,cAA6B;AACtF,QAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,2BAA2B;AAElE,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,SAAS,IAAI;AACzE,QAAI,MAAO,OAAM;AACjB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,OAAO,MAAc,UAA4C,CAAC,MAAuB;AAClH,QAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,UAAM,SAAS,QAAQ,UAAU;AAEjC,QAAI,QAAQ,WAAW,OAAO;AAC5B,YAAM,EAAE,MAAAA,OAAM,MAAM,IAAI,MAAM,SAAS,QACpC,KAAK,MAAM,EACX,gBAAgB,MAAM,QAAQ,aAAa,IAAI;AAClD,UAAI,MAAO,OAAM;AACjB,aAAOA,MAAK;AAAA,IACd;AAEA,UAAM,EAAE,KAAK,IAAI,SAAS,QAAQ,KAAK,MAAM,EAAE,aAAa,IAAI;AAChE,WAAO,KAAK;AAAA,EACd,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,YAAY,OAAO,QAAiB,SAAS,cAAsC;AAC9F,QAAI,CAAC,SAAS,QAAS,QAAO,CAAC;AAE/B,UAAM,aAAa,UAAU,YAAY;AACzC,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,KAAK,UAAU;AAC3E,QAAI,MAAO,OAAM;AAEjB,YAAQ,QAAQ,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,MACjC,MAAM,KAAK;AAAA,MACX,MAAM,GAAG,UAAU,IAAI,KAAK,IAAI;AAAA,MAChC,MAAO,KAAK,UAAsC,QAAkB;AAAA,MACpE,MAAO,KAAK,UAAsC,YAAsB;AAAA,MACxE,YAAY,KAAK,cAAc;AAAA,MAC/B,YAAY,KAAK,cAAc,KAAK,cAAc;AAAA,IACpD,EAAE;AAAA,EACJ,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,SAAS,YAAY,OAAO,MAAc,SAAS,cAA6B;AACpF,QAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,2BAA2B;AAElE,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;AACnE,QAAI,MAAO,OAAM;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,QAAQ,UAAU,QAAQ,MAAM,QAAQ,cAAc,SAAS,SAAS,UAAU,cAAc;AAC3G;;;AC1IA,SAAS,YAAAC,WAAU,QAAQ,eAAAC,oBAAmB;AA8DxC,SAqCM,UArCN,KAuCQ,YAvCR;AA9CC,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,KAAK,OAAO;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,QAAQ,WAAW;AACrB,GAAoB;AAClB,QAAM,EAAE,QAAQ,aAAa,IAAI,WAAW;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,KAAK;AAChD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,eAAe,OAAyB,IAAI;AAElD,QAAM,cAAcC,aAAY,OAAO,UAA2B;AAChE,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,iBAAa,IAAI;AAEjB,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC,UAAI,KAAK,OAAO,SAAS;AACvB,kBAAU,IAAI,MAAM,QAAQ,KAAK,IAAI,4BAA4B,KAAK,MAAM,UAAU,OAAO,IAAI,CAAC,IAAI,CAAC;AACvG;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM,EAAE,QAAQ,QAAQ,SAAS,CAAC;AAC9D,mBAAW,MAAM;AAAA,MACnB,SAAS,KAAc;AACrB,kBAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,eAAe,CAAC;AAAA,MACnE;AAAA,IACF;AAEA,iBAAa,KAAK;AAAA,EACpB,GAAG,CAAC,QAAQ,SAAS,UAAU,SAAS,QAAQ,QAAQ,CAAC;AAEzD,QAAM,aAAaA,aAAY,CAAC,MAAuB;AACrD,MAAE,eAAe;AACjB,gBAAY,KAAK;AACjB,gBAAY,EAAE,aAAa,KAAK;AAAA,EAClC,GAAG,CAAC,WAAW,CAAC;AAEhB,MAAI,CAAC,cAAc;AACjB,WACE,oBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,WAAW,UAAU,OAAO,WAAW,QAAQ,sBAAsB,cAAc,MAAM,GAAG,uCAE3H;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ;AAAA,MACR,YAAY,CAAC,MAAM;AAAE,UAAE,eAAe;AAAG,oBAAY,IAAI;AAAA,MAAG;AAAA,MAC5D,aAAa,MAAM,YAAY,KAAK;AAAA,MACpC,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,MAC3C,OAAO;AAAA,QACL,QAAQ,cAAc,WAAW,YAAY,SAAS;AAAA,QACtD,cAAc;AAAA,QACd,SAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,iBAAiB,WAAW,YAAY;AAAA,QACxC,YAAY;AAAA,MACd;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL;AAAA,YACA;AAAA,YACA,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,YAC3C,OAAO,EAAE,SAAS,OAAO;AAAA;AAAA,QAC3B;AAAA,QAEC,YACC,oBAAC,SACE,sBACC,oBAAC,OAAE,OAAO,EAAE,OAAO,UAAU,GAAG,0BAAY,IAE5C,iCACE;AAAA,8BAAC,OAAE,OAAO,EAAE,YAAY,KAAK,cAAc,MAAM,GAAG,gDAAkC;AAAA,UACtF,qBAAC,OAAE,OAAO,EAAE,OAAO,WAAW,UAAU,OAAO,GAAG;AAAA;AAAA,YACrC,KAAK,MAAM,UAAU,OAAO,IAAI;AAAA,YAAE;AAAA,aAC/C;AAAA,WACF,GAEJ;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AC9GA,SAAS,YAAAC,WAAU,iBAAiB;AAkC5B,gBAAAC,YAAA;AArBD,SAAS,aAAa,EAAE,MAAM,MAAM,IAAI,YAAY,IAAI,OAAO,QAAQ,QAAQ,SAAS,KAAK,GAAsB;AACxH,QAAM,EAAE,QAAQ,aAAa,IAAI,WAAW;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAIC,UAAiB,EAAE;AACzC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AAExC,YAAU,MAAM;AACd,QAAI,CAAC,gBAAgB,CAAC,MAAM;AAC1B,iBAAW,KAAK;AAChB;AAAA,IACF;AAEA,WAAO,MAAM,EAAE,QAAQ,OAAO,CAAC,EAC5B,KAAK,MAAM,EACX,MAAM,MAAM,SAAS,IAAI,CAAC,EAC1B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACpC,GAAG,CAAC,MAAM,QAAQ,QAAQ,QAAQ,YAAY,CAAC;AAE/C,MAAI,SAAS;AACX,WACE,gBAAAD,KAAC,SAAI,OAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,UAAU,SAAS,iBAAiB,WAAW,cAAc,OAAO,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAChL,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,UAAU,GAAG,wBAAU,GAC/C;AAAA,EAEJ;AAEA,MAAI,SAAS,CAAC,KAAK;AACjB,WACE,gBAAAA,KAAC,SAAI,OAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,UAAU,SAAS,iBAAiB,WAAW,cAAc,OAAO,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAChL,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,UAAU,GAAG,iCAAmB,GACxD;AAAA,EAEJ;AAEA,SAAO,gBAAAA,KAAC,SAAI,KAAK,KAAK,KAAU,WAAsB,OAAO,EAAE,OAAO,QAAQ,WAAW,SAAS,cAAc,MAAM,GAAG;AAC3H;","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":";;;;;;;;;;;;;AAAA,SAAS,UAAU,aAAa,kBAAkB;AAQlD,IAAM,sBAA8C;AAAA,EAClD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,KAAK;AAAA,EACL,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AACd;AAwBA,SAAS,iBAAiB,WAAW,OAAe;AAClD,MAAI,YAAY,IAAI,sBAAuB,QAAO,IAAI;AACtD,MAAI,CAAC,YAAY,IAAI,uBAAwB,QAAO,IAAI;AACxD,MAAI,IAAI,uBAAwB,QAAO,IAAI;AAC3C,SAAO;AACT;AAEO,SAAS,aAA+B;AAC7C,QAAM,OAAO,WAAW,WAAW;AACnC,QAAM,CAAC,QAAQ,IAAI,SAA0B,SAAS,UAAU,aAAa,MAAM;AACnF,QAAM,OAAQ,MAAM,SAAgD,qBAA+B;AACnG,QAAM,gBAAgB,oBAAoB,IAAI,KAAK;AAEnD,QAAM,cAAc,YAAY,CAAC,SAA0B;AACzD,UAAM,SAAS,MAAM,MAAM;AAC3B,UAAM,WAAW,SAAS,QAAQ,MAAM,KAAK;AAC7C,WAAO,OAAO,GAAG,QAAQ,IAAI,IAAI,KAAK;AAAA,EACxC,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC;AAEnB,QAAM,SAAS,YAAY,OAAO,MAAY,UAAyB,CAAC,MAA8B;AACpG,QAAI,CAAC,SAAS,SAAS;AACrB,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AAEA,UAAM,SAAS,QAAQ,UAAU,iBAAiB,QAAQ,MAAM;AAChE,UAAM,WAAW,YAAY,QAAQ,QAAQ,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;AAEzE,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QACpC,KAAK,MAAM,EACX,OAAO,UAAU,MAAM;AAAA,MACtB,cAAc;AAAA,MACd,QAAQ;AAAA,IACV,CAAC;AAEH,QAAI,MAAO,OAAM;AAEjB,QAAI;AACJ,QAAI,QAAQ,QAAQ;AAClB,YAAM,EAAE,MAAM,QAAQ,IAAI,SAAS,QAAQ,KAAK,MAAM,EAAE,aAAa,QAAQ;AAC7E,YAAM,QAAQ;AAAA,IAChB,OAAO;AACL,YAAM,EAAE,MAAM,YAAY,OAAO,YAAY,IAAI,MAAM,SAAS,QAC7D,KAAK,MAAM,EACX,gBAAgB,UAAU,IAAI;AACjC,UAAI,YAAa,OAAM;AACvB,YAAM,WAAW;AAAA,IACnB;AAEA,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,WAAW,YAAY,OAAO,MAAc,SAAS,iBAAiB,MAAqB;AAC/F,QAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,2BAA2B;AAElE,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,SAAS,IAAI;AACzE,QAAI,MAAO,OAAM;AACjB,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,OAAO,MAAc,UAA4C,CAAC,MAAuB;AAClH,QAAI,CAAC,SAAS,QAAS,QAAO;AAE9B,UAAM,SAAS,QAAQ,UAAU,iBAAiB;AAElD,QAAI,QAAQ,WAAW,OAAO;AAC5B,YAAM,EAAE,MAAAA,OAAM,MAAM,IAAI,MAAM,SAAS,QACpC,KAAK,MAAM,EACX,gBAAgB,MAAM,QAAQ,aAAa,IAAI;AAClD,UAAI,MAAO,OAAM;AACjB,aAAOA,MAAK;AAAA,IACd;AAEA,UAAM,EAAE,KAAK,IAAI,SAAS,QAAQ,KAAK,MAAM,EAAE,aAAa,IAAI;AAChE,WAAO,KAAK;AAAA,EACd,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,YAAY,OAAO,QAAiB,SAAS,iBAAiB,MAA8B;AACvG,QAAI,CAAC,SAAS,QAAS,QAAO,CAAC;AAE/B,UAAM,aAAa,UAAU,YAAY;AACzC,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,KAAK,UAAU;AAC3E,QAAI,MAAO,OAAM;AAEjB,YAAQ,QAAQ,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,MACjC,MAAM,KAAK;AAAA,MACX,MAAM,GAAG,UAAU,IAAI,KAAK,IAAI;AAAA,MAChC,MAAO,KAAK,UAAsC,QAAkB;AAAA,MACpE,MAAO,KAAK,UAAsC,YAAsB;AAAA,MACxE,YAAY,KAAK,cAAc;AAAA,MAC/B,YAAY,KAAK,cAAc,KAAK,cAAc;AAAA,IACpD,EAAE;AAAA,EACJ,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,SAAS,YAAY,OAAO,MAAc,SAAS,iBAAiB,MAAqB;AAC7F,QAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,2BAA2B;AAElE,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;AACnE,QAAI,MAAO,OAAM;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,QAAQ,UAAU,QAAQ,MAAM,QAAQ,cAAc,SAAS,SAAS,UAAU,cAAc;AAC3G;;;ACjJA,SAAS,YAAAC,WAAU,QAAQ,eAAAC,oBAAmB;AA8DxC,SAqCM,UArCN,KAuCQ,YAvCR;AA9CC,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,KAAK,OAAO;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,QAAQ,WAAW;AACrB,GAAoB;AAClB,QAAM,EAAE,QAAQ,aAAa,IAAI,WAAW;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,KAAK;AAChD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,eAAe,OAAyB,IAAI;AAElD,QAAM,cAAcC,aAAY,OAAO,UAA2B;AAChE,QAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,iBAAa,IAAI;AAEjB,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC,UAAI,KAAK,OAAO,SAAS;AACvB,kBAAU,IAAI,MAAM,QAAQ,KAAK,IAAI,4BAA4B,KAAK,MAAM,UAAU,OAAO,IAAI,CAAC,IAAI,CAAC;AACvG;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM,EAAE,QAAQ,QAAQ,SAAS,CAAC;AAC9D,mBAAW,MAAM;AAAA,MACnB,SAAS,KAAc;AACrB,kBAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,eAAe,CAAC;AAAA,MACnE;AAAA,IACF;AAEA,iBAAa,KAAK;AAAA,EACpB,GAAG,CAAC,QAAQ,SAAS,UAAU,SAAS,QAAQ,QAAQ,CAAC;AAEzD,QAAM,aAAaA,aAAY,CAAC,MAAuB;AACrD,MAAE,eAAe;AACjB,gBAAY,KAAK;AACjB,gBAAY,EAAE,aAAa,KAAK;AAAA,EAClC,GAAG,CAAC,WAAW,CAAC;AAEhB,MAAI,CAAC,cAAc;AACjB,WACE,oBAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,WAAW,UAAU,OAAO,WAAW,QAAQ,sBAAsB,cAAc,MAAM,GAAG,uCAE3H;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ;AAAA,MACR,YAAY,CAAC,MAAM;AAAE,UAAE,eAAe;AAAG,oBAAY,IAAI;AAAA,MAAG;AAAA,MAC5D,aAAa,MAAM,YAAY,KAAK;AAAA,MACpC,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,MAC3C,OAAO;AAAA,QACL,QAAQ,cAAc,WAAW,YAAY,SAAS;AAAA,QACtD,cAAc;AAAA,QACd,SAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,iBAAiB,WAAW,YAAY;AAAA,QACxC,YAAY;AAAA,MACd;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,MAAK;AAAA,YACL;AAAA,YACA;AAAA,YACA,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,YAC3C,OAAO,EAAE,SAAS,OAAO;AAAA;AAAA,QAC3B;AAAA,QAEC,YACC,oBAAC,SACE,sBACC,oBAAC,OAAE,OAAO,EAAE,OAAO,UAAU,GAAG,0BAAY,IAE5C,iCACE;AAAA,8BAAC,OAAE,OAAO,EAAE,YAAY,KAAK,cAAc,MAAM,GAAG,gDAAkC;AAAA,UACtF,qBAAC,OAAE,OAAO,EAAE,OAAO,WAAW,UAAU,OAAO,GAAG;AAAA;AAAA,YACrC,KAAK,MAAM,UAAU,OAAO,IAAI;AAAA,YAAE;AAAA,aAC/C;AAAA,WACF,GAEJ;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AC9GA,SAAS,YAAAC,WAAU,iBAAiB;AAkC5B,gBAAAC,YAAA;AArBD,SAAS,aAAa,EAAE,MAAM,MAAM,IAAI,YAAY,IAAI,OAAO,QAAQ,QAAQ,SAAS,KAAK,GAAsB;AACxH,QAAM,EAAE,QAAQ,aAAa,IAAI,WAAW;AAC5C,QAAM,CAAC,KAAK,MAAM,IAAIC,UAAiB,EAAE;AACzC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AAExC,YAAU,MAAM;AACd,QAAI,CAAC,gBAAgB,CAAC,MAAM;AAC1B,iBAAW,KAAK;AAChB;AAAA,IACF;AAEA,WAAO,MAAM,EAAE,QAAQ,OAAO,CAAC,EAC5B,KAAK,MAAM,EACX,MAAM,MAAM,SAAS,IAAI,CAAC,EAC1B,QAAQ,MAAM,WAAW,KAAK,CAAC;AAAA,EACpC,GAAG,CAAC,MAAM,QAAQ,QAAQ,QAAQ,YAAY,CAAC;AAE/C,MAAI,SAAS;AACX,WACE,gBAAAD,KAAC,SAAI,OAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,UAAU,SAAS,iBAAiB,WAAW,cAAc,OAAO,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAChL,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,UAAU,GAAG,wBAAU,GAC/C;AAAA,EAEJ;AAEA,MAAI,SAAS,CAAC,KAAK;AACjB,WACE,gBAAAA,KAAC,SAAI,OAAO,EAAE,OAAO,SAAS,QAAQ,QAAQ,UAAU,SAAS,iBAAiB,WAAW,cAAc,OAAO,SAAS,QAAQ,YAAY,UAAU,gBAAgB,SAAS,GAChL,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,UAAU,GAAG,iCAAmB,GACxD;AAAA,EAEJ;AAEA,SAAO,gBAAAA,KAAC,SAAI,KAAK,KAAK,KAAU,WAAsB,OAAO,EAAE,OAAO,QAAQ,WAAW,SAAS,cAAc,MAAM,GAAG;AAC3H;","names":["data","useState","useCallback","useState","useCallback","useState","jsx","useState"]}
|
|
@@ -36,6 +36,11 @@ interface EzcoderClient {
|
|
|
36
36
|
}) => Promise<AnalyticsResult & {
|
|
37
37
|
url?: string;
|
|
38
38
|
}>;
|
|
39
|
+
getInvoices: (customerId: string, options?: {
|
|
40
|
+
limit?: number;
|
|
41
|
+
}) => Promise<AnalyticsResult & {
|
|
42
|
+
invoices?: unknown[];
|
|
43
|
+
}>;
|
|
39
44
|
};
|
|
40
45
|
users: {
|
|
41
46
|
trackSignup: (userId: string, email: string, role?: string | null) => Promise<AnalyticsResult>;
|
package/package.json
CHANGED
|
@@ -1,105 +1,120 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ezcoder.dev/sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "EzCoder Platform SDK — auth, payments, storage, analytics, and more with zero configuration",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.js"
|
|
12
|
-
},
|
|
13
|
-
"./auth": {
|
|
14
|
-
"types": "./dist/auth/index.d.ts",
|
|
15
|
-
"import": "./dist/auth/index.js"
|
|
16
|
-
},
|
|
17
|
-
"./payments": {
|
|
18
|
-
"types": "./dist/payments/index.d.ts",
|
|
19
|
-
"import": "./dist/payments/index.js"
|
|
20
|
-
},
|
|
21
|
-
"./storage": {
|
|
22
|
-
"types": "./dist/storage/index.d.ts",
|
|
23
|
-
"import": "./dist/storage/index.js"
|
|
24
|
-
},
|
|
25
|
-
"./analytics": {
|
|
26
|
-
"types": "./dist/analytics/index.d.ts",
|
|
27
|
-
"import": "./dist/analytics/index.js"
|
|
28
|
-
},
|
|
29
|
-
"./roles": {
|
|
30
|
-
"types": "./dist/roles/index.d.ts",
|
|
31
|
-
"import": "./dist/roles/index.js"
|
|
32
|
-
},
|
|
33
|
-
"./seo": {
|
|
34
|
-
"types": "./dist/seo/index.d.ts",
|
|
35
|
-
"import": "./dist/seo/index.js"
|
|
36
|
-
},
|
|
37
|
-
"./errors": {
|
|
38
|
-
"types": "./dist/errors/index.d.ts",
|
|
39
|
-
"import": "./dist/errors/index.js"
|
|
40
|
-
},
|
|
41
|
-
"./notifications": {
|
|
42
|
-
"types": "./dist/notifications/index.d.ts",
|
|
43
|
-
"import": "./dist/notifications/index.js"
|
|
44
|
-
},
|
|
45
|
-
"./cms": {
|
|
46
|
-
"types": "./dist/cms/index.d.ts",
|
|
47
|
-
"import": "./dist/cms/index.js"
|
|
48
|
-
},
|
|
49
|
-
"./animation": {
|
|
50
|
-
"types": "./dist/animation/index.d.ts",
|
|
51
|
-
"import": "./dist/animation/index.js"
|
|
52
|
-
},
|
|
53
|
-
"./
|
|
54
|
-
"types": "./dist/
|
|
55
|
-
"import": "./dist/
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@ezcoder.dev/sdk",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "EzCoder Platform SDK — auth, payments, storage, analytics, and more with zero configuration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./auth": {
|
|
14
|
+
"types": "./dist/auth/index.d.ts",
|
|
15
|
+
"import": "./dist/auth/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./payments": {
|
|
18
|
+
"types": "./dist/payments/index.d.ts",
|
|
19
|
+
"import": "./dist/payments/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./storage": {
|
|
22
|
+
"types": "./dist/storage/index.d.ts",
|
|
23
|
+
"import": "./dist/storage/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./analytics": {
|
|
26
|
+
"types": "./dist/analytics/index.d.ts",
|
|
27
|
+
"import": "./dist/analytics/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./roles": {
|
|
30
|
+
"types": "./dist/roles/index.d.ts",
|
|
31
|
+
"import": "./dist/roles/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./seo": {
|
|
34
|
+
"types": "./dist/seo/index.d.ts",
|
|
35
|
+
"import": "./dist/seo/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./errors": {
|
|
38
|
+
"types": "./dist/errors/index.d.ts",
|
|
39
|
+
"import": "./dist/errors/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./notifications": {
|
|
42
|
+
"types": "./dist/notifications/index.d.ts",
|
|
43
|
+
"import": "./dist/notifications/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./cms": {
|
|
46
|
+
"types": "./dist/cms/index.d.ts",
|
|
47
|
+
"import": "./dist/cms/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./animation": {
|
|
50
|
+
"types": "./dist/animation/index.d.ts",
|
|
51
|
+
"import": "./dist/animation/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./database": {
|
|
54
|
+
"types": "./dist/database/index.d.ts",
|
|
55
|
+
"import": "./dist/database/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./email": {
|
|
58
|
+
"types": "./dist/email/index.d.ts",
|
|
59
|
+
"import": "./dist/email/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./cron": {
|
|
62
|
+
"types": "./dist/cron/index.d.ts",
|
|
63
|
+
"import": "./dist/cron/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./server": {
|
|
66
|
+
"types": "./dist/server/index.d.ts",
|
|
67
|
+
"import": "./dist/server/index.js"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"typesVersions": {
|
|
71
|
+
"*": {
|
|
72
|
+
"auth": ["dist/auth/index.d.ts"],
|
|
73
|
+
"payments": ["dist/payments/index.d.ts"],
|
|
74
|
+
"storage": ["dist/storage/index.d.ts"],
|
|
75
|
+
"analytics": ["dist/analytics/index.d.ts"],
|
|
76
|
+
"roles": ["dist/roles/index.d.ts"],
|
|
77
|
+
"seo": ["dist/seo/index.d.ts"],
|
|
78
|
+
"errors": ["dist/errors/index.d.ts"],
|
|
79
|
+
"notifications": ["dist/notifications/index.d.ts"],
|
|
80
|
+
"cms": ["dist/cms/index.d.ts"],
|
|
81
|
+
"animation": ["dist/animation/index.d.ts"],
|
|
82
|
+
"database": ["dist/database/index.d.ts"],
|
|
83
|
+
"email": ["dist/email/index.d.ts"],
|
|
84
|
+
"cron": ["dist/cron/index.d.ts"],
|
|
85
|
+
"server": ["dist/server/index.d.ts"]
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"files": [
|
|
89
|
+
"dist"
|
|
90
|
+
],
|
|
91
|
+
"scripts": {
|
|
92
|
+
"build": "tsup",
|
|
93
|
+
"dev": "tsup --watch",
|
|
94
|
+
"typecheck": "tsc --noEmit",
|
|
95
|
+
"clean": "rm -rf dist"
|
|
96
|
+
},
|
|
97
|
+
"peerDependencies": {
|
|
98
|
+
"react": "^18.0.0",
|
|
99
|
+
"react-dom": "^18.0.0",
|
|
100
|
+
"@supabase/supabase-js": "^2.0.0"
|
|
101
|
+
},
|
|
102
|
+
"peerDependenciesMeta": {
|
|
103
|
+
"framer-motion": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"react-helmet-async": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"stripe": {
|
|
110
|
+
"optional": true
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"devDependencies": {
|
|
114
|
+
"tsup": "^8.0.0",
|
|
115
|
+
"typescript": "^5.5.0",
|
|
116
|
+
"@types/react": "^18.0.0",
|
|
117
|
+
"@types/react-dom": "^18.0.0"
|
|
118
|
+
},
|
|
119
|
+
"license": "MIT"
|
|
120
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/platform.ts"],"sourcesContent":["import { env } from './config';\nimport type { AnalyticsResult, CheckoutOptions, EzcoderClient, AuthIntegration, AuthUser } from './types';\n\nconst isConfigured = (): boolean => Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID);\n\nfunction getSessionId(): string {\n if (typeof sessionStorage === 'undefined') return 'server';\n let sessionId = sessionStorage.getItem('ezcoder_session_id');\n if (!sessionId) {\n sessionId = `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n sessionStorage.setItem('ezcoder_session_id', sessionId);\n }\n return sessionId;\n}\n\nfunction getVisitorId(): string {\n if (typeof localStorage === 'undefined') return 'server';\n let visitorId = localStorage.getItem('ezcoder_visitor_id');\n if (!visitorId) {\n visitorId = `vis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n localStorage.setItem('ezcoder_visitor_id', visitorId);\n }\n return visitorId;\n}\n\nlet pageEntryTime: number = typeof window !== 'undefined' ? Date.now() : 0;\nlet currentPath: string = typeof window !== 'undefined' ? window.location.pathname : '/';\nlet maxScrollDepth: number = 0;\n\nconst trackPageEntry = (): void => {\n pageEntryTime = Date.now();\n currentPath = window.location.pathname;\n maxScrollDepth = 0;\n};\n\nconst getTimeOnPage = (): number => Date.now() - pageEntryTime;\n\nconst throttle = <T extends (...args: never[]) => void>(fn: T, wait: number): ((...args: Parameters<T>) => void) => {\n let lastTime = 0;\n return (...args: Parameters<T>) => {\n const now = Date.now();\n if (now - lastTime >= wait) {\n lastTime = now;\n fn(...args);\n }\n };\n};\n\nconst trackScrollDepth = (): void => {\n if (typeof window === 'undefined') return;\n const scrollTop = window.scrollY;\n const docHeight = document.documentElement.scrollHeight - window.innerHeight;\n if (docHeight > 0) {\n const scrollPercent = Math.round((scrollTop / docHeight) * 100);\n if (scrollPercent > maxScrollDepth) {\n maxScrollDepth = Math.min(scrollPercent, 100);\n }\n }\n};\n\nconst analyticsPost = async (endpoint: string, body: Record<string, unknown>): Promise<AnalyticsResult> => {\n if (!isConfigured()) {\n return { success: false, error: 'Platform not configured' };\n }\n\n try {\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n return { success: false, error };\n }\n\n return await response.json();\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return { success: false, error: message };\n }\n};\n\nconst stripePost = async (endpoint: string, body: Record<string, unknown>): Promise<AnalyticsResult & Record<string, unknown>> => {\n if (!env.EZCODER_API_URL) {\n return { success: false, error: 'Platform not configured' };\n }\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (env.EZC_SECRET_KEY) {\n headers['Authorization'] = `Bearer ${env.EZC_SECRET_KEY}`;\n }\n\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n return { success: false, error };\n }\n\n return await response.json();\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return { success: false, error: message };\n }\n};\n\nconst stripeGet = async (endpoint: string): Promise<AnalyticsResult & Record<string, unknown>> => {\n if (!env.EZCODER_API_URL) {\n return { success: false, error: 'Platform not configured' };\n }\n\n try {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (env.EZC_SECRET_KEY) {\n headers['Authorization'] = `Bearer ${env.EZC_SECRET_KEY}`;\n }\n\n const response = await fetch(`${env.EZCODER_API_URL}${endpoint}`, {\n method: 'GET',\n headers,\n });\n\n if (!response.ok) {\n const error = await response.text();\n return { success: false, error };\n }\n\n return await response.json();\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return { success: false, error: message };\n }\n};\n\nconst sendPageExit = (): void => {\n if (!isConfigured() || typeof navigator === 'undefined') return;\n\n const payload = JSON.stringify({\n type: 'page_exit',\n projectId: env.EZC_PROJECT_ID,\n sessionId: getSessionId(),\n visitorId: getVisitorId(),\n pathname: currentPath,\n timeOnPage: getTimeOnPage(),\n scrollDepth: maxScrollDepth,\n timestamp: new Date().toISOString(),\n });\n\n if (navigator.sendBeacon) {\n navigator.sendBeacon(`${env.EZCODER_API_URL}/api/analytics/collect`, payload);\n }\n};\n\nexport const ezcoder: EzcoderClient = {\n isConfigured,\n\n analytics: {\n track: (eventType: string, properties: Record<string, unknown> = {}) => {\n return analyticsPost('/api/analytics/collect', {\n type: eventType,\n projectId: env.EZC_PROJECT_ID,\n sessionId: getSessionId(),\n visitorId: getVisitorId(),\n url: typeof window !== 'undefined' ? window.location.href : '',\n pathname: typeof window !== 'undefined' ? window.location.pathname : '/',\n referrer: typeof document !== 'undefined' ? document.referrer : '',\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n screenResolution: typeof window !== 'undefined'\n ? `${window.screen.width}x${window.screen.height}`\n : '',\n viewport: typeof window !== 'undefined'\n ? `${window.innerWidth}x${window.innerHeight}`\n : '',\n timestamp: new Date().toISOString(),\n metadata: properties,\n });\n },\n\n pageView: (path?: string) => {\n trackPageEntry();\n return ezcoder.analytics.track('page_view', {\n path: path || (typeof window !== 'undefined' ? window.location.pathname : '/'),\n title: typeof document !== 'undefined' ? document.title : '',\n });\n },\n\n identify: (userId: string, traits: Record<string, unknown> = {}) => {\n return ezcoder.analytics.track('identify', { userId, ...traits });\n },\n\n error: (message: string, context: Record<string, unknown> = {}) => {\n return ezcoder.analytics.track('error', {\n message,\n ...context,\n stack: (context.stack as string) || new Error().stack,\n });\n },\n },\n\n stripe: {\n createCheckout: async (priceId: string, options: CheckoutOptions = {}) => {\n const result = await stripePost('/api/stripe/create-checkout', {\n priceId,\n projectId: env.EZC_PROJECT_ID,\n successUrl: options.successUrl || `${typeof window !== 'undefined' ? window.location.origin : ''}/payment/success`,\n cancelUrl: options.cancelUrl || `${typeof window !== 'undefined' ? window.location.origin : ''}/payment/cancel`,\n customerEmail: options.customerEmail,\n quantity: options.quantity || 1,\n });\n\n if (result.url && options.redirect !== false && typeof window !== 'undefined') {\n window.location.href = result.url as string;\n }\n\n return result;\n },\n\n getProducts: async () => {\n return { products: [], message: 'Products managed via EzCoder dashboard' };\n },\n\n verifySession: async (sessionId: string) => {\n if (!sessionId) {\n return { success: false, error: 'Session ID is required' };\n }\n return stripeGet(`/api/stripe/verify-session?session_id=${encodeURIComponent(sessionId)}`);\n },\n\n getCustomerStatus: async (options: { customerId?: string; email?: string } = {}) => {\n const params = new URLSearchParams();\n if (options.customerId) params.set('customer_id', options.customerId);\n if (options.email) params.set('email', options.email);\n\n if (!options.customerId && !options.email) {\n return { success: false, error: 'Either customerId or email is required' };\n }\n\n return stripeGet(`/api/stripe/customer-status?${params.toString()}`);\n },\n\n createPortalSession: async (customerId: string, options: { returnUrl?: string; redirect?: boolean } = {}) => {\n const result = await stripePost('/api/stripe/customer-portal', {\n customerId,\n returnUrl: options.returnUrl || window.location.href,\n });\n\n if (result.url && options.redirect !== false && typeof window !== 'undefined') {\n window.location.href = result.url as string;\n }\n\n return result;\n },\n },\n\n users: {\n trackSignup: (userId: string, email: string, role: string | null = null) => {\n return ezcoder.analytics.track('user_signup', { userId, email, role, signupMethod: 'email' });\n },\n\n trackLogin: (userId: string) => {\n return ezcoder.analytics.track('user_login', { userId });\n },\n\n trackLogout: (userId: string) => {\n return ezcoder.analytics.track('user_logout', { userId });\n },\n\n trackRoleChange: (userId: string, oldRole: string, newRole: string) => {\n return ezcoder.analytics.track('role_change', { userId, oldRole, newRole });\n },\n },\n};\n\nexport const ezcoderAuthIntegration: AuthIntegration = {\n onLogin: (user: AuthUser) => {\n if (user?.id) {\n ezcoder.analytics.identify(user.id, {\n email: user.email,\n name: user.user_metadata?.full_name,\n });\n ezcoder.users.trackLogin(user.id);\n }\n },\n onSignup: (user: AuthUser) => {\n if (user?.id) {\n ezcoder.analytics.identify(user.id, { email: user.email });\n ezcoder.users.trackSignup(user.id, user.email || '');\n }\n },\n onLogout: (userId: string) => {\n if (userId) {\n ezcoder.users.trackLogout(userId);\n }\n },\n};\n\ninterface LayoutShift extends PerformanceEntry {\n hadRecentInput: boolean;\n value: number;\n}\n\ninterface PerformanceEventTiming extends PerformanceEntry {\n processingStart: number;\n}\n\nconst trackWebVitals = (): void => {\n if (typeof window === 'undefined' || !('PerformanceObserver' in window)) return;\n\n try {\n new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const lastEntry = entries[entries.length - 1];\n if (lastEntry) {\n ezcoder.analytics.track('web_vital', {\n metric: 'LCP',\n value: Math.round(lastEntry.startTime),\n pathname: window.location.pathname,\n });\n }\n }).observe({ type: 'largest-contentful-paint', buffered: true });\n } catch { /* LCP not supported */ }\n\n try {\n new PerformanceObserver((list) => {\n const entry = list.getEntries()[0] as PerformanceEventTiming;\n if (entry) {\n ezcoder.analytics.track('web_vital', {\n metric: 'FID',\n value: Math.round(entry.processingStart - entry.startTime),\n pathname: window.location.pathname,\n });\n }\n }).observe({ type: 'first-input', buffered: true });\n } catch { /* FID not supported */ }\n\n try {\n let clsValue = 0;\n new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (!(entry as LayoutShift).hadRecentInput) {\n clsValue += (entry as LayoutShift).value;\n }\n }\n }).observe({ type: 'layout-shift', buffered: true });\n\n document.addEventListener('visibilitychange', () => {\n if (document.hidden && clsValue > 0) {\n ezcoder.analytics.track('web_vital', {\n metric: 'CLS',\n value: Math.round(clsValue * 1000) / 1000,\n pathname: window.location.pathname,\n });\n }\n });\n } catch { /* CLS not supported */ }\n};\n\nconst setupErrorTracking = (): void => {\n if (typeof window === 'undefined') return;\n\n window.onerror = (message, source, lineno, colno, error) => {\n ezcoder.analytics.track('js_error', {\n message: String(message),\n source,\n lineno,\n colno,\n stack: error?.stack,\n pathname: window.location.pathname,\n });\n return false;\n };\n\n window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {\n ezcoder.analytics.track('promise_rejection', {\n reason: event.reason?.message || String(event.reason),\n stack: event.reason?.stack,\n pathname: window.location.pathname,\n });\n });\n};\n\nif (typeof window !== 'undefined') {\n window.addEventListener('scroll', throttle(trackScrollDepth, 500), { passive: true });\n window.addEventListener('beforeunload', sendPageExit);\n\n document.addEventListener('visibilitychange', () => {\n if (!isConfigured()) return;\n if (document.hidden) {\n ezcoder.analytics.track('page_blur', {\n timeOnPage: getTimeOnPage(),\n scrollDepth: maxScrollDepth,\n pathname: currentPath,\n });\n } else {\n ezcoder.analytics.track('page_focus', { pathname: window.location.pathname });\n }\n });\n\n const originalPushState = history.pushState;\n history.pushState = function (...args: Parameters<typeof history.pushState>) {\n sendPageExit();\n originalPushState.apply(this, args);\n trackPageEntry();\n if (isConfigured()) ezcoder.analytics.pageView();\n };\n\n const originalReplaceState = history.replaceState;\n history.replaceState = function (...args: Parameters<typeof history.replaceState>) {\n originalReplaceState.apply(this, args);\n trackPageEntry();\n };\n\n window.addEventListener('popstate', () => {\n sendPageExit();\n trackPageEntry();\n if (isConfigured()) ezcoder.analytics.pageView();\n });\n\n if (isConfigured()) {\n setTimeout(() => {\n ezcoder.analytics.pageView();\n trackWebVitals();\n setupErrorTracking();\n }, 100);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/core/supabase.ts"],"sourcesContent":["const getEnv = (viteKey: string, nextKey?: string): string => {\n try {\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n return (import.meta.env[viteKey] as string) || '';\n }\n } catch {\n // import.meta not available\n }\n try {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[nextKey || viteKey] || '';\n }\n } catch {\n // process not available\n }\n return '';\n};\n\nexport const env = {\n SUPABASE_URL: getEnv('VITE_SUPABASE_URL', 'NEXT_PUBLIC_SUPABASE_URL'),\n SUPABASE_ANON_KEY: getEnv('VITE_SUPABASE_ANON_KEY', 'NEXT_PUBLIC_SUPABASE_ANON_KEY'),\n STRIPE_PUBLISHABLE_KEY: getEnv('VITE_STRIPE_PUBLISHABLE_KEY', 'NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY'),\n EZC_PROJECT_ID: getEnv('VITE_EZC_PROJECT_ID', 'NEXT_PUBLIC_EZC_PROJECT_ID'),\n EZCODER_API_URL: getEnv('VITE_EZCODER_API_URL', 'NEXT_PUBLIC_EZCODER_API_URL'),\n EZC_SECRET_KEY: getEnv('VITE_EZC_SECRET_KEY', 'EZC_SECRET_KEY'),\n S3_BUCKET: getEnv('VITE_S3_BUCKET', 'S3_BUCKET'),\n CLOUDINARY_URL: getEnv('VITE_CLOUDINARY_URL', 'CLOUDINARY_URL'),\n};\n\nexport const features = {\n auth: Boolean(env.SUPABASE_URL && env.SUPABASE_ANON_KEY),\n payments: Boolean(env.STRIPE_PUBLISHABLE_KEY),\n analytics: Boolean(env.EZCODER_API_URL && env.EZC_PROJECT_ID),\n storage: Boolean(env.SUPABASE_URL || env.S3_BUCKET || env.CLOUDINARY_URL),\n database: Boolean(env.SUPABASE_URL),\n};\n\nexport function isFeatureConfigured(feature: keyof typeof features): boolean {\n return features[feature];\n}\n","import { createClient, SupabaseClient } from '@supabase/supabase-js';\nimport { env, features } from './config';\n\nfunction createStubClient(): SupabaseClient {\n const notConfiguredError = new Error('Supabase not configured');\n\n function createQueryBuilder() {\n const builder: Record<string, unknown> = {\n select: () => builder,\n insert: () => builder,\n update: () => builder,\n upsert: () => builder,\n delete: () => builder,\n eq: () => builder,\n neq: () => builder,\n gt: () => builder,\n gte: () => builder,\n lt: () => builder,\n lte: () => builder,\n like: () => builder,\n ilike: () => builder,\n is: () => builder,\n in: () => builder,\n contains: () => builder,\n containedBy: () => builder,\n match: () => builder,\n not: () => builder,\n or: () => builder,\n filter: () => builder,\n order: () => builder,\n limit: () => builder,\n range: () => builder,\n textSearch: () => builder,\n csv: () => builder,\n single: () => Promise.resolve({ data: null, error: null }),\n maybeSingle: () => Promise.resolve({ data: null, error: null }),\n then: (resolve: (value: unknown) => void, reject?: (reason: unknown) => void) =>\n Promise.resolve({ data: [], error: null }).then(resolve, reject),\n catch: (fn: (reason: unknown) => void) =>\n Promise.resolve({ data: [], error: null }).catch(fn),\n };\n return builder;\n }\n\n return {\n auth: {\n getSession: async () => ({ data: { session: null }, error: null }),\n getUser: async () => ({ data: { user: null }, error: null }),\n signUp: async () => ({ data: null, error: notConfiguredError }),\n signInWithPassword: async () => ({ data: null, error: notConfiguredError }),\n signInWithOAuth: async () => ({ data: null, error: notConfiguredError }),\n signOut: async () => ({ error: null }),\n resetPasswordForEmail: async () => ({ data: null, error: notConfiguredError }),\n updateUser: async () => ({ data: null, error: notConfiguredError }),\n onAuthStateChange: (callback: (event: string, session: null) => void) => {\n if (typeof window !== 'undefined') {\n setTimeout(() => callback('INITIAL_SESSION', null), 0);\n }\n return { data: { subscription: { unsubscribe: () => {} } } };\n },\n },\n from: () => createQueryBuilder(),\n rpc: async () => ({ data: null, error: notConfiguredError }),\n channel: (_name: string) => ({\n on: (_event: string, _filter: unknown, _callback: unknown) => ({\n subscribe: (cb?: (status: string) => void) => {\n if (cb) cb('SUBSCRIBED');\n return { unsubscribe: () => {} };\n },\n }),\n subscribe: (cb?: (status: string) => void) => {\n if (cb) cb('SUBSCRIBED');\n return { unsubscribe: () => {} };\n },\n }),\n removeChannel: () => Promise.resolve('ok'),\n removeAllChannels: () => Promise.resolve([]),\n storage: {\n from: () => ({\n upload: async () => ({ data: null, error: notConfiguredError }),\n download: async () => ({ data: null, error: notConfiguredError }),\n getPublicUrl: () => ({ data: { publicUrl: '' } }),\n createSignedUrl: async () => ({ data: null, error: notConfiguredError }),\n list: async () => ({ data: [], error: null }),\n remove: async () => ({ data: [], error: null }),\n }),\n },\n } as unknown as SupabaseClient;\n}\n\nexport const supabase: SupabaseClient = features.auth\n ? createClient(env.SUPABASE_URL, env.SUPABASE_ANON_KEY, {\n auth: {\n autoRefreshToken: true,\n persistSession: true,\n detectSessionInUrl: true,\n },\n })\n : createStubClient();\n\nexport const isSupabaseConfigured: boolean = features.auth;\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';\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":[]}
|