@fiction/sdk 1.0.18 → 1.0.19
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/modules/self/schema.ts +92 -0
- package/dist/modules/user/schema.ts +139 -0
- package/dist/types/media.ts +106 -0
- package/package.json +2 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { MediaSchema } from '@/types/media'
|
|
3
|
+
|
|
4
|
+
// Core self schema - define manually for better type control (still using Drizzle as reference)
|
|
5
|
+
export const selfSchema = z.object({
|
|
6
|
+
selfId: z.string().optional(),
|
|
7
|
+
handle: z.string().optional(),
|
|
8
|
+
ownerId: z.string().optional(),
|
|
9
|
+
orgId: z.string().optional(),
|
|
10
|
+
name: z.string().optional(),
|
|
11
|
+
title: z.string().nullable().optional(),
|
|
12
|
+
summary: z.string().nullable().optional(),
|
|
13
|
+
entityType: z.string().optional(),
|
|
14
|
+
|
|
15
|
+
// Media foreign keys and joined objects
|
|
16
|
+
avatarId: z.string().nullable().optional(),
|
|
17
|
+
coverId: z.string().nullable().optional(),
|
|
18
|
+
avatar: MediaSchema.optional(), // Joined MediaObject for UI
|
|
19
|
+
cover: MediaSchema.optional(), // Joined MediaObject for UI
|
|
20
|
+
voiceRecordings: z.array(MediaSchema).optional(), // Joined voice media with context: 'voice'
|
|
21
|
+
|
|
22
|
+
// Contact and social media
|
|
23
|
+
email: z.string().nullable().optional(),
|
|
24
|
+
website: z.string().url().nullable().optional(),
|
|
25
|
+
accounts: z.record(z.string(), z.object({
|
|
26
|
+
handle: z.string().optional(),
|
|
27
|
+
url: z.string().optional(),
|
|
28
|
+
})).nullable().optional(), // Social media accounts: { linkedin?: { handle: string }, x?: { handle: string }, etc. }
|
|
29
|
+
|
|
30
|
+
// AI Configuration
|
|
31
|
+
basePrompt: z.string().nullable().optional(),
|
|
32
|
+
firstMessage: z.string().nullable().optional(),
|
|
33
|
+
personalityPrompt: z.string().nullable().optional(), // AI-generated personality with concise examples
|
|
34
|
+
useCustomPrompts: z.boolean().nullable().optional(), // Boolean flag for custom vs generated prompts
|
|
35
|
+
elevenlabsVoiceId: z.string().nullable().optional(),
|
|
36
|
+
elevenlabsAgentId: z.string().nullable().optional(),
|
|
37
|
+
|
|
38
|
+
// Personality fields
|
|
39
|
+
headline: z.string().nullable().optional(),
|
|
40
|
+
industry: z.string().nullable().optional(),
|
|
41
|
+
location: z.string().nullable().optional(),
|
|
42
|
+
influences: z.array(z.string()).nullable().optional(),
|
|
43
|
+
interests: z.array(z.string()).nullable().optional(),
|
|
44
|
+
personalDetails: z.string().nullable().optional(),
|
|
45
|
+
cloutScore: z.number().nullable().optional(),
|
|
46
|
+
|
|
47
|
+
// Demographics (optional)
|
|
48
|
+
gender: z.string().nullable().optional(),
|
|
49
|
+
birthdayAt: z.string().nullable().optional(), // ISO date string
|
|
50
|
+
|
|
51
|
+
// Business configuration
|
|
52
|
+
businessTemplate: z.string().nullable().optional(),
|
|
53
|
+
|
|
54
|
+
// JSONB fields
|
|
55
|
+
enrichment: z.record(z.string(), z.any()).nullable().optional(),
|
|
56
|
+
onboarding: z.record(z.string(), z.any()).nullable().optional(),
|
|
57
|
+
|
|
58
|
+
// Joined org data - inline type following YAGNI principle
|
|
59
|
+
org: z.object({
|
|
60
|
+
orgId: z.string(),
|
|
61
|
+
handle: z.string(),
|
|
62
|
+
name: z.string(),
|
|
63
|
+
headline: z.string().optional(),
|
|
64
|
+
summary: z.string().optional(),
|
|
65
|
+
status: z.string(),
|
|
66
|
+
}).optional(),
|
|
67
|
+
|
|
68
|
+
// Meta
|
|
69
|
+
visibility: z.enum(['private', 'org', 'public']).optional(),
|
|
70
|
+
status: z.string().optional(),
|
|
71
|
+
createdAt: z.string().optional(), // ISO string for JSON compatibility
|
|
72
|
+
updatedAt: z.string().optional(), // ISO string for JSON compatibility
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
export const EnrichedSelfSchema = selfSchema.extend({
|
|
76
|
+
avatar: MediaSchema.optional(),
|
|
77
|
+
cover: MediaSchema.optional(),
|
|
78
|
+
voiceRecordings: z.array(MediaSchema).optional(),
|
|
79
|
+
isPrimary: z.boolean().optional(), // For selves within org context
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Type exports - all derived from Drizzle schema
|
|
83
|
+
export type Self = z.infer<typeof EnrichedSelfSchema>
|
|
84
|
+
|
|
85
|
+
// Create/Update types using the same flexible Self type
|
|
86
|
+
export type CreateSelf = Self
|
|
87
|
+
export type UpdateSelf = Self
|
|
88
|
+
|
|
89
|
+
// AiEnhancement type now imported from onboard/generation.ts
|
|
90
|
+
|
|
91
|
+
// Re-export Drizzle types for database operations
|
|
92
|
+
export type { Self as DrizzleSelf, SelfInsert as DrizzleSelfInsert } from '@/modules/db/tables/schema/selves'
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { selfSchema } from '@/modules/self/schema'
|
|
3
|
+
import { MediaSchema } from '@/types/media'
|
|
4
|
+
|
|
5
|
+
export const userSchema = z.object({
|
|
6
|
+
userId: z.string(),
|
|
7
|
+
email: z.string().optional(),
|
|
8
|
+
handle: z.string().optional(),
|
|
9
|
+
fullName: z.string().optional(),
|
|
10
|
+
emailVerified: z.boolean().optional(),
|
|
11
|
+
hashedPassword: z.string().optional(),
|
|
12
|
+
primarySelfId: z.string().optional(),
|
|
13
|
+
onboarding: z.any().optional(),
|
|
14
|
+
recentSelfIds: z.array(z.string()).optional(),
|
|
15
|
+
status: z.string().optional(),
|
|
16
|
+
lastSeenAt: z.string().optional(),
|
|
17
|
+
createdAt: z.string().optional(),
|
|
18
|
+
updatedAt: z.string().optional(),
|
|
19
|
+
onboarded: z.boolean().optional(),
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export const updateUserSchema = z.object({
|
|
23
|
+
name: z.string().min(1).max(100).optional(),
|
|
24
|
+
primarySelfId: z.string().optional(),
|
|
25
|
+
onboarding: z.any().optional(),
|
|
26
|
+
}).partial()
|
|
27
|
+
|
|
28
|
+
export const emailSchema = z.object({
|
|
29
|
+
email: z.string(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export const loginSchema = z.object({
|
|
33
|
+
email: z.string(),
|
|
34
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
export const registerSchema = z.object({
|
|
38
|
+
email: z.string(),
|
|
39
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
40
|
+
fullName: z.string().min(1, 'Name is required'),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
export const verifyCodeSchema = z.object({
|
|
44
|
+
email: z.string(),
|
|
45
|
+
code: z.string().min(6, 'Verification code is required'),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
export const resetPasswordSchema = z.object({
|
|
49
|
+
email: z.string(),
|
|
50
|
+
code: z.string().min(6, 'Verification code is required'),
|
|
51
|
+
newPassword: z.string().min(8, 'New password must be at least 8 characters'),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
export const changeEmailSchema = z.object({
|
|
55
|
+
newEmail: z.string(),
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
export const changePasswordSchema = z.object({
|
|
59
|
+
newPassword: z.string().min(8, 'New password must be at least 8 characters'),
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
export const googleAuthSchema = z.object({
|
|
63
|
+
credential: z.string().optional(),
|
|
64
|
+
code: z.string().optional(),
|
|
65
|
+
createOnEmpty: z.boolean().optional(),
|
|
66
|
+
}).refine((data) => data.credential || data.code, {
|
|
67
|
+
message: 'Either credential or code must be provided',
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
export const orgSchema = z.object({
|
|
71
|
+
orgId: z.string().optional(),
|
|
72
|
+
handle: z.string().optional(),
|
|
73
|
+
name: z.string().optional(),
|
|
74
|
+
email: z.string().optional(),
|
|
75
|
+
website: z.string().url().nullable().optional(),
|
|
76
|
+
summary: z.string().optional(),
|
|
77
|
+
avatarId: z.string().optional(),
|
|
78
|
+
avatar: MediaSchema.optional(),
|
|
79
|
+
coverId: z.string().optional(),
|
|
80
|
+
cover: MediaSchema.optional(),
|
|
81
|
+
accounts: z.record(z.string(), z.object({
|
|
82
|
+
handle: z.string().optional(),
|
|
83
|
+
url: z.string().optional(),
|
|
84
|
+
})).nullable().optional(),
|
|
85
|
+
ownerId: z.string().optional(),
|
|
86
|
+
billingStatus: z.string().optional(),
|
|
87
|
+
isPersonal: z.boolean().optional(),
|
|
88
|
+
stripeCustomerIdTest: z.string().optional(),
|
|
89
|
+
stripeCustomerIdLive: z.string().optional(),
|
|
90
|
+
subscriptionStatus: z.string().optional(),
|
|
91
|
+
planId: z.string().optional(),
|
|
92
|
+
maxSelves: z.number().optional(),
|
|
93
|
+
maxUsers: z.number().optional(),
|
|
94
|
+
onboarding: z.any().optional(),
|
|
95
|
+
status: z.string().optional(),
|
|
96
|
+
createdAt: z.string().optional(),
|
|
97
|
+
updatedAt: z.string().optional(),
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
export type User = z.infer<typeof userSchema>
|
|
101
|
+
export type UpdateUser = z.infer<typeof updateUserSchema>
|
|
102
|
+
export type Org = z.infer<typeof orgSchema>
|
|
103
|
+
|
|
104
|
+
export type { User as DrizzleUser, UserInsert as DrizzleUserInsert } from '@/modules/db/tables/schema/users'
|
|
105
|
+
|
|
106
|
+
export type AuthMode = 'start' | 'pass' | 'verify' | 'set-password' | 'forgot' | 'success'
|
|
107
|
+
|
|
108
|
+
export const orgInfoSchema = z.object({
|
|
109
|
+
membershipId: z.string(),
|
|
110
|
+
orgId: z.string(),
|
|
111
|
+
name: z.string(),
|
|
112
|
+
handle: z.string(),
|
|
113
|
+
avatarId: z.string().optional(),
|
|
114
|
+
avatar: MediaSchema.optional(),
|
|
115
|
+
coverId: z.string().optional(),
|
|
116
|
+
cover: MediaSchema.optional(),
|
|
117
|
+
role: z.enum(['owner', 'admin', 'member', 'observer']),
|
|
118
|
+
joinedAt: z.string(),
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
export const enrichedUserSchema = userSchema.extend({
|
|
122
|
+
orgs: z.array(orgInfoSchema).optional(),
|
|
123
|
+
memberships: z.array(orgInfoSchema).optional(),
|
|
124
|
+
selves: z.array(selfSchema).optional(),
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
export type OrgInfo = z.infer<typeof orgInfoSchema>
|
|
128
|
+
export type MembershipInfo = z.infer<typeof orgInfoSchema> // Alias for OrgInfo
|
|
129
|
+
export type EnrichedUser = z.infer<typeof enrichedUserSchema>
|
|
130
|
+
|
|
131
|
+
export type ApiResponse<T = any> = {
|
|
132
|
+
ok: true
|
|
133
|
+
data: T
|
|
134
|
+
user?: EnrichedUser
|
|
135
|
+
token?: string
|
|
136
|
+
} | {
|
|
137
|
+
ok: false
|
|
138
|
+
error: string
|
|
139
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
// Core media enums - defined here as single source of truth
|
|
4
|
+
export const MediaFormatSchema = z.enum(['image', 'video', 'audio'])
|
|
5
|
+
export type MediaFormat = z.infer<typeof MediaFormatSchema>
|
|
6
|
+
|
|
7
|
+
export const MediaContextSchema = z.enum(['avatar', 'cover', 'voice', 'general'])
|
|
8
|
+
export type MediaContext = z.infer<typeof MediaContextSchema>
|
|
9
|
+
|
|
10
|
+
export const MediaStatusSchema = z.enum(['processing', 'active', 'failed', 'deleted'])
|
|
11
|
+
export type MediaStatus = z.infer<typeof MediaStatusSchema>
|
|
12
|
+
|
|
13
|
+
// Format-specific enums for file extensions
|
|
14
|
+
export const ImageFormatSchema = z.enum(['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'])
|
|
15
|
+
export type ImageFormat = z.infer<typeof ImageFormatSchema>
|
|
16
|
+
|
|
17
|
+
export const VideoFormatSchema = z.enum(['mp4', 'webm', 'ogg', 'mov', 'avi'])
|
|
18
|
+
export type VideoFormat = z.infer<typeof VideoFormatSchema>
|
|
19
|
+
|
|
20
|
+
export const AudioFormatSchema = z.enum(['mp3', 'wav', 'ogg', 'aac', 'flac'])
|
|
21
|
+
export type AudioFormat = z.infer<typeof AudioFormatSchema>
|
|
22
|
+
|
|
23
|
+
// Base media schema - independent definition
|
|
24
|
+
const baseMediaSchema = z.object({
|
|
25
|
+
mediaId: z.string(),
|
|
26
|
+
userId: z.string(),
|
|
27
|
+
orgId: z.string(),
|
|
28
|
+
selfId: z.string().nullable().optional(),
|
|
29
|
+
filename: z.string(),
|
|
30
|
+
mimeType: z.string(),
|
|
31
|
+
size: z.number(),
|
|
32
|
+
src: z.string(),
|
|
33
|
+
alt: z.string().optional(),
|
|
34
|
+
context: MediaContextSchema.default('general'),
|
|
35
|
+
status: MediaStatusSchema.default('processing'),
|
|
36
|
+
createdAt: z.string().optional(), // ISO string for JSON compatibility
|
|
37
|
+
updatedAt: z.string().optional(), // ISO string for JSON compatibility
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// Extended MediaObject for UI use - with UI-friendly field names
|
|
41
|
+
export const MediaSchema = baseMediaSchema.extend({
|
|
42
|
+
// Additional UI fields not in database
|
|
43
|
+
format: MediaFormatSchema.optional(), // Derived from mimeType
|
|
44
|
+
className: z.string().optional(), // CSS classes for rendering
|
|
45
|
+
|
|
46
|
+
// Image/video dimensions
|
|
47
|
+
width: z.number().optional(),
|
|
48
|
+
height: z.number().optional(),
|
|
49
|
+
|
|
50
|
+
// Audio/video duration
|
|
51
|
+
duration: z.number().optional(),
|
|
52
|
+
|
|
53
|
+
// Image blur hash for loading placeholders
|
|
54
|
+
blurhash: z.string().optional(),
|
|
55
|
+
}).partial() // Make all fields optional for UI flexibility
|
|
56
|
+
|
|
57
|
+
// Video-specific properties
|
|
58
|
+
export const VideoPropertiesSchema = z.object({
|
|
59
|
+
duration: z.number().optional(), // in seconds
|
|
60
|
+
thumbnail: z.string().optional(),
|
|
61
|
+
autoplay: z.boolean().optional(),
|
|
62
|
+
loop: z.boolean().optional(),
|
|
63
|
+
muted: z.boolean().optional(),
|
|
64
|
+
controls: z.boolean().optional(),
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Audio-specific properties
|
|
68
|
+
export const AudioPropertiesSchema = z.object({
|
|
69
|
+
duration: z.number().optional(), // in seconds
|
|
70
|
+
autoplay: z.boolean().optional(),
|
|
71
|
+
loop: z.boolean().optional(),
|
|
72
|
+
muted: z.boolean().optional(),
|
|
73
|
+
controls: z.boolean().optional(),
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Extended media schemas with format-specific properties
|
|
77
|
+
export const ImageMediaSchema = MediaSchema.extend({
|
|
78
|
+
format: z.literal('image'),
|
|
79
|
+
imageFormat: ImageFormatSchema,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export const VideoMediaSchema = MediaSchema.extend({
|
|
83
|
+
format: z.literal('video'),
|
|
84
|
+
videoFormat: VideoFormatSchema,
|
|
85
|
+
video: VideoPropertiesSchema.optional(),
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
export const AudioMediaSchema = MediaSchema.extend({
|
|
89
|
+
format: z.literal('audio'),
|
|
90
|
+
audioFormat: AudioFormatSchema,
|
|
91
|
+
audio: AudioPropertiesSchema.optional(),
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// Union type for all media
|
|
95
|
+
export const MediaUnionSchema = z.discriminatedUnion('format', [
|
|
96
|
+
ImageMediaSchema,
|
|
97
|
+
VideoMediaSchema,
|
|
98
|
+
AudioMediaSchema,
|
|
99
|
+
])
|
|
100
|
+
|
|
101
|
+
// Type exports
|
|
102
|
+
export type MediaObject = z.infer<typeof MediaSchema>
|
|
103
|
+
export type ImageMedia = z.infer<typeof ImageMediaSchema>
|
|
104
|
+
export type VideoMedia = z.infer<typeof VideoMediaSchema>
|
|
105
|
+
export type AudioMedia = z.infer<typeof AudioMediaSchema>
|
|
106
|
+
export type MediaUnion = z.infer<typeof MediaUnionSchema>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiction/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "SDK for Fiction app authentication and user management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/sdk.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"nanoid": "^5.1.6",
|
|
55
55
|
"nanostores": "^1.0.1",
|
|
56
56
|
"zod": "^4.1.11",
|
|
57
|
-
"@fiction/sdk": "1.0.
|
|
57
|
+
"@fiction/sdk": "1.0.19"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@antfu/eslint-config": "^5.4.1",
|