@codingfactory/socialkit-vue 0.5.2 → 0.6.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.
@@ -68,6 +68,25 @@ interface LocalReactionEchoMarker {
68
68
  expiresAt: number
69
69
  }
70
70
 
71
+ interface DiscussionCreateThreadResponse {
72
+ data?: Thread
73
+ }
74
+
75
+ interface DiscussionCreateReplyResponse {
76
+ data?: Reply
77
+ }
78
+
79
+ interface DiscussionDraftPayload {
80
+ title?: string | null
81
+ content?: string
82
+ metadata?: Record<string, unknown>
83
+ [key: string]: unknown
84
+ }
85
+
86
+ interface DiscussionSaveDraftResponse {
87
+ data?: DiscussionDraftPayload
88
+ }
89
+
71
90
  type UnknownRecord = Record<string, unknown>
72
91
 
73
92
  function isRecord(value: unknown): value is UnknownRecord {
@@ -979,13 +998,16 @@ export function createDiscussionStoreDefinition(config: DiscussionStoreConfig) {
979
998
  }
980
999
  }
981
1000
 
982
- async function createThread(spaceSlug: string, input: CreateThreadInput): Promise<unknown> {
1001
+ async function createThread(
1002
+ spaceSlug: string,
1003
+ input: CreateThreadInput
1004
+ ): Promise<DiscussionCreateThreadResponse> {
983
1005
  cleanupRealtimeChannels()
984
1006
  loading.value = true
985
1007
  error.value = null
986
1008
 
987
1009
  try {
988
- const response = await client.post<unknown>(`/v1/discussion/spaces/${spaceSlug}/threads`, {
1010
+ const response = await client.post<DiscussionCreateThreadResponse>(`/v1/discussion/spaces/${spaceSlug}/threads`, {
989
1011
  title: input.title,
990
1012
  body: input.body,
991
1013
  audience: input.audience || 'public',
@@ -1107,11 +1129,14 @@ export function createDiscussionStoreDefinition(config: DiscussionStoreConfig) {
1107
1129
  return err.message === 'Network Error' && !err.response
1108
1130
  }
1109
1131
 
1110
- async function createReply(threadId: string, input: CreateReplyInput): Promise<unknown> {
1132
+ async function createReply(
1133
+ threadId: string,
1134
+ input: CreateReplyInput
1135
+ ): Promise<DiscussionCreateReplyResponse> {
1111
1136
  pendingReplyCreations.set(threadId, (pendingReplyCreations.get(threadId) ?? 0) + 1)
1112
1137
 
1113
1138
  try {
1114
- const response = await client.post<unknown>(`/v1/discussion/threads/${threadId}/replies`, {
1139
+ const response = await client.post<DiscussionCreateReplyResponse>(`/v1/discussion/threads/${threadId}/replies`, {
1115
1140
  body: input.body,
1116
1141
  parent_reply_id: input.parent_id,
1117
1142
  ...(input.quoted_reply_id ? { quoted_reply_id: input.quoted_reply_id } : {}),
@@ -2093,9 +2118,9 @@ export function createDiscussionStoreDefinition(config: DiscussionStoreConfig) {
2093
2118
  id: string,
2094
2119
  content: string,
2095
2120
  options?: SaveDraftOptions
2096
- ): Promise<unknown> {
2121
+ ): Promise<DiscussionSaveDraftResponse> {
2097
2122
  try {
2098
- const response = await client.post<unknown>('/v1/editor/drafts/save', {
2123
+ const response = await client.post<DiscussionSaveDraftResponse>('/v1/editor/drafts/save', {
2099
2124
  type,
2100
2125
  id,
2101
2126
  title: options?.title,
@@ -2110,13 +2135,14 @@ export function createDiscussionStoreDefinition(config: DiscussionStoreConfig) {
2110
2135
  }
2111
2136
  }
2112
2137
 
2113
- async function getDraft(type: string, id: string): Promise<unknown> {
2138
+ async function getDraft(type: string, id: string): Promise<DiscussionDraftPayload | null> {
2114
2139
  try {
2115
2140
  const response = await client.get<unknown>('/v1/editor/drafts/check', {
2116
2141
  params: { type, id },
2117
2142
  })
2118
2143
  const responseData = toRecord(response.data)
2119
- return responseData?.data ?? null
2144
+ const draftData = toRecord(responseData?.data)
2145
+ return draftData as DiscussionDraftPayload | null
2120
2146
  } catch (draftError) {
2121
2147
  if (isAxiosError(draftError) && draftError.response?.status === 404) {
2122
2148
  return null
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Content API type definitions.
3
+ */
4
+
5
+ import type { FeedEntry, Post } from './content.js'
6
+
7
+ export interface FeedResponse {
8
+ data: {
9
+ entries: FeedEntry[]
10
+ meta?: {
11
+ next_cursor?: string | null
12
+ has_more?: boolean
13
+ current_page?: number
14
+ total?: number
15
+ }
16
+ next_cursor?: string | null
17
+ }
18
+ page_entries?: FeedEntry[]
19
+ next_cursor?: string | null
20
+ entries?: FeedEntry[]
21
+ posts?: Post[]
22
+ hasMore?: boolean
23
+ nextCursor?: string | null
24
+ }
@@ -0,0 +1,381 @@
1
+ /**
2
+ * Content-domain types and store contracts shared across SocialKit frontends.
3
+ */
4
+
5
+ import type { ApiService } from '../services/api.js'
6
+ import type { LocalMediaItem } from './media.js'
7
+
8
+ export interface BaseEntity {
9
+ id: string
10
+ created_at: string
11
+ updated_at?: string
12
+ }
13
+
14
+ export type VideoRenderStatus = 'pending' | 'processing' | 'ready' | 'failed'
15
+
16
+ export interface PostMedia {
17
+ id?: string
18
+ uuid?: string
19
+ mime_type?: string
20
+ url?: string
21
+ thumb_url?: string
22
+ preview_url?: string
23
+ playback_url?: string
24
+ thumbnail_url?: string
25
+ urls?: {
26
+ original?: string
27
+ thumb?: string
28
+ thumbnail?: string
29
+ preview?: string
30
+ }
31
+ type?: 'image' | 'video'
32
+ alt_text?: string
33
+ width?: number
34
+ height?: number
35
+ responsive?: {
36
+ preview?: {
37
+ srcset?: string
38
+ }
39
+ original?: {
40
+ srcset?: string
41
+ }
42
+ }
43
+ processing_status?: VideoRenderStatus
44
+ video_render_status?: VideoRenderStatus
45
+ video_render_progress?: number
46
+ video_render_error?: string | null
47
+ video_render_job_id?: string | null
48
+ source_media_id?: string
49
+ output_media_id?: string
50
+ provider?: string
51
+ provider_asset_id?: string
52
+ provider_library_id?: string
53
+ duration?: number
54
+ aspect_ratio?: string
55
+ }
56
+
57
+ export interface PostAuthor {
58
+ id: string
59
+ name: string
60
+ avatar?: string | null
61
+ username?: string | null
62
+ handle?: string | null
63
+ }
64
+
65
+ export type PostFeelingType = 'mood' | 'activity'
66
+ export type PostFeelingValue =
67
+ | 'inspired'
68
+ | 'creative'
69
+ | 'focused'
70
+ | 'relaxed'
71
+ | 'excited'
72
+ | 'grateful'
73
+ | 'proud'
74
+ | 'experimental'
75
+ | 'in_the_studio'
76
+ | 'teaching_a_class'
77
+ | 'at_a_show'
78
+ | 'experimenting'
79
+ | 'collaborating'
80
+ | 'learning_a_technique'
81
+
82
+ export interface PostFeeling {
83
+ type: PostFeelingType
84
+ value: PostFeelingValue
85
+ }
86
+
87
+ export interface PostMeta {
88
+ live_viewers?: number | null
89
+ feeling?: PostFeeling | null
90
+ [key: string]: unknown
91
+ }
92
+
93
+ export type PostShareType = 'original' | 'repost' | 'quote'
94
+
95
+ export interface QuotedPostPreview {
96
+ id: string
97
+ body: string
98
+ author?: PostAuthor | null
99
+ author_id?: string
100
+ created_at?: string
101
+ }
102
+
103
+ export interface Post extends BaseEntity {
104
+ body: string
105
+ share_type?: PostShareType
106
+ quoted_post_id?: string | null
107
+ quoted_post?: QuotedPostPreview | null
108
+ content_warning?: string | null
109
+ sensitive?: boolean
110
+ author: PostAuthor
111
+ author_id: string
112
+ reactions_count: number
113
+ comments_count: number
114
+ user_has_reacted: boolean
115
+ user_has_reposted?: boolean
116
+ user_repost_id?: string | null
117
+ visibility?: 'public' | 'private' | 'friends'
118
+ media?: PostMedia[]
119
+ meta?: PostMeta
120
+ live_viewers?: number | null
121
+ is_quarantined?: boolean
122
+ published_site_names?: string[] | null
123
+ }
124
+
125
+ export interface PostWithPendingState extends Post {
126
+ _isPending?: boolean
127
+ _tempId?: string
128
+ }
129
+
130
+ export interface Comment extends BaseEntity {
131
+ body: string
132
+ post_id: string
133
+ author: PostAuthor
134
+ media?: PostMedia[]
135
+ parent_id?: string
136
+ thread_id?: string
137
+ depth?: number
138
+ reactions_count?: number
139
+ replies_count?: number
140
+ user_has_reacted?: boolean
141
+ user_reaction_type?: string
142
+ reactions?: Record<string, number>
143
+ replies?: Comment[]
144
+ is_hidden?: boolean
145
+ }
146
+
147
+ export interface Reaction {
148
+ id: string
149
+ user_id: string
150
+ target_id: string
151
+ target_type: 'post' | 'comment'
152
+ kind: string
153
+ created_at: string
154
+ }
155
+
156
+ export interface ThreadSummary {
157
+ id: string
158
+ space_id: string
159
+ slug: string
160
+ title: string
161
+ body?: string | null
162
+ reply_count: number
163
+ author_id: string
164
+ author?: {
165
+ id: string
166
+ name: string
167
+ handle?: string
168
+ avatar_url?: string | null
169
+ avatar?: unknown
170
+ } | null
171
+ created_at: string
172
+ tags?: Array<{
173
+ id: string
174
+ slug: string
175
+ label: string
176
+ }>
177
+ }
178
+
179
+ export interface AlbumSummary {
180
+ id: string
181
+ name: string
182
+ description?: string | null
183
+ media_count: number
184
+ owner: {
185
+ id: string
186
+ type: string
187
+ name?: string
188
+ avatar_url?: string | null
189
+ }
190
+ cover_media?: {
191
+ uuid: string
192
+ urls: {
193
+ thumb?: string
194
+ preview?: string
195
+ original?: string
196
+ }
197
+ } | null
198
+ created_at?: string | null
199
+ }
200
+
201
+ export interface FeedEntry {
202
+ id?: string
203
+ entity_id: string
204
+ entity_type: string
205
+ created_at?: string
206
+ activity_type?: string
207
+ actor_id?: string
208
+ owner_user_id?: string
209
+ visibility?: string
210
+ is_hidden?: boolean
211
+ post?: PostWithPendingState | null
212
+ thread?: ThreadSummary | null
213
+ album?: AlbumSummary | null
214
+ [key: string]: unknown
215
+ }
216
+
217
+ export interface ScheduledPostEntry {
218
+ id: string
219
+ status: string
220
+ publish_at: string
221
+ post_id: string | null
222
+ payload: Record<string, unknown> | string | null
223
+ }
224
+
225
+ export interface ScheduledPostsPage {
226
+ data: ScheduledPostEntry[]
227
+ meta: {
228
+ next_cursor: string | null
229
+ }
230
+ }
231
+
232
+ export type PendingPostStatus = 'pending' | 'uploading' | 'failed'
233
+
234
+ export interface PendingVideoRender {
235
+ sourceMediaUuid: string
236
+ renderJobId: string | null
237
+ }
238
+
239
+ export interface PendingPost {
240
+ tempId: string
241
+ body: string
242
+ share_type?: PostShareType | undefined
243
+ quoted_post_id?: string | undefined
244
+ visibility: string
245
+ content_warning?: string | undefined
246
+ meta?: PostMeta | undefined
247
+ media_ids?: string[] | undefined
248
+ mediaItems?: LocalMediaItem[] | undefined
249
+ hadUnuploadedMedia?: boolean | undefined
250
+ container_type?: string | undefined
251
+ container_id?: string | undefined
252
+ pendingVideoRenders?: PendingVideoRender[] | undefined
253
+ status: PendingPostStatus
254
+ createdAt: string
255
+ retryCount: number
256
+ error?: string | undefined
257
+ }
258
+
259
+ export interface RecoverablePendingDraft {
260
+ tempId: string
261
+ body: string
262
+ visibility: string
263
+ contentWarning?: string
264
+ }
265
+
266
+ export type ProcessPendingPostResult =
267
+ | {
268
+ ok: true
269
+ postId: string
270
+ isQuarantined?: boolean
271
+ }
272
+ | {
273
+ ok: false
274
+ error: string
275
+ retryable: boolean
276
+ }
277
+
278
+ export function isPost(obj: unknown): obj is Post {
279
+ return (
280
+ obj !== null
281
+ && typeof obj === 'object'
282
+ && 'id' in obj
283
+ && 'body' in obj
284
+ && 'author' in obj
285
+ && 'reactions_count' in obj
286
+ && 'comments_count' in obj
287
+ )
288
+ }
289
+
290
+ export function isComment(obj: unknown): obj is Comment {
291
+ return (
292
+ obj !== null
293
+ && typeof obj === 'object'
294
+ && 'id' in obj
295
+ && 'body' in obj
296
+ && 'post_id' in obj
297
+ && 'author' in obj
298
+ )
299
+ }
300
+
301
+ export type PostUpdate = Partial<Omit<Post, 'id' | 'created_at' | 'author' | 'author_id'>>
302
+ export type CommentUpdate = Partial<Omit<Comment, 'id' | 'created_at' | 'author' | 'post_id'>>
303
+
304
+ export interface PostResponse {
305
+ data: Post
306
+ meta?: Record<string, unknown>
307
+ }
308
+
309
+ export interface PostListResponse {
310
+ data: Post[]
311
+ meta?: {
312
+ total: number
313
+ per_page: number
314
+ current_page: number
315
+ next_cursor?: string
316
+ }
317
+ }
318
+
319
+ export interface CommentListResponse {
320
+ data: Comment[]
321
+ meta?: {
322
+ total: number
323
+ next_cursor?: string
324
+ }
325
+ }
326
+
327
+ export enum PostVisibility {
328
+ PUBLIC = 'public',
329
+ PRIVATE = 'private',
330
+ FRIENDS = 'friends'
331
+ }
332
+
333
+ export enum ReactionKind {
334
+ LIKE = 'like',
335
+ LOVE = 'love',
336
+ HAHA = 'haha',
337
+ WOW = 'wow',
338
+ SAD = 'sad',
339
+ ANGRY = 'angry'
340
+ }
341
+
342
+ export interface ContentActiveRecipeMeta {
343
+ id: string
344
+ name: string
345
+ icon: string | null
346
+ is_preset: boolean
347
+ }
348
+
349
+ export interface ContentCurrentUser {
350
+ id: string
351
+ name: string
352
+ handle?: string | null
353
+ avatar?: string | null
354
+ }
355
+
356
+ export interface ContentStoreStorage {
357
+ getItem(key: string): string | null
358
+ setItem(key: string, value: string): void
359
+ removeItem(key: string): void
360
+ }
361
+
362
+ export interface ContentMediaUploadService {
363
+ uploadLocalMediaItems(items: LocalMediaItem[]): Promise<string[]>
364
+ }
365
+
366
+ export interface ContentStoreLogger {
367
+ error: (...args: unknown[]) => void
368
+ warn: (...args: unknown[]) => void
369
+ info: (...args: unknown[]) => void
370
+ }
371
+
372
+ export interface ContentStoreConfig {
373
+ client: ApiService
374
+ mediaUploadService: ContentMediaUploadService
375
+ getCurrentUser: () => ContentCurrentUser | null
376
+ syncActiveRecipe?: (meta: ContentActiveRecipeMeta | null) => void
377
+ storage?: ContentStoreStorage | null
378
+ pageSize?: number
379
+ logger?: ContentStoreLogger
380
+ storeId?: string
381
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Core type definitions for media.
3
+ */
4
+
5
+ export interface MediaItem {
6
+ id: string
7
+ type: 'image' | 'video' | 'document'
8
+ url: string
9
+ thumbnail_url?: string
10
+ alt_text?: string
11
+ width?: number
12
+ height?: number
13
+ size?: number
14
+ mime_type?: string
15
+ created_at?: string
16
+ updated_at?: string
17
+ }
18
+
19
+ export function isMediaItem(obj: unknown): obj is MediaItem {
20
+ return (
21
+ obj !== null
22
+ && typeof obj === 'object'
23
+ && 'id' in obj
24
+ && 'type' in obj
25
+ && 'url' in obj
26
+ && typeof (obj as MediaItem).type === 'string'
27
+ && ['image', 'video', 'document'].includes((obj as MediaItem).type)
28
+ )
29
+ }
30
+
31
+ export interface UploadedMedia {
32
+ id: string
33
+ url: string
34
+ thumb_url?: string | null
35
+ preview_url?: string | null
36
+ mime_type: string
37
+ size: number
38
+ urls?: {
39
+ original?: string
40
+ thumbnail?: string
41
+ preview?: string
42
+ }
43
+ original_url?: string
44
+ }
45
+
46
+ export interface LocalMediaItem {
47
+ id?: string
48
+ previewUrl: string
49
+ file?: File
50
+ mimeType: string
51
+ name: string
52
+ size: number
53
+ status: 'pending' | 'uploading' | 'uploaded' | 'failed'
54
+ error?: string
55
+ }
56
+
57
+ export interface FilterConfig {
58
+ name: string
59
+ type: string
60
+ value: number | string
61
+ timestamp?: number
62
+ }
63
+
64
+ export type ImageEditorContext = 'profile' | 'editor' | 'gallery'
65
+ export type ImageFormat = 'jpeg' | 'png' | 'webp'
66
+
67
+ export interface ImageEditorSaveData {
68
+ imageData: Blob
69
+ filters: FilterConfig[]
70
+ metadata: ImageEditorMetadata
71
+ }
72
+
73
+ export interface ImageEditorMetadata {
74
+ originalUrl: string
75
+ context: string
76
+ appliedFilters: FilterConfig[]
77
+ processingTime: number
78
+ }
79
+
80
+ export type MediaType = MediaItem['type']
81
+ export type MediaUpdate = Partial<Omit<MediaItem, 'id' | 'created_at'>>