@digiko-npm/cms 0.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.
@@ -0,0 +1,10 @@
1
+ import { createClient, type SupabaseClient } from '@supabase/supabase-js'
2
+ import type { SupabaseConfig } from '../types/config'
3
+
4
+ /**
5
+ * Browser-side Supabase client with anon key.
6
+ * Respects RLS — only reads published content.
7
+ */
8
+ export function createBrowserClient(config: SupabaseConfig): SupabaseClient {
9
+ return createClient(config.url, config.anonKey)
10
+ }
@@ -0,0 +1,2 @@
1
+ export { createBrowserClient } from './client'
2
+ export { createAdminClient, createPublicClient } from './server'
@@ -0,0 +1,21 @@
1
+ import { createClient, type SupabaseClient } from '@supabase/supabase-js'
2
+ import type { SupabaseConfig } from '../types/config'
3
+
4
+ /**
5
+ * Server-side Supabase client with service role key.
6
+ * Bypasses RLS — full read/write access.
7
+ */
8
+ export function createAdminClient(config: SupabaseConfig): SupabaseClient {
9
+ if (!config.serviceRoleKey) {
10
+ throw new Error('@digiko-npm/cms: serviceRoleKey is required for createAdminClient')
11
+ }
12
+ return createClient(config.url, config.serviceRoleKey)
13
+ }
14
+
15
+ /**
16
+ * Server-side Supabase client with anon key.
17
+ * Respects RLS — safe for public data fetching.
18
+ */
19
+ export function createPublicClient(config: SupabaseConfig): SupabaseClient {
20
+ return createClient(config.url, config.anonKey)
21
+ }
@@ -0,0 +1,27 @@
1
+ /** Server-side session data stored in Redis */
2
+ export interface Session {
3
+ createdAt: number
4
+ expiresAt: number
5
+ ip?: string
6
+ userAgent?: string
7
+ }
8
+
9
+ /** Result of an authentication attempt */
10
+ export interface AuthResult {
11
+ success: boolean
12
+ message: string
13
+ sessionToken?: string
14
+ expiresAt?: number
15
+ }
16
+
17
+ /** Result of admin request verification */
18
+ export type VerifyResult =
19
+ | { authorized: true; token: string }
20
+ | { authorized: false; status: number; message: string }
21
+
22
+ /** Rate limit check result */
23
+ export interface RateLimitResult {
24
+ allowed: boolean
25
+ remaining: number
26
+ retryAfterMs?: number
27
+ }
@@ -0,0 +1,65 @@
1
+ /** Supabase connection config */
2
+ export interface SupabaseConfig {
3
+ url: string
4
+ anonKey: string
5
+ serviceRoleKey?: string
6
+ }
7
+
8
+ /** Cloudflare R2 storage config */
9
+ export interface R2Config {
10
+ accountId: string
11
+ accessKeyId: string
12
+ secretAccessKey: string
13
+ bucketName: string
14
+ publicUrl: string
15
+ }
16
+
17
+ /** Redis session store config */
18
+ export interface SessionStoreConfig {
19
+ redisUrl: string
20
+ redisToken: string
21
+ /** Key namespace prefix (e.g. "marketplace:", "portfolio:") */
22
+ keyPrefix: string
23
+ /** Session TTL in milliseconds. Default: 24 hours */
24
+ sessionDuration?: number
25
+ }
26
+
27
+ /** Rate limiter config */
28
+ export interface RateLimiterConfig {
29
+ redisUrl: string
30
+ redisToken: string
31
+ keyPrefix: string
32
+ /** Max attempts before blocking. Default: 10 */
33
+ maxAttempts?: number
34
+ /** Time window in milliseconds. Default: 15 minutes */
35
+ windowMs?: number
36
+ }
37
+
38
+ /** Auth/password config */
39
+ export interface AuthConfig {
40
+ /** Cookie name for admin session. Default: "admin_session" */
41
+ cookieName?: string
42
+ pbkdf2?: {
43
+ iterations?: number
44
+ keyLength?: number
45
+ digest?: string
46
+ }
47
+ /** Session token length in bytes. Default: 32 (64-char hex) */
48
+ tokenBytes?: number
49
+ }
50
+
51
+ /** Client-side upload config (API endpoint paths) */
52
+ export interface UploadConfig {
53
+ /** Endpoint that returns presigned R2 URL (e.g. "/api/admin/upload") */
54
+ uploadEndpoint: string
55
+ /** Endpoint to register media in DB (e.g. "/api/admin/media") */
56
+ mediaEndpoint: string
57
+ }
58
+
59
+ /** Next.js request verifier config */
60
+ export interface RequestVerifierConfig {
61
+ cookieName?: string
62
+ getSession: (token: string) => Promise<{ createdAt: number; expiresAt: number } | undefined>
63
+ unauthorizedMessage?: string
64
+ sessionExpiredMessage?: string
65
+ }
@@ -0,0 +1,22 @@
1
+ export type {
2
+ SupabaseConfig,
3
+ R2Config,
4
+ SessionStoreConfig,
5
+ RateLimiterConfig,
6
+ AuthConfig,
7
+ UploadConfig,
8
+ RequestVerifierConfig,
9
+ } from './config'
10
+
11
+ export type {
12
+ MediaRecord,
13
+ MediaInsert,
14
+ MediaUpdate,
15
+ } from './media'
16
+
17
+ export type {
18
+ Session,
19
+ AuthResult,
20
+ VerifyResult,
21
+ RateLimitResult,
22
+ } from './auth'
@@ -0,0 +1,19 @@
1
+ /** Generic media record — shared across all projects that use R2 uploads */
2
+ export interface MediaRecord {
3
+ id: string
4
+ filename: string
5
+ original_name: string
6
+ mime_type: string
7
+ size_bytes: number
8
+ url: string
9
+ width?: number | null
10
+ height?: number | null
11
+ alt_text?: string | null
12
+ created_at: string
13
+ }
14
+
15
+ /** Fields required when creating a media record */
16
+ export type MediaInsert = Omit<MediaRecord, 'id' | 'created_at'>
17
+
18
+ /** Fields that can be updated on an existing media record */
19
+ export type MediaUpdate = Partial<Pick<MediaRecord, 'alt_text' | 'filename'>>