@meycult/core 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/package.json +3 -6
  2. package/src/brand/BrandName.tsx +4 -2
  3. package/src/brand/LaunchButton.tsx +5 -3
  4. package/src/brand/Logo.tsx +25 -6
  5. package/src/brand/PyramidName.tsx +10 -0
  6. package/src/brand/Sigil.tsx +10 -5
  7. package/src/brand/TokenIcons.tsx +12 -6
  8. package/src/brand.ts +4 -1
  9. package/src/components/CultCountdown.tsx +89 -14
  10. package/src/game/categories.ts +23 -0
  11. package/src/game/cults.ts +88 -0
  12. package/src/game/quests.ts +62 -0
  13. package/src/game/types.ts +27 -0
  14. package/src/index.ts +64 -21
  15. package/src/product.ts +17 -0
  16. package/src/styles/theme.css +97 -6
  17. package/src/tokens.ts +10 -2
  18. package/src/ui/CultButton.tsx +55 -0
  19. package/src/ui/RarityBadge.tsx +18 -0
  20. package/src/ui/animated-shiny-text.tsx +2 -2
  21. package/src/ui/badges.tsx +43 -0
  22. package/src/ui/card.tsx +20 -92
  23. package/src/ui/shimmer-button.tsx +5 -3
  24. package/src/ui/virtues.tsx +66 -0
  25. package/src/unveil/LaunchStage.tsx +3 -2
  26. package/src/unveil/bg.ts +20 -11
  27. package/src/unveil/bgStyles.ts +0 -1
  28. package/src/unveil/blocks.tsx +51 -14
  29. package/src/unveil/effects.tsx +182 -86
  30. package/src/unveil.ts +2 -21
  31. package/src/auth/Gate.tsx +0 -14
  32. package/src/auth/types.ts +0 -12
  33. package/src/brand/GodEmperor.tsx +0 -8
  34. package/src/cn.ts +0 -6
  35. package/src/lib/images.ts +0 -10
  36. package/src/lib/money.ts +0 -12
  37. package/src/lib/store.ts +0 -19
  38. package/src/shell/types.ts +0 -13
  39. package/src/supabase/browser.ts +0 -103
  40. package/src/supabase/callback.ts +0 -15
  41. package/src/supabase/proxy.ts +0 -36
  42. package/src/supabase/server.ts +0 -31
  43. package/src/ui/Callout.tsx +0 -33
