@ezcoder.dev/sdk 1.0.0 → 1.1.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 +78 -5
- package/dist/analytics/index.js.map +1 -1
- package/dist/animation/index.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +3 -3
- package/dist/auth/index.js.map +1 -1
- package/dist/{chunk-G7XDUN3Z.js → chunk-2WG4O4J2.js} +24 -8
- package/dist/chunk-2WG4O4J2.js.map +1 -0
- package/dist/chunk-7VGYFCQC.js +640 -0
- package/dist/chunk-7VGYFCQC.js.map +1 -0
- package/dist/{chunk-YNDCD53D.js → chunk-AWU47M6N.js} +36 -12
- package/dist/chunk-AWU47M6N.js.map +1 -0
- package/dist/{chunk-5XIZHBKE.js → chunk-GPF4AYNG.js} +23 -6
- package/dist/chunk-GPF4AYNG.js.map +1 -0
- package/dist/cms/index.js +1 -1
- package/dist/cms/index.js.map +1 -1
- package/dist/cron/index.d.ts +15 -0
- package/dist/cron/index.js +49 -0
- package/dist/cron/index.js.map +1 -0
- package/dist/database/index.d.ts +37 -0
- package/dist/database/index.js +31 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/index.d.ts +11 -0
- package/dist/email/index.js +45 -0
- package/dist/email/index.js.map +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +11 -3
- package/dist/notifications/index.d.ts +10 -1
- package/dist/notifications/index.js +25 -3
- package/dist/notifications/index.js.map +1 -1
- package/dist/payments/index.d.ts +11 -3
- package/dist/payments/index.js +98 -6
- package/dist/payments/index.js.map +1 -1
- package/dist/roles/index.js +3 -3
- 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 +15 -8
- 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/seo/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/seo/SEOHead.tsx"],"sourcesContent":["interface SEOHeadProps {\n title?: string;\n description?: string;\n keywords?: string;\n image?: string;\n url?: string;\n type?: string;\n twitterCard?: 'summary' | 'summary_large_image';\n author?: string;\n publishedTime?: string;\n modifiedTime?: string;\n noIndex?: boolean;\n children?: React.ReactNode;\n}\n\nexport function SEOHead({\n title,\n description,\n keywords,\n image,\n url,\n type = 'website',\n twitterCard = 'summary_large_image',\n author,\n publishedTime,\n modifiedTime,\n noIndex = false,\n children,\n}: SEOHeadProps) {\n // Uses react-helmet-async if available, otherwise falls back to document manipulation\n if (typeof document === 'undefined') return null;\n\n const setMeta = (name: string, content: string, property = false) => {\n const attr = property ? 'property' : 'name';\n let el = document.querySelector(`meta[${attr}=\"${name}\"]`) as HTMLMetaElement | null;\n if (!el) {\n el = document.createElement('meta');\n el.setAttribute(attr, name);\n document.head.appendChild(el);\n }\n el.content = content;\n };\n\n if (title) {\n document.title = title;\n setMeta('og:title', title, true);\n setMeta('twitter:title', title);\n }\n if (description) {\n setMeta('description', description);\n setMeta('og:description', description, true);\n setMeta('twitter:description', description);\n }\n if (keywords) setMeta('keywords', keywords);\n if (image) {\n setMeta('og:image', image, true);\n setMeta('twitter:image', image);\n }\n if (url) setMeta('og:url', url, true);\n setMeta('og:type', type, true);\n setMeta('twitter:card', twitterCard);\n if (author) setMeta('author', author);\n if (publishedTime) setMeta('article:published_time', publishedTime, true);\n if (modifiedTime) setMeta('article:modified_time', modifiedTime, true);\n if (noIndex) setMeta('robots', 'noindex, nofollow');\n\n return <>{children}</>;\n}\n\ninterface JsonLdProps {\n data: Record<string, unknown>;\n}\n\nexport function JsonLd({ data }: JsonLdProps) {\n return (\n <script\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}\n />\n );\n}\n\ninterface OrganizationJsonLdProps {\n name: string;\n url: string;\n logo?: string;\n sameAs?: string[];\n}\n\nexport function OrganizationJsonLd({ name, url, logo, sameAs }: OrganizationJsonLdProps) {\n return (\n <JsonLd data={{\n '@context': 'https://schema.org',\n '@type': 'Organization',\n name, url, logo, sameAs,\n }} />\n );\n}\n\ninterface ArticleJsonLdProps {\n title: string;\n description: string;\n url: string;\n image?: string;\n datePublished?: string;\n authorName?: string;\n}\n\nexport function ArticleJsonLd({ title, description, url, image, datePublished, authorName }: ArticleJsonLdProps) {\n return (\n <JsonLd data={{\n '@context': 'https://schema.org',\n '@type': 'Article',\n headline: title,\n description, url, image,\n datePublished,\n author: authorName ? { '@type': 'Person', name: authorName } : undefined,\n }} />\n );\n}\n"],"mappings":";AAkES;AAnDF,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAAiB;AAEf,MAAI,OAAO,aAAa,YAAa,QAAO;AAE5C,QAAM,UAAU,CAAC,MAAc,SAAiB,WAAW,UAAU;AACnE,UAAM,OAAO,WAAW,aAAa;AACrC,QAAI,KAAK,SAAS,cAAc,QAAQ,IAAI,KAAK,IAAI,IAAI;AACzD,QAAI,CAAC,IAAI;AACP,WAAK,SAAS,cAAc,MAAM;AAClC,SAAG,aAAa,MAAM,IAAI;AAC1B,eAAS,KAAK,YAAY,EAAE;AAAA,IAC9B;AACA,OAAG,UAAU;AAAA,EACf;AAEA,MAAI,OAAO;AACT,aAAS,QAAQ;AACjB,YAAQ,YAAY,OAAO,IAAI;AAC/B,YAAQ,iBAAiB,KAAK;AAAA,EAChC;AACA,MAAI,aAAa;AACf,YAAQ,eAAe,WAAW;AAClC,YAAQ,kBAAkB,aAAa,IAAI;AAC3C,YAAQ,uBAAuB,WAAW;AAAA,EAC5C;AACA,MAAI,SAAU,SAAQ,YAAY,QAAQ;AAC1C,MAAI,OAAO;AACT,YAAQ,YAAY,OAAO,IAAI;AAC/B,YAAQ,iBAAiB,KAAK;AAAA,EAChC;AACA,MAAI,IAAK,SAAQ,UAAU,KAAK,IAAI;AACpC,UAAQ,WAAW,MAAM,IAAI;AAC7B,UAAQ,gBAAgB,WAAW;AACnC,MAAI,OAAQ,SAAQ,UAAU,MAAM;AACpC,MAAI,cAAe,SAAQ,0BAA0B,eAAe,IAAI;AACxE,MAAI,aAAc,SAAQ,yBAAyB,cAAc,IAAI;AACrE,MAAI,QAAS,SAAQ,UAAU,mBAAmB;AAElD,SAAO,gCAAG,UAAS;AACrB;AAMO,SAAS,OAAO,EAAE,KAAK,GAAgB;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,yBAAyB,EAAE,QAAQ,KAAK,UAAU,IAAI,EAAE;AAAA;AAAA,EAC1D;AAEJ;AASO,SAAS,mBAAmB,EAAE,MAAM,KAAK,MAAM,OAAO,GAA4B;AACvF,SACE,oBAAC,UAAO,MAAM;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IAAM;AAAA,IAAK;AAAA,IAAM;AAAA,EACnB,GAAG;AAEP;AAWO,SAAS,cAAc,EAAE,OAAO,aAAa,KAAK,OAAO,eAAe,WAAW,GAAuB;AAC/G,SACE,oBAAC,UAAO,MAAM;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,IAAa;AAAA,IAAK;AAAA,IAClB;AAAA,IACA,QAAQ,aAAa,EAAE,SAAS,UAAU,MAAM,WAAW,IAAI;AAAA,EACjE,GAAG;AAEP;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/seo/SEOHead.tsx"],"sourcesContent":["interface SEOHeadProps {\r\n title?: string;\r\n description?: string;\r\n keywords?: string;\r\n image?: string;\r\n url?: string;\r\n type?: string;\r\n twitterCard?: 'summary' | 'summary_large_image';\r\n author?: string;\r\n publishedTime?: string;\r\n modifiedTime?: string;\r\n noIndex?: boolean;\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport function SEOHead({\r\n title,\r\n description,\r\n keywords,\r\n image,\r\n url,\r\n type = 'website',\r\n twitterCard = 'summary_large_image',\r\n author,\r\n publishedTime,\r\n modifiedTime,\r\n noIndex = false,\r\n children,\r\n}: SEOHeadProps) {\r\n // Uses react-helmet-async if available, otherwise falls back to document manipulation\r\n if (typeof document === 'undefined') return null;\r\n\r\n const setMeta = (name: string, content: string, property = false) => {\r\n const attr = property ? 'property' : 'name';\r\n let el = document.querySelector(`meta[${attr}=\"${name}\"]`) as HTMLMetaElement | null;\r\n if (!el) {\r\n el = document.createElement('meta');\r\n el.setAttribute(attr, name);\r\n document.head.appendChild(el);\r\n }\r\n el.content = content;\r\n };\r\n\r\n if (title) {\r\n document.title = title;\r\n setMeta('og:title', title, true);\r\n setMeta('twitter:title', title);\r\n }\r\n if (description) {\r\n setMeta('description', description);\r\n setMeta('og:description', description, true);\r\n setMeta('twitter:description', description);\r\n }\r\n if (keywords) setMeta('keywords', keywords);\r\n if (image) {\r\n setMeta('og:image', image, true);\r\n setMeta('twitter:image', image);\r\n }\r\n if (url) setMeta('og:url', url, true);\r\n setMeta('og:type', type, true);\r\n setMeta('twitter:card', twitterCard);\r\n if (author) setMeta('author', author);\r\n if (publishedTime) setMeta('article:published_time', publishedTime, true);\r\n if (modifiedTime) setMeta('article:modified_time', modifiedTime, true);\r\n if (noIndex) setMeta('robots', 'noindex, nofollow');\r\n\r\n return <>{children}</>;\r\n}\r\n\r\ninterface JsonLdProps {\r\n data: Record<string, unknown>;\r\n}\r\n\r\nexport function JsonLd({ data }: JsonLdProps) {\r\n return (\r\n <script\r\n type=\"application/ld+json\"\r\n dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}\r\n />\r\n );\r\n}\r\n\r\ninterface OrganizationJsonLdProps {\r\n name: string;\r\n url: string;\r\n logo?: string;\r\n sameAs?: string[];\r\n}\r\n\r\nexport function OrganizationJsonLd({ name, url, logo, sameAs }: OrganizationJsonLdProps) {\r\n return (\r\n <JsonLd data={{\r\n '@context': 'https://schema.org',\r\n '@type': 'Organization',\r\n name, url, logo, sameAs,\r\n }} />\r\n );\r\n}\r\n\r\ninterface ArticleJsonLdProps {\r\n title: string;\r\n description: string;\r\n url: string;\r\n image?: string;\r\n datePublished?: string;\r\n authorName?: string;\r\n}\r\n\r\nexport function ArticleJsonLd({ title, description, url, image, datePublished, authorName }: ArticleJsonLdProps) {\r\n return (\r\n <JsonLd data={{\r\n '@context': 'https://schema.org',\r\n '@type': 'Article',\r\n headline: title,\r\n description, url, image,\r\n datePublished,\r\n author: authorName ? { '@type': 'Person', name: authorName } : undefined,\r\n }} />\r\n );\r\n}\r\n"],"mappings":";AAkES;AAnDF,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAAiB;AAEf,MAAI,OAAO,aAAa,YAAa,QAAO;AAE5C,QAAM,UAAU,CAAC,MAAc,SAAiB,WAAW,UAAU;AACnE,UAAM,OAAO,WAAW,aAAa;AACrC,QAAI,KAAK,SAAS,cAAc,QAAQ,IAAI,KAAK,IAAI,IAAI;AACzD,QAAI,CAAC,IAAI;AACP,WAAK,SAAS,cAAc,MAAM;AAClC,SAAG,aAAa,MAAM,IAAI;AAC1B,eAAS,KAAK,YAAY,EAAE;AAAA,IAC9B;AACA,OAAG,UAAU;AAAA,EACf;AAEA,MAAI,OAAO;AACT,aAAS,QAAQ;AACjB,YAAQ,YAAY,OAAO,IAAI;AAC/B,YAAQ,iBAAiB,KAAK;AAAA,EAChC;AACA,MAAI,aAAa;AACf,YAAQ,eAAe,WAAW;AAClC,YAAQ,kBAAkB,aAAa,IAAI;AAC3C,YAAQ,uBAAuB,WAAW;AAAA,EAC5C;AACA,MAAI,SAAU,SAAQ,YAAY,QAAQ;AAC1C,MAAI,OAAO;AACT,YAAQ,YAAY,OAAO,IAAI;AAC/B,YAAQ,iBAAiB,KAAK;AAAA,EAChC;AACA,MAAI,IAAK,SAAQ,UAAU,KAAK,IAAI;AACpC,UAAQ,WAAW,MAAM,IAAI;AAC7B,UAAQ,gBAAgB,WAAW;AACnC,MAAI,OAAQ,SAAQ,UAAU,MAAM;AACpC,MAAI,cAAe,SAAQ,0BAA0B,eAAe,IAAI;AACxE,MAAI,aAAc,SAAQ,yBAAyB,cAAc,IAAI;AACrE,MAAI,QAAS,SAAQ,UAAU,mBAAmB;AAElD,SAAO,gCAAG,UAAS;AACrB;AAMO,SAAS,OAAO,EAAE,KAAK,GAAgB;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,yBAAyB,EAAE,QAAQ,KAAK,UAAU,IAAI,EAAE;AAAA;AAAA,EAC1D;AAEJ;AASO,SAAS,mBAAmB,EAAE,MAAM,KAAK,MAAM,OAAO,GAA4B;AACvF,SACE,oBAAC,UAAO,MAAM;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IAAM;AAAA,IAAK;AAAA,IAAM;AAAA,EACnB,GAAG;AAEP;AAWO,SAAS,cAAc,EAAE,OAAO,aAAa,KAAK,OAAO,eAAe,WAAW,GAAuB;AAC/G,SACE,oBAAC,UAAO,MAAM;AAAA,IACZ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,IAAa;AAAA,IAAK;AAAA,IAClB;AAAA,IACA,QAAQ,aAAa,EAAE,SAAS,UAAU,MAAM,WAAW,IAAI;AAAA,EACjE,GAAG;AAEP;","names":[]}
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/supabase.ts","../../src/server/stripe.ts","../../src/server/storage.ts","../../src/server/middleware.ts"],"sourcesContent":["import { createClient, SupabaseClient } from '@supabase/supabase-js';\n\ninterface ServerSupabaseOptions {\n supabaseUrl?: string;\n supabaseServiceKey?: string;\n}\n\nexport function createServerSupabase(options: ServerSupabaseOptions = {}): SupabaseClient {\n const url = options.supabaseUrl || process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL || '';\n const key = options.supabaseServiceKey || process.env.SUPABASE_SERVICE_ROLE_KEY || '';\n\n if (!url || !key) {\n throw new Error('Server Supabase requires SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY');\n }\n\n return createClient(url, key, {\n auth: {\n autoRefreshToken: false,\n persistSession: false,\n },\n });\n}\n","import { createServerSupabase } from './supabase';\n\ninterface WebhookRequest {\n headers: Record<string, string | string[] | undefined> | { get(name: string): string | null };\n body?: unknown;\n rawBody?: Buffer | string;\n text?: () => Promise<string>;\n}\n\ninterface StripeEvent {\n id: string;\n type: string;\n data: {\n object: Record<string, unknown>;\n };\n}\n\ninterface HandleOptions {\n supabaseServiceKey?: string;\n supabaseUrl?: string;\n}\n\nexport async function verifyStripeWebhook(\n req: WebhookRequest,\n webhookSecret?: string\n): Promise<StripeEvent> {\n const secret = webhookSecret || process.env.STRIPE_WEBHOOK_SECRET;\n if (!secret) {\n throw new Error('STRIPE_WEBHOOK_SECRET is required');\n }\n\n let rawBody: string;\n if (typeof req.rawBody === 'string') {\n rawBody = req.rawBody;\n } else if (req.rawBody instanceof Buffer) {\n rawBody = req.rawBody.toString('utf-8');\n } else if (typeof req.text === 'function') {\n rawBody = await req.text();\n } else if (typeof req.body === 'string') {\n rawBody = req.body;\n } else {\n rawBody = JSON.stringify(req.body);\n }\n\n // Dynamic import to keep stripe as optional peer dep\n const stripe = await import('stripe');\n const Stripe = stripe.default || stripe;\n const stripeClient = new (Stripe as unknown as new (key: string) => { webhooks: { constructEvent(body: string, sig: string, secret: string): StripeEvent } })(\n process.env.STRIPE_SECRET_KEY || ''\n );\n\n const sig = typeof req.headers === 'object' && 'get' in req.headers\n ? (req.headers as { get(name: string): string | null }).get('stripe-signature') || ''\n : (req.headers as Record<string, string | string[] | undefined>)['stripe-signature'] as string || '';\n\n return stripeClient.webhooks.constructEvent(rawBody, sig, secret);\n}\n\nexport async function handleSubscriptionEvent(\n event: StripeEvent,\n options: HandleOptions = {}\n): Promise<void> {\n const supabase = createServerSupabase(options);\n const obj = event.data.object;\n\n switch (event.type) {\n case 'checkout.session.completed': {\n const customerId = obj.customer as string;\n const subscriptionId = obj.subscription as string;\n const customerEmail = obj.customer_email as string;\n\n if (customerEmail) {\n await supabase\n .from('user_profiles')\n .update({\n stripe_customer_id: customerId,\n subscription_status: 'active',\n })\n .eq('email', customerEmail);\n }\n\n void subscriptionId;\n break;\n }\n\n case 'customer.subscription.created':\n case 'customer.subscription.updated': {\n const customerId = obj.customer as string;\n const status = obj.status as string;\n const priceId = ((obj.items as Record<string, unknown>)?.data as Array<Record<string, unknown>>)?.[0]?.price as Record<string, unknown>;\n const currentPeriodEnd = obj.current_period_end as number;\n\n const tier = mapPriceToTier(priceId?.id as string);\n\n await supabase\n .from('user_profiles')\n .update({\n subscription_tier: tier,\n subscription_status: status,\n subscription_period_end: currentPeriodEnd ? new Date(currentPeriodEnd * 1000).toISOString() : null,\n })\n .eq('stripe_customer_id', customerId);\n break;\n }\n\n case 'customer.subscription.deleted': {\n const customerId = obj.customer as string;\n\n await supabase\n .from('user_profiles')\n .update({\n subscription_tier: 'free',\n subscription_status: 'canceled',\n })\n .eq('stripe_customer_id', customerId);\n break;\n }\n\n case 'invoice.payment_succeeded': {\n const customerId = obj.customer as string;\n const subscriptionId = obj.subscription as string;\n\n if (subscriptionId) {\n await supabase\n .from('user_profiles')\n .update({\n subscription_status: 'active',\n last_payment_at: new Date().toISOString(),\n })\n .eq('stripe_customer_id', customerId);\n }\n break;\n }\n\n case 'invoice.payment_failed': {\n const customerId = obj.customer as string;\n\n await supabase\n .from('user_profiles')\n .update({ subscription_status: 'past_due' })\n .eq('stripe_customer_id', customerId);\n break;\n }\n }\n}\n\nfunction mapPriceToTier(priceId: string): string {\n if (!priceId) return 'free';\n\n const mapping: Record<string, string> = {};\n const envPrefixes = ['STRIPE_CREATOR', 'STRIPE_PRO', 'STRIPE_BUSINESS', 'STRIPE_ENTERPRISE'];\n const tierNames = ['creator', 'pro', 'business', 'enterprise'];\n\n envPrefixes.forEach((prefix, i) => {\n const monthly = process.env[`${prefix}_MONTHLY_PRICE_ID`];\n const yearly = process.env[`${prefix}_YEARLY_PRICE_ID`];\n if (monthly) mapping[monthly] = tierNames[i];\n if (yearly) mapping[yearly] = tierNames[i];\n });\n\n return mapping[priceId] || 'creator';\n}\n","import { createServerSupabase } from './supabase';\n\ninterface UploadRequest {\n body?: unknown;\n file?: { buffer: Buffer; originalname: string; mimetype: string; size: number };\n formData?: () => Promise<FormData>;\n}\n\ninterface HandleUploadOptions {\n supabaseServiceKey?: string;\n supabaseUrl?: string;\n maxSizeMB?: number;\n bucket?: string;\n allowedTypes?: string[];\n}\n\ninterface UploadResult {\n success: boolean;\n path?: string;\n url?: string;\n error?: string;\n}\n\nexport async function handleUpload(\n req: UploadRequest,\n options: HandleUploadOptions = {}\n): Promise<UploadResult> {\n const supabase = createServerSupabase(options);\n const bucket = options.bucket || 'uploads';\n const maxSize = (options.maxSizeMB || 10) * 1024 * 1024;\n\n try {\n let fileBuffer: Buffer;\n let fileName: string;\n let mimeType: string;\n let fileSize: number;\n\n if (req.file) {\n fileBuffer = req.file.buffer;\n fileName = req.file.originalname;\n mimeType = req.file.mimetype;\n fileSize = req.file.size;\n } else if (typeof req.formData === 'function') {\n const formData = await req.formData();\n const file = formData.get('file') as File | null;\n if (!file) return { success: false, error: 'No file provided' };\n\n fileBuffer = Buffer.from(await file.arrayBuffer());\n fileName = file.name;\n mimeType = file.type;\n fileSize = file.size;\n } else {\n return { success: false, error: 'No file in request' };\n }\n\n if (fileSize > maxSize) {\n return { success: false, error: `File exceeds ${options.maxSizeMB || 10}MB limit` };\n }\n\n if (options.allowedTypes?.length && !options.allowedTypes.includes(mimeType)) {\n return { success: false, error: `File type ${mimeType} not allowed` };\n }\n\n const path = `uploads/${Date.now()}_${fileName}`;\n\n const { error } = await supabase.storage\n .from(bucket)\n .upload(path, fileBuffer, {\n contentType: mimeType,\n cacheControl: '3600',\n });\n\n if (error) return { success: false, error: error.message };\n\n const { data: signedData } = await supabase.storage\n .from(bucket)\n .createSignedUrl(path, 3600);\n\n return {\n success: true,\n path,\n url: signedData?.signedUrl,\n };\n } catch (err: unknown) {\n return {\n success: false,\n error: err instanceof Error ? err.message : 'Upload failed',\n };\n }\n}\n","import { createServerSupabase } from './supabase';\n\ninterface AuthRequest {\n headers: Record<string, string | string[] | undefined> | { get(name: string): string | null };\n}\n\ninterface AuthUser {\n id: string;\n email?: string;\n role?: string;\n}\n\ninterface RequireAuthOptions {\n supabaseUrl?: string;\n supabaseServiceKey?: string;\n}\n\nexport async function requireAuth(\n req: AuthRequest,\n options: RequireAuthOptions = {}\n): Promise<AuthUser> {\n const authHeader = typeof req.headers === 'object' && 'get' in req.headers\n ? (req.headers as { get(name: string): string | null }).get('authorization')\n : (req.headers as Record<string, string | string[] | undefined>)['authorization'] as string;\n\n if (!authHeader?.startsWith('Bearer ')) {\n throw new Error('Missing or invalid Authorization header');\n }\n\n const token = authHeader.slice(7);\n const supabase = createServerSupabase(options);\n\n const { data: { user }, error } = await supabase.auth.getUser(token);\n\n if (error || !user) {\n throw new Error('Invalid or expired token');\n }\n\n return {\n id: user.id,\n email: user.email,\n role: user.role,\n };\n}\n"],"mappings":";AAAA,SAAS,oBAAoC;AAOtC,SAAS,qBAAqB,UAAiC,CAAC,GAAmB;AACxF,QAAM,MAAM,QAAQ,eAAe,QAAQ,IAAI,gBAAgB,QAAQ,IAAI,4BAA4B;AACvG,QAAM,MAAM,QAAQ,sBAAsB,QAAQ,IAAI,6BAA6B;AAEnF,MAAI,CAAC,OAAO,CAAC,KAAK;AAChB,UAAM,IAAI,MAAM,qEAAqE;AAAA,EACvF;AAEA,SAAO,aAAa,KAAK,KAAK;AAAA,IAC5B,MAAM;AAAA,MACJ,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACH;;;ACCA,eAAsB,oBACpB,KACA,eACsB;AACtB,QAAM,SAAS,iBAAiB,QAAQ,IAAI;AAC5C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,MAAI;AACJ,MAAI,OAAO,IAAI,YAAY,UAAU;AACnC,cAAU,IAAI;AAAA,EAChB,WAAW,IAAI,mBAAmB,QAAQ;AACxC,cAAU,IAAI,QAAQ,SAAS,OAAO;AAAA,EACxC,WAAW,OAAO,IAAI,SAAS,YAAY;AACzC,cAAU,MAAM,IAAI,KAAK;AAAA,EAC3B,WAAW,OAAO,IAAI,SAAS,UAAU;AACvC,cAAU,IAAI;AAAA,EAChB,OAAO;AACL,cAAU,KAAK,UAAU,IAAI,IAAI;AAAA,EACnC;AAGA,QAAM,SAAS,MAAM,OAAO,QAAQ;AACpC,QAAM,SAAS,OAAO,WAAW;AACjC,QAAM,eAAe,IAAK;AAAA,IACxB,QAAQ,IAAI,qBAAqB;AAAA,EACnC;AAEA,QAAM,MAAM,OAAO,IAAI,YAAY,YAAY,SAAS,IAAI,UACvD,IAAI,QAAiD,IAAI,kBAAkB,KAAK,KAChF,IAAI,QAA0D,kBAAkB,KAAe;AAEpG,SAAO,aAAa,SAAS,eAAe,SAAS,KAAK,MAAM;AAClE;AAEA,eAAsB,wBACpB,OACA,UAAyB,CAAC,GACX;AACf,QAAM,WAAW,qBAAqB,OAAO;AAC7C,QAAM,MAAM,MAAM,KAAK;AAEvB,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,8BAA8B;AACjC,YAAM,aAAa,IAAI;AACvB,YAAM,iBAAiB,IAAI;AAC3B,YAAM,gBAAgB,IAAI;AAE1B,UAAI,eAAe;AACjB,cAAM,SACH,KAAK,eAAe,EACpB,OAAO;AAAA,UACN,oBAAoB;AAAA,UACpB,qBAAqB;AAAA,QACvB,CAAC,EACA,GAAG,SAAS,aAAa;AAAA,MAC9B;AAEA,WAAK;AACL;AAAA,IACF;AAAA,IAEA,KAAK;AAAA,IACL,KAAK,iCAAiC;AACpC,YAAM,aAAa,IAAI;AACvB,YAAM,SAAS,IAAI;AACnB,YAAM,UAAY,IAAI,OAAmC,OAA0C,CAAC,GAAG;AACvG,YAAM,mBAAmB,IAAI;AAE7B,YAAM,OAAO,eAAe,SAAS,EAAY;AAEjD,YAAM,SACH,KAAK,eAAe,EACpB,OAAO;AAAA,QACN,mBAAmB;AAAA,QACnB,qBAAqB;AAAA,QACrB,yBAAyB,mBAAmB,IAAI,KAAK,mBAAmB,GAAI,EAAE,YAAY,IAAI;AAAA,MAChG,CAAC,EACA,GAAG,sBAAsB,UAAU;AACtC;AAAA,IACF;AAAA,IAEA,KAAK,iCAAiC;AACpC,YAAM,aAAa,IAAI;AAEvB,YAAM,SACH,KAAK,eAAe,EACpB,OAAO;AAAA,QACN,mBAAmB;AAAA,QACnB,qBAAqB;AAAA,MACvB,CAAC,EACA,GAAG,sBAAsB,UAAU;AACtC;AAAA,IACF;AAAA,IAEA,KAAK,6BAA6B;AAChC,YAAM,aAAa,IAAI;AACvB,YAAM,iBAAiB,IAAI;AAE3B,UAAI,gBAAgB;AAClB,cAAM,SACH,KAAK,eAAe,EACpB,OAAO;AAAA,UACN,qBAAqB;AAAA,UACrB,kBAAiB,oBAAI,KAAK,GAAE,YAAY;AAAA,QAC1C,CAAC,EACA,GAAG,sBAAsB,UAAU;AAAA,MACxC;AACA;AAAA,IACF;AAAA,IAEA,KAAK,0BAA0B;AAC7B,YAAM,aAAa,IAAI;AAEvB,YAAM,SACH,KAAK,eAAe,EACpB,OAAO,EAAE,qBAAqB,WAAW,CAAC,EAC1C,GAAG,sBAAsB,UAAU;AACtC;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,SAAyB;AAC/C,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,UAAkC,CAAC;AACzC,QAAM,cAAc,CAAC,kBAAkB,cAAc,mBAAmB,mBAAmB;AAC3F,QAAM,YAAY,CAAC,WAAW,OAAO,YAAY,YAAY;AAE7D,cAAY,QAAQ,CAAC,QAAQ,MAAM;AACjC,UAAM,UAAU,QAAQ,IAAI,GAAG,MAAM,mBAAmB;AACxD,UAAM,SAAS,QAAQ,IAAI,GAAG,MAAM,kBAAkB;AACtD,QAAI,QAAS,SAAQ,OAAO,IAAI,UAAU,CAAC;AAC3C,QAAI,OAAQ,SAAQ,MAAM,IAAI,UAAU,CAAC;AAAA,EAC3C,CAAC;AAED,SAAO,QAAQ,OAAO,KAAK;AAC7B;;;AC1IA,eAAsB,aACpB,KACA,UAA+B,CAAC,GACT;AACvB,QAAM,WAAW,qBAAqB,OAAO;AAC7C,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,WAAW,QAAQ,aAAa,MAAM,OAAO;AAEnD,MAAI;AACF,QAAI;AACJ,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,IAAI,MAAM;AACZ,mBAAa,IAAI,KAAK;AACtB,iBAAW,IAAI,KAAK;AACpB,iBAAW,IAAI,KAAK;AACpB,iBAAW,IAAI,KAAK;AAAA,IACtB,WAAW,OAAO,IAAI,aAAa,YAAY;AAC7C,YAAM,WAAW,MAAM,IAAI,SAAS;AACpC,YAAM,OAAO,SAAS,IAAI,MAAM;AAChC,UAAI,CAAC,KAAM,QAAO,EAAE,SAAS,OAAO,OAAO,mBAAmB;AAE9D,mBAAa,OAAO,KAAK,MAAM,KAAK,YAAY,CAAC;AACjD,iBAAW,KAAK;AAChB,iBAAW,KAAK;AAChB,iBAAW,KAAK;AAAA,IAClB,OAAO;AACL,aAAO,EAAE,SAAS,OAAO,OAAO,qBAAqB;AAAA,IACvD;AAEA,QAAI,WAAW,SAAS;AACtB,aAAO,EAAE,SAAS,OAAO,OAAO,gBAAgB,QAAQ,aAAa,EAAE,WAAW;AAAA,IACpF;AAEA,QAAI,QAAQ,cAAc,UAAU,CAAC,QAAQ,aAAa,SAAS,QAAQ,GAAG;AAC5E,aAAO,EAAE,SAAS,OAAO,OAAO,aAAa,QAAQ,eAAe;AAAA,IACtE;AAEA,UAAM,OAAO,WAAW,KAAK,IAAI,CAAC,IAAI,QAAQ;AAE9C,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,QAC9B,KAAK,MAAM,EACX,OAAO,MAAM,YAAY;AAAA,MACxB,aAAa;AAAA,MACb,cAAc;AAAA,IAChB,CAAC;AAEH,QAAI,MAAO,QAAO,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ;AAEzD,UAAM,EAAE,MAAM,WAAW,IAAI,MAAM,SAAS,QACzC,KAAK,MAAM,EACX,gBAAgB,MAAM,IAAI;AAE7B,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,KAAK,YAAY;AAAA,IACnB;AAAA,EACF,SAAS,KAAc;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,IAC9C;AAAA,EACF;AACF;;;ACxEA,eAAsB,YACpB,KACA,UAA8B,CAAC,GACZ;AACnB,QAAM,aAAa,OAAO,IAAI,YAAY,YAAY,SAAS,IAAI,UAC9D,IAAI,QAAiD,IAAI,eAAe,IACxE,IAAI,QAA0D,eAAe;AAElF,MAAI,CAAC,YAAY,WAAW,SAAS,GAAG;AACtC,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,QAAM,QAAQ,WAAW,MAAM,CAAC;AAChC,QAAM,WAAW,qBAAqB,OAAO;AAE7C,QAAM,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,IAAI,MAAM,SAAS,KAAK,QAAQ,KAAK;AAEnE,MAAI,SAAS,CAAC,MAAM;AAClB,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,EACb;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/supabase.ts","../../src/server/stripe.ts","../../src/server/storage.ts","../../src/server/middleware.ts"],"sourcesContent":["import { createClient, SupabaseClient } from '@supabase/supabase-js';\r\n\r\ninterface ServerSupabaseOptions {\r\n supabaseUrl?: string;\r\n supabaseServiceKey?: string;\r\n}\r\n\r\nexport function createServerSupabase(options: ServerSupabaseOptions = {}): SupabaseClient {\r\n const url = options.supabaseUrl || process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL || '';\r\n const key = options.supabaseServiceKey || process.env.SUPABASE_SERVICE_ROLE_KEY || '';\r\n\r\n if (!url || !key) {\r\n throw new Error('Server Supabase requires SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY');\r\n }\r\n\r\n return createClient(url, key, {\r\n auth: {\r\n autoRefreshToken: false,\r\n persistSession: false,\r\n },\r\n });\r\n}\r\n","import { createServerSupabase } from './supabase';\r\n\r\ninterface WebhookRequest {\r\n headers: Record<string, string | string[] | undefined> | { get(name: string): string | null };\r\n body?: unknown;\r\n rawBody?: Buffer | string;\r\n text?: () => Promise<string>;\r\n}\r\n\r\ninterface StripeEvent {\r\n id: string;\r\n type: string;\r\n data: {\r\n object: Record<string, unknown>;\r\n };\r\n}\r\n\r\ninterface HandleOptions {\r\n supabaseServiceKey?: string;\r\n supabaseUrl?: string;\r\n}\r\n\r\nexport async function verifyStripeWebhook(\r\n req: WebhookRequest,\r\n webhookSecret?: string\r\n): Promise<StripeEvent> {\r\n const secret = webhookSecret || process.env.STRIPE_WEBHOOK_SECRET;\r\n if (!secret) {\r\n throw new Error('STRIPE_WEBHOOK_SECRET is required');\r\n }\r\n\r\n let rawBody: string;\r\n if (typeof req.rawBody === 'string') {\r\n rawBody = req.rawBody;\r\n } else if (req.rawBody instanceof Buffer) {\r\n rawBody = req.rawBody.toString('utf-8');\r\n } else if (typeof req.text === 'function') {\r\n rawBody = await req.text();\r\n } else if (typeof req.body === 'string') {\r\n rawBody = req.body;\r\n } else {\r\n rawBody = JSON.stringify(req.body);\r\n }\r\n\r\n // Dynamic import to keep stripe as optional peer dep\r\n const stripe = await import('stripe');\r\n const Stripe = stripe.default || stripe;\r\n const stripeClient = new (Stripe as unknown as new (key: string) => { webhooks: { constructEvent(body: string, sig: string, secret: string): StripeEvent } })(\r\n process.env.STRIPE_SECRET_KEY || ''\r\n );\r\n\r\n const sig = typeof req.headers === 'object' && 'get' in req.headers\r\n ? (req.headers as { get(name: string): string | null }).get('stripe-signature') || ''\r\n : (req.headers as Record<string, string | string[] | undefined>)['stripe-signature'] as string || '';\r\n\r\n return stripeClient.webhooks.constructEvent(rawBody, sig, secret);\r\n}\r\n\r\nexport async function handleSubscriptionEvent(\r\n event: StripeEvent,\r\n options: HandleOptions = {}\r\n): Promise<void> {\r\n const supabase = createServerSupabase(options);\r\n const obj = event.data.object;\r\n\r\n switch (event.type) {\r\n case 'checkout.session.completed': {\r\n const customerId = obj.customer as string;\r\n const subscriptionId = obj.subscription as string;\r\n const customerEmail = obj.customer_email as string;\r\n\r\n if (customerEmail) {\r\n await supabase\r\n .from('user_profiles')\r\n .update({\r\n stripe_customer_id: customerId,\r\n subscription_status: 'active',\r\n })\r\n .eq('email', customerEmail);\r\n }\r\n\r\n void subscriptionId;\r\n break;\r\n }\r\n\r\n case 'customer.subscription.created':\r\n case 'customer.subscription.updated': {\r\n const customerId = obj.customer as string;\r\n const status = obj.status as string;\r\n const priceId = ((obj.items as Record<string, unknown>)?.data as Array<Record<string, unknown>>)?.[0]?.price as Record<string, unknown>;\r\n const currentPeriodEnd = obj.current_period_end as number;\r\n\r\n const tier = mapPriceToTier(priceId?.id as string);\r\n\r\n await supabase\r\n .from('user_profiles')\r\n .update({\r\n subscription_tier: tier,\r\n subscription_status: status,\r\n subscription_period_end: currentPeriodEnd ? new Date(currentPeriodEnd * 1000).toISOString() : null,\r\n })\r\n .eq('stripe_customer_id', customerId);\r\n break;\r\n }\r\n\r\n case 'customer.subscription.deleted': {\r\n const customerId = obj.customer as string;\r\n\r\n await supabase\r\n .from('user_profiles')\r\n .update({\r\n subscription_tier: 'free',\r\n subscription_status: 'canceled',\r\n })\r\n .eq('stripe_customer_id', customerId);\r\n break;\r\n }\r\n\r\n case 'invoice.payment_succeeded': {\r\n const customerId = obj.customer as string;\r\n const subscriptionId = obj.subscription as string;\r\n\r\n if (subscriptionId) {\r\n await supabase\r\n .from('user_profiles')\r\n .update({\r\n subscription_status: 'active',\r\n last_payment_at: new Date().toISOString(),\r\n })\r\n .eq('stripe_customer_id', customerId);\r\n }\r\n break;\r\n }\r\n\r\n case 'invoice.payment_failed': {\r\n const customerId = obj.customer as string;\r\n\r\n await supabase\r\n .from('user_profiles')\r\n .update({ subscription_status: 'past_due' })\r\n .eq('stripe_customer_id', customerId);\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction mapPriceToTier(priceId: string): string {\r\n if (!priceId) return 'free';\r\n\r\n const mapping: Record<string, string> = {};\r\n const envPrefixes = ['STRIPE_CREATOR', 'STRIPE_PRO', 'STRIPE_BUSINESS', 'STRIPE_ENTERPRISE'];\r\n const tierNames = ['creator', 'pro', 'business', 'enterprise'];\r\n\r\n envPrefixes.forEach((prefix, i) => {\r\n const monthly = process.env[`${prefix}_MONTHLY_PRICE_ID`];\r\n const yearly = process.env[`${prefix}_YEARLY_PRICE_ID`];\r\n if (monthly) mapping[monthly] = tierNames[i];\r\n if (yearly) mapping[yearly] = tierNames[i];\r\n });\r\n\r\n return mapping[priceId] || 'creator';\r\n}\r\n","import { createServerSupabase } from './supabase';\r\n\r\ninterface UploadRequest {\r\n body?: unknown;\r\n file?: { buffer: Buffer; originalname: string; mimetype: string; size: number };\r\n formData?: () => Promise<FormData>;\r\n}\r\n\r\ninterface HandleUploadOptions {\r\n supabaseServiceKey?: string;\r\n supabaseUrl?: string;\r\n maxSizeMB?: number;\r\n bucket?: string;\r\n allowedTypes?: string[];\r\n}\r\n\r\ninterface UploadResult {\r\n success: boolean;\r\n path?: string;\r\n url?: string;\r\n error?: string;\r\n}\r\n\r\nexport async function handleUpload(\r\n req: UploadRequest,\r\n options: HandleUploadOptions = {}\r\n): Promise<UploadResult> {\r\n const supabase = createServerSupabase(options);\r\n const bucket = options.bucket || 'uploads';\r\n const maxSize = (options.maxSizeMB || 10) * 1024 * 1024;\r\n\r\n try {\r\n let fileBuffer: Buffer;\r\n let fileName: string;\r\n let mimeType: string;\r\n let fileSize: number;\r\n\r\n if (req.file) {\r\n fileBuffer = req.file.buffer;\r\n fileName = req.file.originalname;\r\n mimeType = req.file.mimetype;\r\n fileSize = req.file.size;\r\n } else if (typeof req.formData === 'function') {\r\n const formData = await req.formData();\r\n const file = formData.get('file') as File | null;\r\n if (!file) return { success: false, error: 'No file provided' };\r\n\r\n fileBuffer = Buffer.from(await file.arrayBuffer());\r\n fileName = file.name;\r\n mimeType = file.type;\r\n fileSize = file.size;\r\n } else {\r\n return { success: false, error: 'No file in request' };\r\n }\r\n\r\n if (fileSize > maxSize) {\r\n return { success: false, error: `File exceeds ${options.maxSizeMB || 10}MB limit` };\r\n }\r\n\r\n if (options.allowedTypes?.length && !options.allowedTypes.includes(mimeType)) {\r\n return { success: false, error: `File type ${mimeType} not allowed` };\r\n }\r\n\r\n const path = `uploads/${Date.now()}_${fileName}`;\r\n\r\n const { error } = await supabase.storage\r\n .from(bucket)\r\n .upload(path, fileBuffer, {\r\n contentType: mimeType,\r\n cacheControl: '3600',\r\n });\r\n\r\n if (error) return { success: false, error: error.message };\r\n\r\n const { data: signedData } = await supabase.storage\r\n .from(bucket)\r\n .createSignedUrl(path, 3600);\r\n\r\n return {\r\n success: true,\r\n path,\r\n url: signedData?.signedUrl,\r\n };\r\n } catch (err: unknown) {\r\n return {\r\n success: false,\r\n error: err instanceof Error ? err.message : 'Upload failed',\r\n };\r\n }\r\n}\r\n","import { createServerSupabase } from './supabase';\r\n\r\ninterface AuthRequest {\r\n headers: Record<string, string | string[] | undefined> | { get(name: string): string | null };\r\n}\r\n\r\ninterface AuthUser {\r\n id: string;\r\n email?: string;\r\n role?: string;\r\n}\r\n\r\ninterface RequireAuthOptions {\r\n supabaseUrl?: string;\r\n supabaseServiceKey?: string;\r\n}\r\n\r\nexport async function requireAuth(\r\n req: AuthRequest,\r\n options: RequireAuthOptions = {}\r\n): Promise<AuthUser> {\r\n const authHeader = typeof req.headers === 'object' && 'get' in req.headers\r\n ? (req.headers as { get(name: string): string | null }).get('authorization')\r\n : (req.headers as Record<string, string | string[] | undefined>)['authorization'] as string;\r\n\r\n if (!authHeader?.startsWith('Bearer ')) {\r\n throw new Error('Missing or invalid Authorization header');\r\n }\r\n\r\n const token = authHeader.slice(7);\r\n const supabase = createServerSupabase(options);\r\n\r\n const { data: { user }, error } = await supabase.auth.getUser(token);\r\n\r\n if (error || !user) {\r\n throw new Error('Invalid or expired token');\r\n }\r\n\r\n return {\r\n id: user.id,\r\n email: user.email,\r\n role: user.role,\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/storage/index.d.ts
CHANGED
package/dist/storage/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthContext
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-AWU47M6N.js";
|
|
4
|
+
import "../chunk-GPF4AYNG.js";
|
|
5
5
|
import {
|
|
6
|
+
env,
|
|
6
7
|
features,
|
|
7
8
|
supabase
|
|
8
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-2WG4O4J2.js";
|
|
9
10
|
|
|
10
11
|
// src/storage/useStorage.ts
|
|
11
12
|
import { useState, useCallback, useContext } from "react";
|
|
@@ -17,6 +18,12 @@ var TIER_RETENTION_DAYS = {
|
|
|
17
18
|
business: 365,
|
|
18
19
|
enterprise: -1
|
|
19
20
|
};
|
|
21
|
+
function getDefaultBucket(isPublic = false) {
|
|
22
|
+
if (isPublic && env.STORAGE_BUCKET_PUBLIC) return env.STORAGE_BUCKET_PUBLIC;
|
|
23
|
+
if (!isPublic && env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;
|
|
24
|
+
if (env.STORAGE_BUCKET_PRIVATE) return env.STORAGE_BUCKET_PRIVATE;
|
|
25
|
+
return "uploads";
|
|
26
|
+
}
|
|
20
27
|
function useStorage() {
|
|
21
28
|
const auth = useContext(AuthContext);
|
|
22
29
|
const [provider] = useState(features.storage ? "supabase" : "stub");
|
|
@@ -31,7 +38,7 @@ function useStorage() {
|
|
|
31
38
|
if (!features.storage) {
|
|
32
39
|
throw new Error("Storage is not configured. Set SUPABASE_URL to enable file storage.");
|
|
33
40
|
}
|
|
34
|
-
const bucket = options.bucket ||
|
|
41
|
+
const bucket = options.bucket || getDefaultBucket(options.public);
|
|
35
42
|
const filePath = getUserPath(options.path || `${Date.now()}_${file.name}`);
|
|
36
43
|
const { data, error } = await supabase.storage.from(bucket).upload(filePath, file, {
|
|
37
44
|
cacheControl: "3600",
|
|
@@ -54,7 +61,7 @@ function useStorage() {
|
|
|
54
61
|
type: file.type
|
|
55
62
|
};
|
|
56
63
|
}, [getUserPath]);
|
|
57
|
-
const download = useCallback(async (path, bucket =
|
|
64
|
+
const download = useCallback(async (path, bucket = getDefaultBucket()) => {
|
|
58
65
|
if (!features.storage) throw new Error("Storage is not configured");
|
|
59
66
|
const { data, error } = await supabase.storage.from(bucket).download(path);
|
|
60
67
|
if (error) throw error;
|
|
@@ -62,7 +69,7 @@ function useStorage() {
|
|
|
62
69
|
}, []);
|
|
63
70
|
const getUrl = useCallback(async (path, options = {}) => {
|
|
64
71
|
if (!features.storage) return "";
|
|
65
|
-
const bucket = options.bucket ||
|
|
72
|
+
const bucket = options.bucket || getDefaultBucket();
|
|
66
73
|
if (options.signed !== false) {
|
|
67
74
|
const { data: data2, error } = await supabase.storage.from(bucket).createSignedUrl(path, options.expiresIn || 3600);
|
|
68
75
|
if (error) throw error;
|
|
@@ -71,7 +78,7 @@ function useStorage() {
|
|
|
71
78
|
const { data } = supabase.storage.from(bucket).getPublicUrl(path);
|
|
72
79
|
return data.publicUrl;
|
|
73
80
|
}, []);
|
|
74
|
-
const list = useCallback(async (prefix, bucket =
|
|
81
|
+
const list = useCallback(async (prefix, bucket = getDefaultBucket()) => {
|
|
75
82
|
if (!features.storage) return [];
|
|
76
83
|
const searchPath = prefix || getUserPath();
|
|
77
84
|
const { data, error } = await supabase.storage.from(bucket).list(searchPath);
|
|
@@ -85,7 +92,7 @@ function useStorage() {
|
|
|
85
92
|
updated_at: item.updated_at || item.created_at || ""
|
|
86
93
|
}));
|
|
87
94
|
}, [getUserPath]);
|
|
88
|
-
const remove = useCallback(async (path, bucket =
|
|
95
|
+
const remove = useCallback(async (path, bucket = getDefaultBucket()) => {
|
|
89
96
|
if (!features.storage) throw new Error("Storage is not configured");
|
|
90
97
|
const { error } = await supabase.storage.from(bucket).remove([path]);
|
|
91
98
|
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":"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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"]}
|
|
@@ -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.1.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":";;;;;AAGA,IAAM,eAAe,MAAe,QAAQ,IAAI,mBAAmB,IAAI,cAAc;AAErF,SAAS,eAAuB;AAC9B,MAAI,OAAO,mBAAmB,YAAa,QAAO;AAClD,MAAI,YAAY,eAAe,QAAQ,oBAAoB;AAC3D,MAAI,CAAC,WAAW;AACd,gBAAY,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACzE,mBAAe,QAAQ,sBAAsB,SAAS;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,eAAuB;AAC9B,MAAI,OAAO,iBAAiB,YAAa,QAAO;AAChD,MAAI,YAAY,aAAa,QAAQ,oBAAoB;AACzD,MAAI,CAAC,WAAW;AACd,gBAAY,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACxE,iBAAa,QAAQ,sBAAsB,SAAS;AAAA,EACtD;AACA,SAAO;AACT;AAEA,IAAI,gBAAwB,OAAO,WAAW,cAAc,KAAK,IAAI,IAAI;AACzE,IAAI,cAAsB,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AACrF,IAAI,iBAAyB;AAE7B,IAAM,iBAAiB,MAAY;AACjC,kBAAgB,KAAK,IAAI;AACzB,gBAAc,OAAO,SAAS;AAC9B,mBAAiB;AACnB;AAEA,IAAM,gBAAgB,MAAc,KAAK,IAAI,IAAI;AAEjD,IAAM,WAAW,CAAuC,IAAO,SAAqD;AAClH,MAAI,WAAW;AACf,SAAO,IAAI,SAAwB;AACjC,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,MAAM,YAAY,MAAM;AAC1B,iBAAW;AACX,SAAG,GAAG,IAAI;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,mBAAmB,MAAY;AACnC,MAAI,OAAO,WAAW,YAAa;AACnC,QAAM,YAAY,OAAO;AACzB,QAAM,YAAY,SAAS,gBAAgB,eAAe,OAAO;AACjE,MAAI,YAAY,GAAG;AACjB,UAAM,gBAAgB,KAAK,MAAO,YAAY,YAAa,GAAG;AAC9D,QAAI,gBAAgB,gBAAgB;AAClC,uBAAiB,KAAK,IAAI,eAAe,GAAG;AAAA,IAC9C;AAAA,EACF;AACF;AAEA,IAAM,gBAAgB,OAAO,UAAkB,SAA4D;AACzG,MAAI,CAAC,aAAa,GAAG;AACnB,WAAO,EAAE,SAAS,OAAO,OAAO,0BAA0B;AAAA,EAC5D;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,eAAe,GAAG,QAAQ,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,aAAO,EAAE,SAAS,OAAO,MAAM;AAAA,IACjC;AAEA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,SAAS,OAAgB;AACvB,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,EAAE,SAAS,OAAO,OAAO,QAAQ;AAAA,EAC1C;AACF;AAEA,IAAM,aAAa,OAAO,UAAkB,SAAsF;AAChI,MAAI,CAAC,IAAI,iBAAiB;AACxB,WAAO,EAAE,SAAS,OAAO,OAAO,0BAA0B;AAAA,EAC5D;AAEA,MAAI;AACF,UAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,QAAI,IAAI,gBAAgB;AACtB,cAAQ,eAAe,IAAI,UAAU,IAAI,cAAc;AAAA,IACzD;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,eAAe,GAAG,QAAQ,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,aAAO,EAAE,SAAS,OAAO,MAAM;AAAA,IACjC;AAEA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,SAAS,OAAgB;AACvB,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,EAAE,SAAS,OAAO,OAAO,QAAQ;AAAA,EAC1C;AACF;AAEA,IAAM,YAAY,OAAO,aAAyE;AAChG,MAAI,CAAC,IAAI,iBAAiB;AACxB,WAAO,EAAE,SAAS,OAAO,OAAO,0BAA0B;AAAA,EAC5D;AAEA,MAAI;AACF,UAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,QAAI,IAAI,gBAAgB;AACtB,cAAQ,eAAe,IAAI,UAAU,IAAI,cAAc;AAAA,IACzD;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,IAAI,eAAe,GAAG,QAAQ,IAAI;AAAA,MAChE,QAAQ;AAAA,MACR;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,aAAO,EAAE,SAAS,OAAO,MAAM;AAAA,IACjC;AAEA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,SAAS,OAAgB;AACvB,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,EAAE,SAAS,OAAO,OAAO,QAAQ;AAAA,EAC1C;AACF;AAEA,IAAM,eAAe,MAAY;AAC/B,MAAI,CAAC,aAAa,KAAK,OAAO,cAAc,YAAa;AAEzD,QAAM,UAAU,KAAK,UAAU;AAAA,IAC7B,MAAM;AAAA,IACN,WAAW,IAAI;AAAA,IACf,WAAW,aAAa;AAAA,IACxB,WAAW,aAAa;AAAA,IACxB,UAAU;AAAA,IACV,YAAY,cAAc;AAAA,IAC1B,aAAa;AAAA,IACb,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC,CAAC;AAED,MAAI,UAAU,YAAY;AACxB,cAAU,WAAW,GAAG,IAAI,eAAe,0BAA0B,OAAO;AAAA,EAC9E;AACF;AAEO,IAAM,UAAyB;AAAA,EACpC;AAAA,EAEA,WAAW;AAAA,IACT,OAAO,CAAC,WAAmB,aAAsC,CAAC,MAAM;AACtE,aAAO,cAAc,0BAA0B;AAAA,QAC7C,MAAM;AAAA,QACN,WAAW,IAAI;AAAA,QACf,WAAW,aAAa;AAAA,QACxB,WAAW,aAAa;AAAA,QACxB,KAAK,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO;AAAA,QAC5D,UAAU,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,QACrE,UAAU,OAAO,aAAa,cAAc,SAAS,WAAW;AAAA,QAChE,WAAW,OAAO,cAAc,cAAc,UAAU,YAAY;AAAA,QACpE,kBAAkB,OAAO,WAAW,cAChC,GAAG,OAAO,OAAO,KAAK,IAAI,OAAO,OAAO,MAAM,KAC9C;AAAA,QACJ,UAAU,OAAO,WAAW,cACxB,GAAG,OAAO,UAAU,IAAI,OAAO,WAAW,KAC1C;AAAA,QACJ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,IAEA,UAAU,CAAC,SAAkB;AAC3B,qBAAe;AACf,aAAO,QAAQ,UAAU,MAAM,aAAa;AAAA,QAC1C,MAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;AAAA,QAC1E,OAAO,OAAO,aAAa,cAAc,SAAS,QAAQ;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,IAEA,UAAU,CAAC,QAAgB,SAAkC,CAAC,MAAM;AAClE,aAAO,QAAQ,UAAU,MAAM,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC;AAAA,IAClE;AAAA,IAEA,OAAO,CAAC,SAAiB,UAAmC,CAAC,MAAM;AACjE,aAAO,QAAQ,UAAU,MAAM,SAAS;AAAA,QACtC;AAAA,QACA,GAAG;AAAA,QACH,OAAQ,QAAQ,SAAoB,IAAI,MAAM,EAAE;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,QAAQ;AAAA,IACN,gBAAgB,OAAO,SAAiB,UAA2B,CAAC,MAAM;AACxE,YAAM,SAAS,MAAM,WAAW,+BAA+B;AAAA,QAC7D;AAAA,QACA,WAAW,IAAI;AAAA,QACf,YAAY,QAAQ,cAAc,GAAG,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,EAAE;AAAA,QAChG,WAAW,QAAQ,aAAa,GAAG,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,EAAE;AAAA,QAC9F,eAAe,QAAQ;AAAA,QACvB,UAAU,QAAQ,YAAY;AAAA,MAChC,CAAC;AAED,UAAI,OAAO,OAAO,QAAQ,aAAa,SAAS,OAAO,WAAW,aAAa;AAC7E,eAAO,SAAS,OAAO,OAAO;AAAA,MAChC;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,aAAa,YAAY;AACvB,aAAO,EAAE,UAAU,CAAC,GAAG,SAAS,yCAAyC;AAAA,IAC3E;AAAA,IAEA,eAAe,OAAO,cAAsB;AAC1C,UAAI,CAAC,WAAW;AACd,eAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB;AAAA,MAC3D;AACA,aAAO,UAAU,yCAAyC,mBAAmB,SAAS,CAAC,EAAE;AAAA,IAC3F;AAAA,IAEA,mBAAmB,OAAO,UAAmD,CAAC,MAAM;AAClF,YAAM,SAAS,IAAI,gBAAgB;AACnC,UAAI,QAAQ,WAAY,QAAO,IAAI,eAAe,QAAQ,UAAU;AACpE,UAAI,QAAQ,MAAO,QAAO,IAAI,SAAS,QAAQ,KAAK;AAEpD,UAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,OAAO;AACzC,eAAO,EAAE,SAAS,OAAO,OAAO,yCAAyC;AAAA,MAC3E;AAEA,aAAO,UAAU,+BAA+B,OAAO,SAAS,CAAC,EAAE;AAAA,IACrE;AAAA,IAEA,qBAAqB,OAAO,YAAoB,UAAsD,CAAC,MAAM;AAC3G,YAAM,SAAS,MAAM,WAAW,+BAA+B;AAAA,QAC7D;AAAA,QACA,WAAW,QAAQ,aAAa,OAAO,SAAS;AAAA,MAClD,CAAC;AAED,UAAI,OAAO,OAAO,QAAQ,aAAa,SAAS,OAAO,WAAW,aAAa;AAC7E,eAAO,SAAS,OAAO,OAAO;AAAA,MAChC;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACL,aAAa,CAAC,QAAgB,OAAe,OAAsB,SAAS;AAC1E,aAAO,QAAQ,UAAU,MAAM,eAAe,EAAE,QAAQ,OAAO,MAAM,cAAc,QAAQ,CAAC;AAAA,IAC9F;AAAA,IAEA,YAAY,CAAC,WAAmB;AAC9B,aAAO,QAAQ,UAAU,MAAM,cAAc,EAAE,OAAO,CAAC;AAAA,IACzD;AAAA,IAEA,aAAa,CAAC,WAAmB;AAC/B,aAAO,QAAQ,UAAU,MAAM,eAAe,EAAE,OAAO,CAAC;AAAA,IAC1D;AAAA,IAEA,iBAAiB,CAAC,QAAgB,SAAiB,YAAoB;AACrE,aAAO,QAAQ,UAAU,MAAM,eAAe,EAAE,QAAQ,SAAS,QAAQ,CAAC;AAAA,IAC5E;AAAA,EACF;AACF;AAEO,IAAM,yBAA0C;AAAA,EACrD,SAAS,CAAC,SAAmB;AAC3B,QAAI,MAAM,IAAI;AACZ,cAAQ,UAAU,SAAS,KAAK,IAAI;AAAA,QAClC,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK,eAAe;AAAA,MAC5B,CAAC;AACD,cAAQ,MAAM,WAAW,KAAK,EAAE;AAAA,IAClC;AAAA,EACF;AAAA,EACA,UAAU,CAAC,SAAmB;AAC5B,QAAI,MAAM,IAAI;AACZ,cAAQ,UAAU,SAAS,KAAK,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC;AACzD,cAAQ,MAAM,YAAY,KAAK,IAAI,KAAK,SAAS,EAAE;AAAA,IACrD;AAAA,EACF;AAAA,EACA,UAAU,CAAC,WAAmB;AAC5B,QAAI,QAAQ;AACV,cAAQ,MAAM,YAAY,MAAM;AAAA,IAClC;AAAA,EACF;AACF;AAWA,IAAM,iBAAiB,MAAY;AACjC,MAAI,OAAO,WAAW,eAAe,EAAE,yBAAyB,QAAS;AAEzE,MAAI;AACF,QAAI,oBAAoB,CAAC,SAAS;AAChC,YAAM,UAAU,KAAK,WAAW;AAChC,YAAM,YAAY,QAAQ,QAAQ,SAAS,CAAC;AAC5C,UAAI,WAAW;AACb,gBAAQ,UAAU,MAAM,aAAa;AAAA,UACnC,QAAQ;AAAA,UACR,OAAO,KAAK,MAAM,UAAU,SAAS;AAAA,UACrC,UAAU,OAAO,SAAS;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF,CAAC,EAAE,QAAQ,EAAE,MAAM,4BAA4B,UAAU,KAAK,CAAC;AAAA,EACjE,QAAQ;AAAA,EAA0B;AAElC,MAAI;AACF,QAAI,oBAAoB,CAAC,SAAS;AAChC,YAAM,QAAQ,KAAK,WAAW,EAAE,CAAC;AACjC,UAAI,OAAO;AACT,gBAAQ,UAAU,MAAM,aAAa;AAAA,UACnC,QAAQ;AAAA,UACR,OAAO,KAAK,MAAM,MAAM,kBAAkB,MAAM,SAAS;AAAA,UACzD,UAAU,OAAO,SAAS;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF,CAAC,EAAE,QAAQ,EAAE,MAAM,eAAe,UAAU,KAAK,CAAC;AAAA,EACpD,QAAQ;AAAA,EAA0B;AAElC,MAAI;AACF,QAAI,WAAW;AACf,QAAI,oBAAoB,CAAC,SAAS;AAChC,iBAAW,SAAS,KAAK,WAAW,GAAG;AACrC,YAAI,CAAE,MAAsB,gBAAgB;AAC1C,sBAAa,MAAsB;AAAA,QACrC;AAAA,MACF;AAAA,IACF,CAAC,EAAE,QAAQ,EAAE,MAAM,gBAAgB,UAAU,KAAK,CAAC;AAEnD,aAAS,iBAAiB,oBAAoB,MAAM;AAClD,UAAI,SAAS,UAAU,WAAW,GAAG;AACnC,gBAAQ,UAAU,MAAM,aAAa;AAAA,UACnC,QAAQ;AAAA,UACR,OAAO,KAAK,MAAM,WAAW,GAAI,IAAI;AAAA,UACrC,UAAU,OAAO,SAAS;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAA0B;AACpC;AAEA,IAAM,qBAAqB,MAAY;AACrC,MAAI,OAAO,WAAW,YAAa;AAEnC,SAAO,UAAU,CAAC,SAAS,QAAQ,QAAQ,OAAO,UAAU;AAC1D,YAAQ,UAAU,MAAM,YAAY;AAAA,MAClC,SAAS,OAAO,OAAO;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,OAAO;AAAA,MACd,UAAU,OAAO,SAAS;AAAA,IAC5B,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO,iBAAiB,sBAAsB,CAAC,UAAiC;AAC9E,YAAQ,UAAU,MAAM,qBAAqB;AAAA,MAC3C,QAAQ,MAAM,QAAQ,WAAW,OAAO,MAAM,MAAM;AAAA,MACpD,OAAO,MAAM,QAAQ;AAAA,MACrB,UAAU,OAAO,SAAS;AAAA,IAC5B,CAAC;AAAA,EACH,CAAC;AACH;AAEA,IAAI,OAAO,WAAW,aAAa;AACjC,SAAO,iBAAiB,UAAU,SAAS,kBAAkB,GAAG,GAAG,EAAE,SAAS,KAAK,CAAC;AACpF,SAAO,iBAAiB,gBAAgB,YAAY;AAEpD,WAAS,iBAAiB,oBAAoB,MAAM;AAClD,QAAI,CAAC,aAAa,EAAG;AACrB,QAAI,SAAS,QAAQ;AACnB,cAAQ,UAAU,MAAM,aAAa;AAAA,QACnC,YAAY,cAAc;AAAA,QAC1B,aAAa;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,UAAU,MAAM,cAAc,EAAE,UAAU,OAAO,SAAS,SAAS,CAAC;AAAA,IAC9E;AAAA,EACF,CAAC;AAED,QAAM,oBAAoB,QAAQ;AAClC,UAAQ,YAAY,YAAa,MAA4C;AAC3E,iBAAa;AACb,sBAAkB,MAAM,MAAM,IAAI;AAClC,mBAAe;AACf,QAAI,aAAa,EAAG,SAAQ,UAAU,SAAS;AAAA,EACjD;AAEA,QAAM,uBAAuB,QAAQ;AACrC,UAAQ,eAAe,YAAa,MAA+C;AACjF,yBAAqB,MAAM,MAAM,IAAI;AACrC,mBAAe;AAAA,EACjB;AAEA,SAAO,iBAAiB,YAAY,MAAM;AACxC,iBAAa;AACb,mBAAe;AACf,QAAI,aAAa,EAAG,SAAQ,UAAU,SAAS;AAAA,EACjD,CAAC;AAED,MAAI,aAAa,GAAG;AAClB,eAAW,MAAM;AACf,cAAQ,UAAU,SAAS;AAC3B,qBAAe;AACf,yBAAmB;AAAA,IACrB,GAAG,GAAG;AAAA,EACR;AACF;","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":[]}
|