@structcms/api 0.1.0 → 0.1.1
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/README.md +2 -2
- package/dist/index.cjs +266 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +241 -12
- package/dist/index.d.ts +241 -12
- package/dist/index.js +250 -20
- package/dist/index.js.map +1 -1
- package/dist/next/index.cjs +147 -33
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +3 -2
- package/dist/next/index.d.ts +3 -2
- package/dist/next/index.js +147 -33
- package/dist/next/index.js.map +1 -1
- package/dist/supabase/index.cjs +37 -1
- package/dist/supabase/index.cjs.map +1 -1
- package/dist/supabase/index.d.cts +1 -1
- package/dist/supabase/index.d.ts +1 -1
- package/dist/supabase/index.js +37 -1
- package/dist/supabase/index.js.map +1 -1
- package/dist/{types-Zi0Iyow1.d.cts → types-Cdui_Ets.d.cts} +21 -2
- package/dist/{types-Zi0Iyow1.d.ts → types-Cdui_Ets.d.ts} +21 -2
- package/package.json +3 -2
package/dist/supabase/index.d.ts
CHANGED
package/dist/supabase/index.js
CHANGED
|
@@ -109,7 +109,38 @@ function createAuthAdapter(config) {
|
|
|
109
109
|
return new SupabaseAuthAdapter(config);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// src/media/types.ts
|
|
113
|
+
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
114
|
+
var ALLOWED_MIME_TYPES = [
|
|
115
|
+
"image/jpeg",
|
|
116
|
+
"image/png",
|
|
117
|
+
"image/gif",
|
|
118
|
+
"image/webp",
|
|
119
|
+
"image/svg+xml"
|
|
120
|
+
];
|
|
121
|
+
var ALLOWED_DOCUMENT_MIME_TYPES = [
|
|
122
|
+
"application/pdf",
|
|
123
|
+
"application/msword",
|
|
124
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
125
|
+
"application/vnd.ms-excel",
|
|
126
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
127
|
+
"application/vnd.ms-powerpoint",
|
|
128
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
129
|
+
"text/plain",
|
|
130
|
+
"text/csv",
|
|
131
|
+
"application/zip",
|
|
132
|
+
"application/gzip"
|
|
133
|
+
];
|
|
134
|
+
var ALL_ALLOWED_MIME_TYPES = [
|
|
135
|
+
...ALLOWED_MIME_TYPES,
|
|
136
|
+
...ALLOWED_DOCUMENT_MIME_TYPES
|
|
137
|
+
];
|
|
138
|
+
|
|
112
139
|
// src/media/supabase-adapter.ts
|
|
140
|
+
function deriveCategory(mimeType) {
|
|
141
|
+
const imageMimes = ALLOWED_MIME_TYPES;
|
|
142
|
+
return imageMimes.includes(mimeType) ? "image" : "document";
|
|
143
|
+
}
|
|
113
144
|
var MediaError = class extends Error {
|
|
114
145
|
constructor(message, code, details) {
|
|
115
146
|
super(message);
|
|
@@ -151,6 +182,7 @@ var SupabaseMediaAdapter = class {
|
|
|
151
182
|
url: this.getPublicUrl(row.storage_path),
|
|
152
183
|
mimeType: row.mime_type,
|
|
153
184
|
size: row.size,
|
|
185
|
+
category: row.category,
|
|
154
186
|
createdAt: new Date(row.created_at)
|
|
155
187
|
};
|
|
156
188
|
}
|
|
@@ -171,7 +203,8 @@ var SupabaseMediaAdapter = class {
|
|
|
171
203
|
filename: input.filename,
|
|
172
204
|
storage_path: storagePath,
|
|
173
205
|
mime_type: input.mimeType,
|
|
174
|
-
size: input.size
|
|
206
|
+
size: input.size,
|
|
207
|
+
category: deriveCategory(input.mimeType)
|
|
175
208
|
}).select().single();
|
|
176
209
|
if (dbError) {
|
|
177
210
|
await this.client.storage.from(this.bucketName).remove([storagePath]);
|
|
@@ -198,6 +231,9 @@ var SupabaseMediaAdapter = class {
|
|
|
198
231
|
if (filter?.mimeType) {
|
|
199
232
|
query = query.eq("mime_type", filter.mimeType);
|
|
200
233
|
}
|
|
234
|
+
if (filter?.category) {
|
|
235
|
+
query = query.eq("category", filter.category);
|
|
236
|
+
}
|
|
201
237
|
query = query.order("created_at", { ascending: false });
|
|
202
238
|
if (filter?.limit) {
|
|
203
239
|
query = query.limit(filter.limit);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/supabase/factory.ts","../../src/auth/supabase-adapter.ts","../../src/media/supabase-adapter.ts","../../src/storage/supabase-adapter.ts"],"sourcesContent":["import { createClient } from '@supabase/supabase-js';\nimport { createAuthAdapter } from '../auth';\nimport type { AuthAdapter } from '../auth';\nimport { createMediaAdapter } from '../media';\nimport type { MediaAdapter } from '../media';\nimport { createStorageAdapter } from '../storage';\nimport type { StorageAdapter } from '../storage';\n\nexport interface SupabaseAdapterFactoryStorageConfig {\n bucket?: string;\n}\n\nexport interface SupabaseAdapterFactoryConfig {\n url?: string;\n key?: string;\n storage?: SupabaseAdapterFactoryStorageConfig;\n}\n\nexport interface SupabaseAdapters {\n storageAdapter: StorageAdapter;\n mediaAdapter: MediaAdapter;\n authAdapter: AuthAdapter;\n}\n\ninterface ProcessLike {\n env: Record<string, string | undefined>;\n}\n\nfunction readEnv(name: string): string | undefined {\n const processLike = (globalThis as typeof globalThis & { process?: ProcessLike }).process;\n return processLike?.env[name];\n}\n\nfunction resolveRequiredConfig(\n explicitValue: string | undefined,\n envName: 'SUPABASE_URL' | 'SUPABASE_SECRET_KEY'\n): string {\n const explicit = explicitValue?.trim();\n if (explicit) {\n return explicit;\n }\n\n const fromEnv = readEnv(envName)?.trim();\n if (fromEnv) {\n return fromEnv;\n }\n\n throw new Error(\n `Missing Supabase configuration: provide ${envName} in factory config or environment variable`\n );\n}\n\nfunction resolveBucketName(config: SupabaseAdapterFactoryConfig): string {\n const explicitBucket = config.storage?.bucket?.trim();\n if (explicitBucket) {\n return explicitBucket;\n }\n\n const envBucket = readEnv('SUPABASE_STORAGE_BUCKET')?.trim();\n if (envBucket) {\n return envBucket;\n }\n\n return 'media';\n}\n\nexport function createSupabaseAdapters(\n config: SupabaseAdapterFactoryConfig = {}\n): SupabaseAdapters {\n const url = resolveRequiredConfig(config.url, 'SUPABASE_URL');\n const key = resolveRequiredConfig(config.key, 'SUPABASE_SECRET_KEY');\n const bucketName = resolveBucketName(config);\n\n const client = createClient(url, key);\n\n return {\n storageAdapter: createStorageAdapter({ client }),\n mediaAdapter: createMediaAdapter({ client, bucketName }),\n authAdapter: createAuthAdapter({ client }),\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n AuthAdapter,\n AuthSession,\n AuthUser,\n OAuthResponse,\n SignInWithOAuthInput,\n SignInWithPasswordInput,\n VerifySessionInput,\n} from './types';\n\nexport class AuthError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'AuthError';\n }\n}\n\nexport interface SupabaseAuthAdapterConfig {\n client: SupabaseClient;\n}\n\nexport class SupabaseAuthAdapter implements AuthAdapter {\n private client: SupabaseClient;\n\n constructor(config: SupabaseAuthAdapterConfig) {\n this.client = config.client;\n }\n\n private mapSupabaseUser(user: {\n id: string;\n email?: string;\n user_metadata?: Record<string, unknown>;\n }): AuthUser {\n if (!user.email) {\n throw new AuthError('User email is required', 'INVALID_USER');\n }\n\n return {\n id: user.id,\n email: user.email,\n metadata: user.user_metadata,\n };\n }\n\n async signInWithOAuth(input: SignInWithOAuthInput): Promise<OAuthResponse> {\n const { data, error } = await this.client.auth.signInWithOAuth({\n provider: input.provider,\n options: {\n redirectTo: input.redirectTo,\n },\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.url) {\n throw new AuthError('OAuth URL not provided', 'OAUTH_URL_MISSING');\n }\n\n return {\n url: data.url,\n provider: input.provider,\n };\n }\n\n async signInWithPassword(input: SignInWithPasswordInput): Promise<AuthSession> {\n const { data, error } = await this.client.auth.signInWithPassword({\n email: input.email,\n password: input.password,\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.session || !data.user) {\n throw new AuthError('Session or user not returned', 'AUTH_FAILED');\n }\n\n return {\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n expiresAt: data.session.expires_at ? new Date(data.session.expires_at * 1000) : undefined,\n user: this.mapSupabaseUser(data.user),\n };\n }\n\n async signOut(_accessToken: string): Promise<void> {\n const { error } = await this.client.auth.signOut();\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n }\n\n async verifySession(input: VerifySessionInput): Promise<AuthUser | null> {\n const { data, error } = await this.client.auth.getUser(input.accessToken);\n\n if (error) {\n return null;\n }\n\n if (!data.user) {\n return null;\n }\n\n return this.mapSupabaseUser(data.user);\n }\n\n async refreshSession(refreshToken: string): Promise<AuthSession> {\n const { data, error } = await this.client.auth.refreshSession({\n refresh_token: refreshToken,\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.session || !data.user) {\n throw new AuthError('Session refresh failed', 'REFRESH_FAILED');\n }\n\n return {\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n expiresAt: data.session.expires_at ? new Date(data.session.expires_at * 1000) : undefined,\n user: this.mapSupabaseUser(data.user),\n };\n }\n\n async getCurrentUser(accessToken: string): Promise<AuthUser | null> {\n const { data, error } = await this.client.auth.getUser(accessToken);\n\n if (error) {\n return null;\n }\n\n if (!data.user) {\n return null;\n }\n\n return this.mapSupabaseUser(data.user);\n }\n}\n\nexport function createAuthAdapter(config: SupabaseAuthAdapterConfig): AuthAdapter {\n return new SupabaseAuthAdapter(config);\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type { MediaAdapter, MediaFile, MediaFilter, UploadMediaInput } from './types';\n\n/**\n * Database row type for media (snake_case)\n */\ninterface MediaRow {\n id: string;\n filename: string;\n storage_path: string;\n mime_type: string;\n size: number;\n created_at: string;\n updated_at: string;\n}\n\n/**\n * Media adapter error with additional context\n */\nexport class MediaError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'MediaError';\n }\n}\n\n/**\n * Configuration for creating a Supabase media adapter\n */\nexport interface SupabaseMediaAdapterConfig {\n client: SupabaseClient;\n bucketName?: string;\n}\n\n/**\n * Supabase implementation of the MediaAdapter interface\n */\nexport class SupabaseMediaAdapter implements MediaAdapter {\n private client: SupabaseClient;\n private bucketName: string;\n\n constructor(config: SupabaseMediaAdapterConfig) {\n this.client = config.client;\n this.bucketName = config.bucketName ?? 'media';\n }\n\n /**\n * Generates a unique storage path for a file\n */\n private generateStoragePath(filename: string): string {\n const timestamp = Date.now();\n const randomSuffix = Math.random().toString(36).substring(2, 8);\n const sanitizedFilename = filename.replace(/[^a-zA-Z0-9.-]/g, '_');\n return `${timestamp}-${randomSuffix}-${sanitizedFilename}`;\n }\n\n /**\n * Constructs the public URL for a stored file\n */\n private getPublicUrl(storagePath: string): string {\n const { data } = this.client.storage.from(this.bucketName).getPublicUrl(storagePath);\n return data.publicUrl;\n }\n\n /**\n * Maps a database row to MediaFile\n */\n private mapRowToMediaFile(row: MediaRow): MediaFile {\n return {\n id: row.id,\n filename: row.filename,\n url: this.getPublicUrl(row.storage_path),\n mimeType: row.mime_type,\n size: row.size,\n createdAt: new Date(row.created_at),\n };\n }\n\n async upload(input: UploadMediaInput): Promise<MediaFile> {\n const storagePath = this.generateStoragePath(input.filename);\n\n // Upload file to Supabase Storage\n const { error: uploadError } = await this.client.storage\n .from(this.bucketName)\n .upload(storagePath, input.data, {\n contentType: input.mimeType,\n upsert: false,\n });\n\n if (uploadError) {\n throw new MediaError(\n `Failed to upload file: ${uploadError.message}`,\n 'UPLOAD_FAILED',\n uploadError.message\n );\n }\n\n // Create database record\n const { data, error: dbError } = await this.client\n .from('media')\n .insert({\n filename: input.filename,\n storage_path: storagePath,\n mime_type: input.mimeType,\n size: input.size,\n })\n .select()\n .single();\n\n if (dbError) {\n // Cleanup: delete uploaded file if DB insert fails\n await this.client.storage.from(this.bucketName).remove([storagePath]);\n throw new MediaError(\n `Failed to create media record: ${dbError.message}`,\n dbError.code,\n dbError.details\n );\n }\n\n return this.mapRowToMediaFile(data as MediaRow);\n }\n\n async getMedia(id: string): Promise<MediaFile | null> {\n const { data, error } = await this.client.from('media').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new MediaError(error.message, error.code, error.details);\n }\n\n return this.mapRowToMediaFile(data as MediaRow);\n }\n\n async listMedia(filter?: MediaFilter): Promise<MediaFile[]> {\n let query = this.client.from('media').select('*');\n\n if (filter?.mimeType) {\n query = query.eq('mime_type', filter.mimeType);\n }\n\n query = query.order('created_at', { ascending: false });\n\n if (filter?.limit) {\n query = query.limit(filter.limit);\n }\n\n if (filter?.offset) {\n query = query.range(filter.offset, filter.offset + (filter.limit ?? 100) - 1);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new MediaError(error.message, error.code, error.details);\n }\n\n return (data as MediaRow[]).map((row) => this.mapRowToMediaFile(row));\n }\n\n async deleteMedia(id: string): Promise<void> {\n // First get the media record to find the storage path\n const { data: mediaRecord, error: fetchError } = await this.client\n .from('media')\n .select('storage_path')\n .eq('id', id)\n .single();\n\n if (fetchError) {\n if (fetchError.code === 'PGRST116') {\n throw new MediaError(`Media not found: ${id}`, 'NOT_FOUND');\n }\n throw new MediaError(fetchError.message, fetchError.code, fetchError.details);\n }\n\n const storagePath = (mediaRecord as { storage_path: string }).storage_path;\n\n // Delete from storage\n const { error: storageError } = await this.client.storage\n .from(this.bucketName)\n .remove([storagePath]);\n\n if (storageError) {\n throw new MediaError(\n `Failed to delete file from storage: ${storageError.message}`,\n 'STORAGE_DELETE_FAILED',\n storageError.message\n );\n }\n\n // Delete database record\n const { error: dbError } = await this.client.from('media').delete().eq('id', id);\n\n if (dbError) {\n throw new MediaError(dbError.message, dbError.code, dbError.details);\n }\n }\n}\n\n/**\n * Creates a media adapter using Supabase\n */\nexport function createMediaAdapter(config: SupabaseMediaAdapterConfig): MediaAdapter {\n return new SupabaseMediaAdapter(config);\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n CreateNavigationInput,\n CreatePageInput,\n Navigation,\n NavigationItem,\n Page,\n PageFilter,\n PageSection,\n StorageAdapter,\n UpdateNavigationInput,\n UpdatePageInput,\n} from './types';\n\n/**\n * Database row types (snake_case)\n */\ninterface PageRow {\n id: string;\n slug: string;\n page_type: string;\n title: string;\n sections: PageSection[];\n created_at: string;\n updated_at: string;\n}\n\ninterface NavigationRow {\n id: string;\n name: string;\n items: NavigationItem[];\n created_at: string;\n updated_at: string;\n}\n\n/**\n * Maps a database page row to the Page type\n */\nfunction mapPageRowToPage(row: PageRow): Page {\n return {\n id: row.id,\n slug: row.slug,\n pageType: row.page_type,\n title: row.title,\n sections: row.sections,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n };\n}\n\n/**\n * Maps a database navigation row to the Navigation type\n */\nfunction mapNavigationRowToNavigation(row: NavigationRow): Navigation {\n return {\n id: row.id,\n name: row.name,\n items: row.items,\n updatedAt: new Date(row.updated_at),\n };\n}\n\n/**\n * Storage adapter error with additional context\n */\nexport class StorageError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'StorageError';\n }\n}\n\n/**\n * Configuration for creating a Supabase storage adapter\n */\nexport interface SupabaseStorageAdapterConfig {\n client: SupabaseClient;\n}\n\n/**\n * Supabase implementation of the StorageAdapter interface\n */\nexport class SupabaseStorageAdapter implements StorageAdapter {\n private client: SupabaseClient;\n\n constructor(config: SupabaseStorageAdapterConfig) {\n this.client = config.client;\n }\n\n async getPage(slug: string): Promise<Page | null> {\n const { data, error } = await this.client.from('pages').select('*').eq('slug', slug).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async getPageById(id: string): Promise<Page | null> {\n const { data, error } = await this.client.from('pages').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async createPage(input: CreatePageInput): Promise<Page> {\n const { data, error } = await this.client\n .from('pages')\n .insert({\n slug: input.slug,\n page_type: input.pageType,\n title: input.title,\n sections: input.sections ?? [],\n })\n .select()\n .single();\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async updatePage(input: UpdatePageInput): Promise<Page> {\n const updateData: Record<string, unknown> = {};\n\n if (input.slug !== undefined) {\n updateData.slug = input.slug;\n }\n if (input.pageType !== undefined) {\n updateData.page_type = input.pageType;\n }\n if (input.title !== undefined) {\n updateData.title = input.title;\n }\n if (input.sections !== undefined) {\n updateData.sections = input.sections;\n }\n\n const { data, error } = await this.client\n .from('pages')\n .update(updateData)\n .eq('id', input.id)\n .select()\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n throw new StorageError(`Page not found: ${input.id}`, 'NOT_FOUND');\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async deletePage(id: string): Promise<void> {\n const { error } = await this.client.from('pages').delete().eq('id', id);\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n }\n\n async listPages(filter?: PageFilter): Promise<Page[]> {\n let query = this.client.from('pages').select('*');\n\n if (filter?.pageType) {\n query = query.eq('page_type', filter.pageType);\n }\n\n query = query.order('created_at', { ascending: false });\n\n if (filter?.limit) {\n query = query.limit(filter.limit);\n }\n\n if (filter?.offset) {\n query = query.range(filter.offset, filter.offset + (filter.limit ?? 100) - 1);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return (data as PageRow[]).map(mapPageRowToPage);\n }\n\n async getNavigation(name: string): Promise<Navigation | null> {\n const { data, error } = await this.client\n .from('navigation')\n .select('*')\n .eq('name', name)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async getNavigationById(id: string): Promise<Navigation | null> {\n const { data, error } = await this.client.from('navigation').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async createNavigation(input: CreateNavigationInput): Promise<Navigation> {\n const { data, error } = await this.client\n .from('navigation')\n .insert({\n name: input.name,\n items: input.items,\n })\n .select()\n .single();\n\n if (error) {\n if (error.code === '23505') {\n throw new StorageError(\n `Navigation with name \"${input.name}\" already exists`,\n 'DUPLICATE_NAME'\n );\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async updateNavigation(input: UpdateNavigationInput): Promise<Navigation> {\n const updateData: Record<string, unknown> = {};\n\n if (input.name !== undefined) {\n updateData.name = input.name;\n }\n if (input.items !== undefined) {\n updateData.items = input.items;\n }\n\n const { data, error } = await this.client\n .from('navigation')\n .update(updateData)\n .eq('id', input.id)\n .select()\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n throw new StorageError(`Navigation not found: ${input.id}`, 'NOT_FOUND');\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async deleteNavigation(id: string): Promise<void> {\n const { error } = await this.client.from('navigation').delete().eq('id', id);\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n }\n\n async listNavigations(): Promise<Navigation[]> {\n const { data, error } = await this.client\n .from('navigation')\n .select('*')\n .order('name', { ascending: true });\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return (data as NavigationRow[]).map(mapNavigationRowToNavigation);\n }\n}\n\n/**\n * Creates a storage adapter using Supabase\n */\nexport function createStorageAdapter(config: SupabaseStorageAdapterConfig): StorageAdapter {\n return new SupabaseStorageAdapter(config);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/supabase/factory.ts","../../src/auth/supabase-adapter.ts","../../src/media/types.ts","../../src/media/supabase-adapter.ts","../../src/storage/supabase-adapter.ts"],"sourcesContent":["import { createClient } from '@supabase/supabase-js';\nimport { createAuthAdapter } from '../auth';\nimport type { AuthAdapter } from '../auth';\nimport { createMediaAdapter } from '../media';\nimport type { MediaAdapter } from '../media';\nimport { createStorageAdapter } from '../storage';\nimport type { StorageAdapter } from '../storage';\n\nexport interface SupabaseAdapterFactoryStorageConfig {\n bucket?: string;\n}\n\nexport interface SupabaseAdapterFactoryConfig {\n url?: string;\n key?: string;\n storage?: SupabaseAdapterFactoryStorageConfig;\n}\n\nexport interface SupabaseAdapters {\n storageAdapter: StorageAdapter;\n mediaAdapter: MediaAdapter;\n authAdapter: AuthAdapter;\n}\n\ninterface ProcessLike {\n env: Record<string, string | undefined>;\n}\n\nfunction readEnv(name: string): string | undefined {\n const processLike = (globalThis as typeof globalThis & { process?: ProcessLike }).process;\n return processLike?.env[name];\n}\n\nfunction resolveRequiredConfig(\n explicitValue: string | undefined,\n envName: 'SUPABASE_URL' | 'SUPABASE_SECRET_KEY'\n): string {\n const explicit = explicitValue?.trim();\n if (explicit) {\n return explicit;\n }\n\n const fromEnv = readEnv(envName)?.trim();\n if (fromEnv) {\n return fromEnv;\n }\n\n throw new Error(\n `Missing Supabase configuration: provide ${envName} in factory config or environment variable`\n );\n}\n\nfunction resolveBucketName(config: SupabaseAdapterFactoryConfig): string {\n const explicitBucket = config.storage?.bucket?.trim();\n if (explicitBucket) {\n return explicitBucket;\n }\n\n const envBucket = readEnv('SUPABASE_STORAGE_BUCKET')?.trim();\n if (envBucket) {\n return envBucket;\n }\n\n return 'media';\n}\n\nexport function createSupabaseAdapters(\n config: SupabaseAdapterFactoryConfig = {}\n): SupabaseAdapters {\n const url = resolveRequiredConfig(config.url, 'SUPABASE_URL');\n const key = resolveRequiredConfig(config.key, 'SUPABASE_SECRET_KEY');\n const bucketName = resolveBucketName(config);\n\n const client = createClient(url, key);\n\n return {\n storageAdapter: createStorageAdapter({ client }),\n mediaAdapter: createMediaAdapter({ client, bucketName }),\n authAdapter: createAuthAdapter({ client }),\n };\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n AuthAdapter,\n AuthSession,\n AuthUser,\n OAuthResponse,\n SignInWithOAuthInput,\n SignInWithPasswordInput,\n VerifySessionInput,\n} from './types';\n\nexport class AuthError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'AuthError';\n }\n}\n\nexport interface SupabaseAuthAdapterConfig {\n client: SupabaseClient;\n}\n\nexport class SupabaseAuthAdapter implements AuthAdapter {\n private client: SupabaseClient;\n\n constructor(config: SupabaseAuthAdapterConfig) {\n this.client = config.client;\n }\n\n private mapSupabaseUser(user: {\n id: string;\n email?: string;\n user_metadata?: Record<string, unknown>;\n }): AuthUser {\n if (!user.email) {\n throw new AuthError('User email is required', 'INVALID_USER');\n }\n\n return {\n id: user.id,\n email: user.email,\n metadata: user.user_metadata,\n };\n }\n\n async signInWithOAuth(input: SignInWithOAuthInput): Promise<OAuthResponse> {\n const { data, error } = await this.client.auth.signInWithOAuth({\n provider: input.provider,\n options: {\n redirectTo: input.redirectTo,\n },\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.url) {\n throw new AuthError('OAuth URL not provided', 'OAUTH_URL_MISSING');\n }\n\n return {\n url: data.url,\n provider: input.provider,\n };\n }\n\n async signInWithPassword(input: SignInWithPasswordInput): Promise<AuthSession> {\n const { data, error } = await this.client.auth.signInWithPassword({\n email: input.email,\n password: input.password,\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.session || !data.user) {\n throw new AuthError('Session or user not returned', 'AUTH_FAILED');\n }\n\n return {\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n expiresAt: data.session.expires_at ? new Date(data.session.expires_at * 1000) : undefined,\n user: this.mapSupabaseUser(data.user),\n };\n }\n\n async signOut(_accessToken: string): Promise<void> {\n const { error } = await this.client.auth.signOut();\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n }\n\n async verifySession(input: VerifySessionInput): Promise<AuthUser | null> {\n const { data, error } = await this.client.auth.getUser(input.accessToken);\n\n if (error) {\n return null;\n }\n\n if (!data.user) {\n return null;\n }\n\n return this.mapSupabaseUser(data.user);\n }\n\n async refreshSession(refreshToken: string): Promise<AuthSession> {\n const { data, error } = await this.client.auth.refreshSession({\n refresh_token: refreshToken,\n });\n\n if (error) {\n throw new AuthError(error.message, error.status?.toString(), error.message);\n }\n\n if (!data.session || !data.user) {\n throw new AuthError('Session refresh failed', 'REFRESH_FAILED');\n }\n\n return {\n accessToken: data.session.access_token,\n refreshToken: data.session.refresh_token,\n expiresAt: data.session.expires_at ? new Date(data.session.expires_at * 1000) : undefined,\n user: this.mapSupabaseUser(data.user),\n };\n }\n\n async getCurrentUser(accessToken: string): Promise<AuthUser | null> {\n const { data, error } = await this.client.auth.getUser(accessToken);\n\n if (error) {\n return null;\n }\n\n if (!data.user) {\n return null;\n }\n\n return this.mapSupabaseUser(data.user);\n }\n}\n\nexport function createAuthAdapter(config: SupabaseAuthAdapterConfig): AuthAdapter {\n return new SupabaseAuthAdapter(config);\n}\n","/**\n * Maximum file size: 50MB\n */\nexport const MAX_FILE_SIZE = 50 * 1024 * 1024;\n\n/**\n * Allowed MIME types for image uploads\n */\nexport const ALLOWED_MIME_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n] as const;\n\nexport type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];\n\n/**\n * Allowed MIME types for document uploads\n */\nexport const ALLOWED_DOCUMENT_MIME_TYPES = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'application/vnd.ms-powerpoint',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n 'text/plain',\n 'text/csv',\n 'application/zip',\n 'application/gzip',\n] as const;\n\nexport type AllowedDocumentMimeType = (typeof ALLOWED_DOCUMENT_MIME_TYPES)[number];\n\n/**\n * All allowed MIME types (images + documents)\n */\nexport const ALL_ALLOWED_MIME_TYPES = [\n ...ALLOWED_MIME_TYPES,\n ...ALLOWED_DOCUMENT_MIME_TYPES,\n] as const;\n\n/**\n * Media category discriminator\n */\nexport type MediaCategory = 'image' | 'document';\n\n/**\n * Represents a media file stored in the CMS\n */\nexport interface MediaFile {\n id: string;\n filename: string;\n url: string;\n mimeType: string;\n size: number;\n category: MediaCategory;\n createdAt: Date;\n}\n\n/**\n * Input for uploading a media file\n * data accepts ArrayBuffer for platform-agnostic binary data\n */\nexport interface UploadMediaInput {\n filename: string;\n mimeType: string;\n size: number;\n data: ArrayBuffer | Uint8Array;\n}\n\n/**\n * Filter options for listing media files\n */\nexport interface MediaFilter {\n limit?: number;\n offset?: number;\n mimeType?: string;\n category?: MediaCategory;\n}\n\n/**\n * Media adapter interface for file storage operations.\n * This interface is Supabase-agnostic to allow future portability.\n */\nexport interface MediaAdapter {\n /**\n * Upload a media file\n */\n upload(input: UploadMediaInput): Promise<MediaFile>;\n\n /**\n * Get a media file by ID\n */\n getMedia(id: string): Promise<MediaFile | null>;\n\n /**\n * List media files with optional filtering and pagination\n */\n listMedia(filter?: MediaFilter): Promise<MediaFile[]>;\n\n /**\n * Delete a media file by ID\n */\n deleteMedia(id: string): Promise<void>;\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n MediaAdapter,\n MediaCategory,\n MediaFile,\n MediaFilter,\n UploadMediaInput,\n} from './types';\nimport { ALLOWED_MIME_TYPES } from './types';\n\n/**\n * Database row type for media (snake_case)\n */\ninterface MediaRow {\n id: string;\n filename: string;\n storage_path: string;\n mime_type: string;\n size: number;\n category: string;\n created_at: string;\n updated_at: string;\n}\n\n/**\n * Derives the media category from a MIME type.\n * Image MIME types map to 'image', everything else to 'document'.\n */\nfunction deriveCategory(mimeType: string): MediaCategory {\n const imageMimes = ALLOWED_MIME_TYPES as readonly string[];\n return imageMimes.includes(mimeType) ? 'image' : 'document';\n}\n\n/**\n * Media adapter error with additional context\n */\nexport class MediaError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'MediaError';\n }\n}\n\n/**\n * Configuration for creating a Supabase media adapter\n */\nexport interface SupabaseMediaAdapterConfig {\n client: SupabaseClient;\n bucketName?: string;\n}\n\n/**\n * Supabase implementation of the MediaAdapter interface\n */\nexport class SupabaseMediaAdapter implements MediaAdapter {\n private client: SupabaseClient;\n private bucketName: string;\n\n constructor(config: SupabaseMediaAdapterConfig) {\n this.client = config.client;\n this.bucketName = config.bucketName ?? 'media';\n }\n\n /**\n * Generates a unique storage path for a file\n */\n private generateStoragePath(filename: string): string {\n const timestamp = Date.now();\n const randomSuffix = Math.random().toString(36).substring(2, 8);\n const sanitizedFilename = filename.replace(/[^a-zA-Z0-9.-]/g, '_');\n return `${timestamp}-${randomSuffix}-${sanitizedFilename}`;\n }\n\n /**\n * Constructs the public URL for a stored file\n */\n private getPublicUrl(storagePath: string): string {\n const { data } = this.client.storage.from(this.bucketName).getPublicUrl(storagePath);\n return data.publicUrl;\n }\n\n /**\n * Maps a database row to MediaFile\n */\n private mapRowToMediaFile(row: MediaRow): MediaFile {\n return {\n id: row.id,\n filename: row.filename,\n url: this.getPublicUrl(row.storage_path),\n mimeType: row.mime_type,\n size: row.size,\n category: row.category as MediaCategory,\n createdAt: new Date(row.created_at),\n };\n }\n\n async upload(input: UploadMediaInput): Promise<MediaFile> {\n const storagePath = this.generateStoragePath(input.filename);\n\n // Upload file to Supabase Storage\n const { error: uploadError } = await this.client.storage\n .from(this.bucketName)\n .upload(storagePath, input.data, {\n contentType: input.mimeType,\n upsert: false,\n });\n\n if (uploadError) {\n throw new MediaError(\n `Failed to upload file: ${uploadError.message}`,\n 'UPLOAD_FAILED',\n uploadError.message\n );\n }\n\n // Create database record\n const { data, error: dbError } = await this.client\n .from('media')\n .insert({\n filename: input.filename,\n storage_path: storagePath,\n mime_type: input.mimeType,\n size: input.size,\n category: deriveCategory(input.mimeType),\n })\n .select()\n .single();\n\n if (dbError) {\n // Cleanup: delete uploaded file if DB insert fails\n await this.client.storage.from(this.bucketName).remove([storagePath]);\n throw new MediaError(\n `Failed to create media record: ${dbError.message}`,\n dbError.code,\n dbError.details\n );\n }\n\n return this.mapRowToMediaFile(data as MediaRow);\n }\n\n async getMedia(id: string): Promise<MediaFile | null> {\n const { data, error } = await this.client.from('media').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new MediaError(error.message, error.code, error.details);\n }\n\n return this.mapRowToMediaFile(data as MediaRow);\n }\n\n async listMedia(filter?: MediaFilter): Promise<MediaFile[]> {\n let query = this.client.from('media').select('*');\n\n if (filter?.mimeType) {\n query = query.eq('mime_type', filter.mimeType);\n }\n\n if (filter?.category) {\n query = query.eq('category', filter.category);\n }\n\n query = query.order('created_at', { ascending: false });\n\n if (filter?.limit) {\n query = query.limit(filter.limit);\n }\n\n if (filter?.offset) {\n query = query.range(filter.offset, filter.offset + (filter.limit ?? 100) - 1);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new MediaError(error.message, error.code, error.details);\n }\n\n return (data as MediaRow[]).map((row) => this.mapRowToMediaFile(row));\n }\n\n async deleteMedia(id: string): Promise<void> {\n // First get the media record to find the storage path\n const { data: mediaRecord, error: fetchError } = await this.client\n .from('media')\n .select('storage_path')\n .eq('id', id)\n .single();\n\n if (fetchError) {\n if (fetchError.code === 'PGRST116') {\n throw new MediaError(`Media not found: ${id}`, 'NOT_FOUND');\n }\n throw new MediaError(fetchError.message, fetchError.code, fetchError.details);\n }\n\n const storagePath = (mediaRecord as { storage_path: string }).storage_path;\n\n // Delete from storage\n const { error: storageError } = await this.client.storage\n .from(this.bucketName)\n .remove([storagePath]);\n\n if (storageError) {\n throw new MediaError(\n `Failed to delete file from storage: ${storageError.message}`,\n 'STORAGE_DELETE_FAILED',\n storageError.message\n );\n }\n\n // Delete database record\n const { error: dbError } = await this.client.from('media').delete().eq('id', id);\n\n if (dbError) {\n throw new MediaError(dbError.message, dbError.code, dbError.details);\n }\n }\n}\n\n/**\n * Creates a media adapter using Supabase\n */\nexport function createMediaAdapter(config: SupabaseMediaAdapterConfig): MediaAdapter {\n return new SupabaseMediaAdapter(config);\n}\n","import type { SupabaseClient } from '@supabase/supabase-js';\nimport type {\n CreateNavigationInput,\n CreatePageInput,\n Navigation,\n NavigationItem,\n Page,\n PageFilter,\n PageSection,\n StorageAdapter,\n UpdateNavigationInput,\n UpdatePageInput,\n} from './types';\n\n/**\n * Database row types (snake_case)\n */\ninterface PageRow {\n id: string;\n slug: string;\n page_type: string;\n title: string;\n sections: PageSection[];\n created_at: string;\n updated_at: string;\n}\n\ninterface NavigationRow {\n id: string;\n name: string;\n items: NavigationItem[];\n created_at: string;\n updated_at: string;\n}\n\n/**\n * Maps a database page row to the Page type\n */\nfunction mapPageRowToPage(row: PageRow): Page {\n return {\n id: row.id,\n slug: row.slug,\n pageType: row.page_type,\n title: row.title,\n sections: row.sections,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n };\n}\n\n/**\n * Maps a database navigation row to the Navigation type\n */\nfunction mapNavigationRowToNavigation(row: NavigationRow): Navigation {\n return {\n id: row.id,\n name: row.name,\n items: row.items,\n updatedAt: new Date(row.updated_at),\n };\n}\n\n/**\n * Storage adapter error with additional context\n */\nexport class StorageError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly details?: string\n ) {\n super(message);\n this.name = 'StorageError';\n }\n}\n\n/**\n * Configuration for creating a Supabase storage adapter\n */\nexport interface SupabaseStorageAdapterConfig {\n client: SupabaseClient;\n}\n\n/**\n * Supabase implementation of the StorageAdapter interface\n */\nexport class SupabaseStorageAdapter implements StorageAdapter {\n private client: SupabaseClient;\n\n constructor(config: SupabaseStorageAdapterConfig) {\n this.client = config.client;\n }\n\n async getPage(slug: string): Promise<Page | null> {\n const { data, error } = await this.client.from('pages').select('*').eq('slug', slug).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async getPageById(id: string): Promise<Page | null> {\n const { data, error } = await this.client.from('pages').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async createPage(input: CreatePageInput): Promise<Page> {\n const { data, error } = await this.client\n .from('pages')\n .insert({\n slug: input.slug,\n page_type: input.pageType,\n title: input.title,\n sections: input.sections ?? [],\n })\n .select()\n .single();\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async updatePage(input: UpdatePageInput): Promise<Page> {\n const updateData: Record<string, unknown> = {};\n\n if (input.slug !== undefined) {\n updateData.slug = input.slug;\n }\n if (input.pageType !== undefined) {\n updateData.page_type = input.pageType;\n }\n if (input.title !== undefined) {\n updateData.title = input.title;\n }\n if (input.sections !== undefined) {\n updateData.sections = input.sections;\n }\n\n const { data, error } = await this.client\n .from('pages')\n .update(updateData)\n .eq('id', input.id)\n .select()\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n throw new StorageError(`Page not found: ${input.id}`, 'NOT_FOUND');\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapPageRowToPage(data as PageRow);\n }\n\n async deletePage(id: string): Promise<void> {\n const { error } = await this.client.from('pages').delete().eq('id', id);\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n }\n\n async listPages(filter?: PageFilter): Promise<Page[]> {\n let query = this.client.from('pages').select('*');\n\n if (filter?.pageType) {\n query = query.eq('page_type', filter.pageType);\n }\n\n query = query.order('created_at', { ascending: false });\n\n if (filter?.limit) {\n query = query.limit(filter.limit);\n }\n\n if (filter?.offset) {\n query = query.range(filter.offset, filter.offset + (filter.limit ?? 100) - 1);\n }\n\n const { data, error } = await query;\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return (data as PageRow[]).map(mapPageRowToPage);\n }\n\n async getNavigation(name: string): Promise<Navigation | null> {\n const { data, error } = await this.client\n .from('navigation')\n .select('*')\n .eq('name', name)\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async getNavigationById(id: string): Promise<Navigation | null> {\n const { data, error } = await this.client.from('navigation').select('*').eq('id', id).single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n return null; // Not found\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async createNavigation(input: CreateNavigationInput): Promise<Navigation> {\n const { data, error } = await this.client\n .from('navigation')\n .insert({\n name: input.name,\n items: input.items,\n })\n .select()\n .single();\n\n if (error) {\n if (error.code === '23505') {\n throw new StorageError(\n `Navigation with name \"${input.name}\" already exists`,\n 'DUPLICATE_NAME'\n );\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async updateNavigation(input: UpdateNavigationInput): Promise<Navigation> {\n const updateData: Record<string, unknown> = {};\n\n if (input.name !== undefined) {\n updateData.name = input.name;\n }\n if (input.items !== undefined) {\n updateData.items = input.items;\n }\n\n const { data, error } = await this.client\n .from('navigation')\n .update(updateData)\n .eq('id', input.id)\n .select()\n .single();\n\n if (error) {\n if (error.code === 'PGRST116') {\n throw new StorageError(`Navigation not found: ${input.id}`, 'NOT_FOUND');\n }\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return mapNavigationRowToNavigation(data as NavigationRow);\n }\n\n async deleteNavigation(id: string): Promise<void> {\n const { error } = await this.client.from('navigation').delete().eq('id', id);\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n }\n\n async listNavigations(): Promise<Navigation[]> {\n const { data, error } = await this.client\n .from('navigation')\n .select('*')\n .order('name', { ascending: true });\n\n if (error) {\n throw new StorageError(error.message, error.code, error.details);\n }\n\n return (data as NavigationRow[]).map(mapNavigationRowToNavigation);\n }\n}\n\n/**\n * Creates a storage adapter using Supabase\n */\nexport function createStorageAdapter(config: SupabaseStorageAdapterConfig): StorageAdapter {\n return new SupabaseStorageAdapter(config);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -109,10 +109,27 @@ interface StorageAdapter {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
112
|
+
* Maximum file size: 50MB
|
|
113
|
+
*/
|
|
114
|
+
declare const MAX_FILE_SIZE: number;
|
|
115
|
+
/**
|
|
116
|
+
* Allowed MIME types for image uploads
|
|
113
117
|
*/
|
|
114
118
|
declare const ALLOWED_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
|
|
115
119
|
type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];
|
|
120
|
+
/**
|
|
121
|
+
* Allowed MIME types for document uploads
|
|
122
|
+
*/
|
|
123
|
+
declare const ALLOWED_DOCUMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "application/zip", "application/gzip"];
|
|
124
|
+
type AllowedDocumentMimeType = (typeof ALLOWED_DOCUMENT_MIME_TYPES)[number];
|
|
125
|
+
/**
|
|
126
|
+
* All allowed MIME types (images + documents)
|
|
127
|
+
*/
|
|
128
|
+
declare const ALL_ALLOWED_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "application/zip", "application/gzip"];
|
|
129
|
+
/**
|
|
130
|
+
* Media category discriminator
|
|
131
|
+
*/
|
|
132
|
+
type MediaCategory = 'image' | 'document';
|
|
116
133
|
/**
|
|
117
134
|
* Represents a media file stored in the CMS
|
|
118
135
|
*/
|
|
@@ -122,6 +139,7 @@ interface MediaFile {
|
|
|
122
139
|
url: string;
|
|
123
140
|
mimeType: string;
|
|
124
141
|
size: number;
|
|
142
|
+
category: MediaCategory;
|
|
125
143
|
createdAt: Date;
|
|
126
144
|
}
|
|
127
145
|
/**
|
|
@@ -141,6 +159,7 @@ interface MediaFilter {
|
|
|
141
159
|
limit?: number;
|
|
142
160
|
offset?: number;
|
|
143
161
|
mimeType?: string;
|
|
162
|
+
category?: MediaCategory;
|
|
144
163
|
}
|
|
145
164
|
/**
|
|
146
165
|
* Media adapter interface for file storage operations.
|
|
@@ -201,4 +220,4 @@ interface AuthAdapter {
|
|
|
201
220
|
getCurrentUser(accessToken: string): Promise<AuthUser | null>;
|
|
202
221
|
}
|
|
203
222
|
|
|
204
|
-
export { type AuthAdapter as A, type CreatePageInput as C, type MediaAdapter as M, type Navigation as N, type OAuthResponse as O, type Page as P, type StorageAdapter as S, type UpdatePageInput as U, type VerifySessionInput as V, type PageFilter as a, type CreateNavigationInput as b, type UpdateNavigationInput as c, type NavigationItem as d, type PageSection as e, type UploadMediaInput as f, type MediaFile as g, type MediaFilter as h, type SignInWithOAuthInput as i, type SignInWithPasswordInput as j, type AuthSession as k, type AuthUser as l,
|
|
223
|
+
export { type AuthAdapter as A, type CreatePageInput as C, type MediaAdapter as M, type Navigation as N, type OAuthResponse as O, type Page as P, type StorageAdapter as S, type UpdatePageInput as U, type VerifySessionInput as V, type PageFilter as a, type CreateNavigationInput as b, type UpdateNavigationInput as c, type NavigationItem as d, type PageSection as e, type UploadMediaInput as f, type MediaFile as g, type MediaFilter as h, type SignInWithOAuthInput as i, type SignInWithPasswordInput as j, type AuthSession as k, type AuthUser as l, ALLOWED_DOCUMENT_MIME_TYPES as m, ALLOWED_MIME_TYPES as n, ALL_ALLOWED_MIME_TYPES as o, type AllowedDocumentMimeType as p, type AllowedMimeType as q, MAX_FILE_SIZE as r, type MediaCategory as s };
|
|
@@ -109,10 +109,27 @@ interface StorageAdapter {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
*
|
|
112
|
+
* Maximum file size: 50MB
|
|
113
|
+
*/
|
|
114
|
+
declare const MAX_FILE_SIZE: number;
|
|
115
|
+
/**
|
|
116
|
+
* Allowed MIME types for image uploads
|
|
113
117
|
*/
|
|
114
118
|
declare const ALLOWED_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
|
|
115
119
|
type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];
|
|
120
|
+
/**
|
|
121
|
+
* Allowed MIME types for document uploads
|
|
122
|
+
*/
|
|
123
|
+
declare const ALLOWED_DOCUMENT_MIME_TYPES: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "application/zip", "application/gzip"];
|
|
124
|
+
type AllowedDocumentMimeType = (typeof ALLOWED_DOCUMENT_MIME_TYPES)[number];
|
|
125
|
+
/**
|
|
126
|
+
* All allowed MIME types (images + documents)
|
|
127
|
+
*/
|
|
128
|
+
declare const ALL_ALLOWED_MIME_TYPES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "text/plain", "text/csv", "application/zip", "application/gzip"];
|
|
129
|
+
/**
|
|
130
|
+
* Media category discriminator
|
|
131
|
+
*/
|
|
132
|
+
type MediaCategory = 'image' | 'document';
|
|
116
133
|
/**
|
|
117
134
|
* Represents a media file stored in the CMS
|
|
118
135
|
*/
|
|
@@ -122,6 +139,7 @@ interface MediaFile {
|
|
|
122
139
|
url: string;
|
|
123
140
|
mimeType: string;
|
|
124
141
|
size: number;
|
|
142
|
+
category: MediaCategory;
|
|
125
143
|
createdAt: Date;
|
|
126
144
|
}
|
|
127
145
|
/**
|
|
@@ -141,6 +159,7 @@ interface MediaFilter {
|
|
|
141
159
|
limit?: number;
|
|
142
160
|
offset?: number;
|
|
143
161
|
mimeType?: string;
|
|
162
|
+
category?: MediaCategory;
|
|
144
163
|
}
|
|
145
164
|
/**
|
|
146
165
|
* Media adapter interface for file storage operations.
|
|
@@ -201,4 +220,4 @@ interface AuthAdapter {
|
|
|
201
220
|
getCurrentUser(accessToken: string): Promise<AuthUser | null>;
|
|
202
221
|
}
|
|
203
222
|
|
|
204
|
-
export { type AuthAdapter as A, type CreatePageInput as C, type MediaAdapter as M, type Navigation as N, type OAuthResponse as O, type Page as P, type StorageAdapter as S, type UpdatePageInput as U, type VerifySessionInput as V, type PageFilter as a, type CreateNavigationInput as b, type UpdateNavigationInput as c, type NavigationItem as d, type PageSection as e, type UploadMediaInput as f, type MediaFile as g, type MediaFilter as h, type SignInWithOAuthInput as i, type SignInWithPasswordInput as j, type AuthSession as k, type AuthUser as l,
|
|
223
|
+
export { type AuthAdapter as A, type CreatePageInput as C, type MediaAdapter as M, type Navigation as N, type OAuthResponse as O, type Page as P, type StorageAdapter as S, type UpdatePageInput as U, type VerifySessionInput as V, type PageFilter as a, type CreateNavigationInput as b, type UpdateNavigationInput as c, type NavigationItem as d, type PageSection as e, type UploadMediaInput as f, type MediaFile as g, type MediaFilter as h, type SignInWithOAuthInput as i, type SignInWithPasswordInput as j, type AuthSession as k, type AuthUser as l, ALLOWED_DOCUMENT_MIME_TYPES as m, ALLOWED_MIME_TYPES as n, ALL_ALLOWED_MIME_TYPES as o, type AllowedDocumentMimeType as p, type AllowedMimeType as q, MAX_FILE_SIZE as r, type MediaCategory as s };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@structcms/api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Storage, domain API, and delivery API for StructCMS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@supabase/supabase-js": "^2.45.0",
|
|
52
|
-
"sanitize-html": "^2.17.0"
|
|
52
|
+
"sanitize-html": "^2.17.0",
|
|
53
|
+
"zod": "^3.23.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@types/sanitize-html": "^2.16.0",
|