@@ -1,103 +0,0 @@
1
- import { createClient, type SupabaseClient } from '@supabase/supabase-js'
2
-
3
- export interface BrowserEnv {
4
- url: string
5
- anonKey: string
6
- }
7
-
8
- /**
9
- * Chunked cookie storage — shares the session across subdomains
10
- * (e.g. app.meycult.com + shop.meycult.com via domain=.meycult.com)
11
- * while staying under the ~4KB cookie limit.
12
- */
13
- export function chunkedCookieStorage(
14
- storageKey: string,
15
- cookieDomain: string | null,
16
- chunkSize = 3200,
17
- ): Pick<Storage, 'getItem' | 'setItem' | 'removeItem'> {
18
- const domainAttr = cookieDomain ? `; domain=${cookieDomain}` : ''
19
-
20
- function readCookie(name: string): string | null {
21
- if (typeof document === 'undefined') return null
22
- const match = document.cookie.match(
23
- new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1') + '=([^;]*)'),
24
- )
25
- return match ? decodeURIComponent(match[1]) : null
26
- }
27
-
28
- function writeCookie(name: string, value: string, maxAge = 60 * 60 * 24 * 30): void {
29
- document.cookie = `${name}=${encodeURIComponent(value)}; path=/${domainAttr}; max-age=${maxAge}; SameSite=Lax; Secure`
30
- }
31
-
32
- function deleteCookie(name: string): void {
33
- document.cookie = `${name}=; path=/${domainAttr}; max-age=0; SameSite=Lax; Secure`
34
- }
35
-
36
- function countKey(): string {
37
- return `${storageKey}.n`
38
- }
39
-
40
- return {
41
- getItem(key: string): string | null {
42
- const count = readCookie(countKey())
43
- if (count) {
44
- let out = ''
45
- for (let i = 0; i < Number(count); i++) out += readCookie(`${key}.${i}`) ?? ''
46
- return out || null
47
- }
48
- return readCookie(key)
49
- },
50
- setItem(key: string, value: string): void {
51
- const prev = readCookie(countKey())
52
- if (prev) for (let i = 0; i < Number(prev); i++) deleteCookie(`${key}.${i}`)
53
- deleteCookie(key)
54
- if (value.length <= chunkSize) {
55
- writeCookie(key, value)
56
- deleteCookie(countKey())
57
- return
58
- }
59
- const parts = Math.ceil(value.length / chunkSize)
60
- for (let i = 0; i < parts; i++) writeCookie(`${key}.${i}`, value.slice(i * chunkSize, (i + 1) * chunkSize))
61
- writeCookie(countKey(), String(parts))
62
- },
63
- removeItem(key: string): void {
64
- const count = readCookie(countKey())
65
- if (count) for (let i = 0; i < Number(count); i++) deleteCookie(`${key}.${i}`)
66
- deleteCookie(countKey())
67
- deleteCookie(key)
68
- },
69
- }
70
- }
71
-
72
- export interface BrowserOptions extends BrowserEnv {
73
- /** e.g. 'meycult-auth'. Defaults to 'meycult-auth'. */
74
- storageKey?: string
75
- /** e.g. '.meycult.com' on prod, null on localhost. Defaults to hostname heuristic. */
76
- cookieDomain?: string | null
77
- detectSessionInUrl?: boolean
78
- }
79
-
80
- function defaultCookieDomain(): string | null {
81
- if (typeof window === 'undefined') return null
82
- return window.location.hostname.endsWith('meycult.com') ? '.meycult.com' : null
83
- }
84
-
85
- export function createSupabaseBrowser(options: BrowserOptions): SupabaseClient {
86
- const {
87
- url,
88
- anonKey,
89
- storageKey = 'meycult-auth',
90
- cookieDomain = defaultCookieDomain(),
91
- detectSessionInUrl = true,
92
- } = options
93
- const onDomain = cookieDomain !== null
94
- return createClient(url, anonKey, {
95
- auth: {
96
- storageKey,
97
- persistSession: true,
98
- autoRefreshToken: true,
99
- detectSessionInUrl,
100
- ...(onDomain ? { storage: chunkedCookieStorage(storageKey, cookieDomain) } : {}),
101
- },
102
- })
103
- }
@@ -1,15 +0,0 @@
1
- import type { SupabaseClient } from '@supabase/supabase-js'
2
-
3
- /**
4
- * OAuth callback helper — host route calls this with its server client,
5
- * then redirects to `next` (default '/').
6
- */
7
- export async function exchangeCodeForSession(
8
- supabase: SupabaseClient,
9
- code: string | null,
10
- next = '/',
11
- ): Promise<{ next: string; error: string | null }> {
12
- if (!code) return { next, error: 'missing_code' }
13
- const { error } = await supabase.auth.exchangeCodeForSession(code)
14
- return { next, error: error ? error.message : null }
15
- }
@@ -1,36 +0,0 @@
1
- import { createServerClient } from '@supabase/ssr'
2
- import { NextResponse, type NextRequest } from 'next/server'
3
-
4
- /**
5
- * Refresh the Supabase session on every request so Server Components
6
- * always see a valid token. Wire into the host's proxy.ts:
7
- * export default coreUpdateSession as middleware-style default export
8
- */
9
- export async function updateSession(request: NextRequest) {
10
- let supabaseResponse = NextResponse.next({ request })
11
-
12
- const supabase = createServerClient(
13
- process.env.NEXT_PUBLIC_SUPABASE_URL!,
14
- process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
15
- {
16
- cookies: {
17
- getAll() {
18
- return request.cookies.getAll()
19
- },
20
- setAll(
21
- cookiesToSet: { name: string; value: string; options?: Record<string, unknown> }[],
22
- ) {
23
- cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
24
- supabaseResponse = NextResponse.next({ request })
25
- cookiesToSet.forEach(({ name, value, options }) =>
26
- supabaseResponse.cookies.set(name, value, options),
27
- )
28
- },
29
- },
30
- },
31
- )
32
-
33
- await supabase.auth.getClaims()
34
-
35
- return supabaseResponse
36
- }
@@ -1,31 +0,0 @@
1
- import { createServerClient } from '@supabase/ssr'
2
- import { cookies } from 'next/headers'
3
-
4
- /** Next.js Server Component / Route Handler / Server Action client. */
5
- export async function createSupabaseServerClient() {
6
- const cookieStore = await cookies()
7
-
8
- return createServerClient(
9
- process.env.NEXT_PUBLIC_SUPABASE_URL!,
10
- process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
11
- {
12
- cookies: {
13
- getAll() {
14
- return cookieStore.getAll()
15
- },
16
- setAll(
17
- cookiesToSet: { name: string; value: string; options?: Record<string, unknown> }[],
18
- ) {
19
- try {
20
- cookiesToSet.forEach(({ name, value, options }) =>
21
- cookieStore.set(name, value, options),
22
- )
23
- } catch {
24
- // Called from a Server Component — read-only there.
25
- // The proxy refreshes sessions on every request.
26
- }
27
- },
28
- },
29
- },
30
- )
31
- }
@@ -1,33 +0,0 @@
1
- import { AlertTriangle, CheckCircle, Info } from "lucide-react";
2
-
3
- type CalloutType = "info" | "warning" | "success" | "danger";
4
-
5
- const icons: Record<CalloutType, React.ReactNode> = {
6
- info: <Info className="h-5 w-5" />,
7
- warning: <AlertTriangle className="h-5 w-5" />,
8
- success: <CheckCircle className="h-5 w-5" />,
9
- danger: <AlertTriangle className="h-5 w-5" />,
10
- };
11
-
12
- const styles: Record<CalloutType, string> = {
13
- info: "border-accent bg-accent/10 text-text",
14
- warning: "border-amber-500 bg-amber-950/30 text-amber-100",
15
- success: "border-green-500 bg-green-950/30 text-green-100",
16
- danger: "border-red-500 bg-red-950/30 text-red-100",
17
- };
18
-
19
- interface CalloutProps {
20
- type?: CalloutType;
21
- children: React.ReactNode;
22
- }
23
-
24
- export function Callout({ type = "info", children }: CalloutProps) {
25
- return (
26
- <div className={`my-6 rounded-lg border-l-4 p-4 not-prose ${styles[type]}`}>
27
- <div className="flex items-start gap-3">
28
- <span className="mt-0.5">{icons[type]}</span>
29
- <div className="[&>p]:m-0">{children}</div>
30
- </div>
31
- </div>
32
- );
33
- }