@sylphx/sdk 0.0.1 → 0.2.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 +247 -260
- package/dist/index.js +229 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +228 -65
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs/index.js.map +1 -1
- package/dist/nextjs/index.mjs.map +1 -1
- package/dist/react/index.js +3668 -12695
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +3671 -12698
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.js +40 -39
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +39 -39
- package/dist/server/index.mjs.map +1 -1
- package/dist/web-analytics.js +1 -1
- package/dist/web-analytics.js.map +1 -1
- package/dist/web-analytics.mjs +1 -1
- package/dist/web-analytics.mjs.map +1 -1
- package/package.json +5 -6
- package/dist/index.d.cts +0 -13938
- package/dist/index.d.ts +0 -13938
- package/dist/nextjs/index.d.cts +0 -2089
- package/dist/nextjs/index.d.ts +0 -2089
- package/dist/react/index.d.cts +0 -14894
- package/dist/react/index.d.ts +0 -14894
- package/dist/server/index.d.cts +0 -9908
- package/dist/server/index.d.ts +0 -9908
- package/dist/web-analytics.d.cts +0 -90
- package/dist/web-analytics.d.ts +0 -90
package/README.md
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://sylphx.com/docs)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Auth, billing, analytics, AI, storage, and more — in one SDK.
|
|
9
9
|
|
|
10
|
-
📖 **Full
|
|
10
|
+
📖 **Full docs:** [sylphx.com/docs](https://sylphx.com/docs)
|
|
11
|
+
|
|
12
|
+
---
|
|
11
13
|
|
|
12
14
|
## Installation
|
|
13
15
|
|
|
@@ -15,32 +17,76 @@ Complete SDK for integrating apps with the Sylphx Platform. Get auth, billing, a
|
|
|
15
17
|
npm install @sylphx/sdk
|
|
16
18
|
# or
|
|
17
19
|
pnpm add @sylphx/sdk
|
|
18
|
-
# or
|
|
19
20
|
bun add @sylphx/sdk
|
|
20
21
|
```
|
|
21
22
|
|
|
23
|
+
---
|
|
24
|
+
|
|
22
25
|
## Quick Start (Next.js)
|
|
23
26
|
|
|
24
27
|
### 1. Environment Variables
|
|
25
28
|
|
|
29
|
+
Two keys from your [Platform Console](https://sylphx.com/console):
|
|
30
|
+
|
|
26
31
|
```bash
|
|
27
32
|
# .env.local
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
SYLPHX_PLATFORM_URL=https://sylphx.com
|
|
33
|
+
SYLPHX_SECRET_KEY=sk_dev_xxxxxxxxxxxxxxxxxxxx # server-only
|
|
34
|
+
NEXT_PUBLIC_SYLPHX_APP_ID=app_dev_xxxxxxxxxxxx # safe to expose
|
|
31
35
|
```
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
That's it. No other config needed.
|
|
38
|
+
|
|
39
|
+
> **Key formats**
|
|
40
|
+
> - `sk_dev_*` / `sk_stg_*` / `sk_prod_*` — Secret key (server only, never expose)
|
|
41
|
+
> - `app_dev_*` / `app_stg_*` / `app_prod_*` — App ID (safe for client-side)
|
|
42
|
+
>
|
|
43
|
+
> Get both from **Console → Your App → API Keys**.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### 2. Middleware
|
|
48
|
+
|
|
49
|
+
Handles auth routes (`/auth/callback`, `/auth/signout`) and route protection automatically.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// middleware.ts
|
|
53
|
+
import { createSylphxMiddleware } from '@sylphx/sdk/nextjs'
|
|
54
|
+
|
|
55
|
+
export default createSylphxMiddleware({
|
|
56
|
+
publicRoutes: ['/', '/about', '/pricing', '/login'],
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
export const config = {
|
|
60
|
+
matcher: ['/((?!_next|.*\\..*).*)', '/'],
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
No manual `/api/auth/*` routes needed — the middleware handles everything.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### 3. Root Layout
|
|
69
|
+
|
|
70
|
+
Fetch config server-side once, pass to the provider:
|
|
34
71
|
|
|
35
72
|
```tsx
|
|
36
73
|
// app/layout.tsx
|
|
74
|
+
import { getAppConfig } from '@sylphx/sdk/server'
|
|
37
75
|
import { SylphxProvider } from '@sylphx/sdk/react'
|
|
38
76
|
|
|
39
|
-
export default function RootLayout({ children }) {
|
|
77
|
+
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
78
|
+
const config = await getAppConfig({
|
|
79
|
+
secretKey: process.env.SYLPHX_SECRET_KEY!,
|
|
80
|
+
appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
|
|
81
|
+
})
|
|
82
|
+
|
|
40
83
|
return (
|
|
41
84
|
<html>
|
|
42
85
|
<body>
|
|
43
|
-
<SylphxProvider
|
|
86
|
+
<SylphxProvider
|
|
87
|
+
config={config}
|
|
88
|
+
appId={process.env.NEXT_PUBLIC_SYLPHX_APP_ID!}
|
|
89
|
+
>
|
|
44
90
|
{children}
|
|
45
91
|
</SylphxProvider>
|
|
46
92
|
</body>
|
|
@@ -49,384 +95,325 @@ export default function RootLayout({ children }) {
|
|
|
49
95
|
}
|
|
50
96
|
```
|
|
51
97
|
|
|
52
|
-
|
|
98
|
+
---
|
|
53
99
|
|
|
54
|
-
|
|
55
|
-
// middleware.ts
|
|
56
|
-
import { authMiddleware } from '@sylphx/sdk/nextjs'
|
|
100
|
+
### 4. Protect Pages (Server Components)
|
|
57
101
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
102
|
+
```tsx
|
|
103
|
+
// app/dashboard/page.tsx
|
|
104
|
+
import { currentUser } from '@sylphx/sdk/nextjs'
|
|
105
|
+
import { redirect } from 'next/navigation'
|
|
62
106
|
|
|
63
|
-
export
|
|
64
|
-
|
|
107
|
+
export default async function Dashboard() {
|
|
108
|
+
const user = await currentUser()
|
|
109
|
+
if (!user) redirect('/login')
|
|
110
|
+
|
|
111
|
+
return <h1>Hello, {user.name}</h1>
|
|
65
112
|
}
|
|
66
113
|
```
|
|
67
114
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
// app/api/auth/callback/route.ts
|
|
72
|
-
import { handleCallback } from '@sylphx/sdk/nextjs'
|
|
73
|
-
|
|
74
|
-
export const GET = handleCallback()
|
|
75
|
-
```
|
|
115
|
+
---
|
|
76
116
|
|
|
77
|
-
### 5.
|
|
117
|
+
### 5. Auth UI (Client Components)
|
|
78
118
|
|
|
79
119
|
```tsx
|
|
80
|
-
// app/page.tsx
|
|
81
120
|
'use client'
|
|
121
|
+
import { useUser, SignedIn, SignedOut, UserButton } from '@sylphx/sdk/react'
|
|
82
122
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
export default function Home() {
|
|
123
|
+
export default function Header() {
|
|
86
124
|
const { user } = useUser()
|
|
87
125
|
|
|
88
126
|
return (
|
|
89
|
-
<
|
|
127
|
+
<header>
|
|
90
128
|
<SignedOut>
|
|
91
|
-
<
|
|
129
|
+
<a href="/login">Sign in</a>
|
|
92
130
|
</SignedOut>
|
|
93
|
-
|
|
94
131
|
<SignedIn>
|
|
95
|
-
<
|
|
96
|
-
<UserButton />
|
|
132
|
+
<span>Hello, {user?.name}</span>
|
|
133
|
+
<UserButton afterSignOutUrl="/" />
|
|
97
134
|
</SignedIn>
|
|
98
|
-
</
|
|
135
|
+
</header>
|
|
99
136
|
)
|
|
100
137
|
}
|
|
101
138
|
```
|
|
102
139
|
|
|
103
140
|
---
|
|
104
141
|
|
|
105
|
-
##
|
|
142
|
+
## Server-Side
|
|
106
143
|
|
|
107
|
-
###
|
|
144
|
+
### Get Current User
|
|
108
145
|
|
|
109
146
|
```tsx
|
|
110
|
-
import {
|
|
147
|
+
import { auth, currentUser, currentUserId } from '@sylphx/sdk/nextjs'
|
|
111
148
|
|
|
112
|
-
//
|
|
113
|
-
const {
|
|
149
|
+
// Full auth state
|
|
150
|
+
const { userId, user, sessionToken } = await auth()
|
|
114
151
|
|
|
115
|
-
//
|
|
116
|
-
const
|
|
152
|
+
// Just the user object (null if not signed in)
|
|
153
|
+
const user = await currentUser()
|
|
117
154
|
|
|
118
|
-
//
|
|
119
|
-
const
|
|
155
|
+
// Just the user ID
|
|
156
|
+
const userId = await currentUserId()
|
|
120
157
|
```
|
|
121
158
|
|
|
122
|
-
###
|
|
123
|
-
|
|
124
|
-
```tsx
|
|
125
|
-
import { useBilling } from '@sylphx/sdk/react'
|
|
159
|
+
### Server API Client
|
|
126
160
|
|
|
127
|
-
|
|
161
|
+
```ts
|
|
162
|
+
import { createServerClient } from '@sylphx/sdk/server'
|
|
128
163
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
164
|
+
const client = createServerClient({
|
|
165
|
+
secretKey: process.env.SYLPHX_SECRET_KEY!,
|
|
166
|
+
})
|
|
133
167
|
|
|
134
|
-
//
|
|
135
|
-
const
|
|
136
|
-
window.location.href = checkoutUrl
|
|
168
|
+
// GET /billing/plans
|
|
169
|
+
const plans = await client.GET('/billing/plans')
|
|
137
170
|
|
|
138
|
-
//
|
|
139
|
-
await
|
|
171
|
+
// POST /analytics/track
|
|
172
|
+
await client.POST('/analytics/track', {
|
|
173
|
+
body: { events: [{ event: 'purchase', properties: { amount: 99 } }] },
|
|
174
|
+
})
|
|
140
175
|
```
|
|
141
176
|
|
|
142
|
-
###
|
|
143
|
-
|
|
144
|
-
```tsx
|
|
145
|
-
import { useAnalytics } from '@sylphx/sdk/react'
|
|
146
|
-
|
|
147
|
-
const { track, identify, pageView } = useAnalytics()
|
|
148
|
-
|
|
149
|
-
// Track custom event
|
|
150
|
-
track('button_clicked', { buttonId: 'signup' })
|
|
177
|
+
### Prefetch App Config
|
|
151
178
|
|
|
152
|
-
|
|
153
|
-
|
|
179
|
+
```ts
|
|
180
|
+
import {
|
|
181
|
+
getAppConfig, // All config in one call (recommended)
|
|
182
|
+
getPlans, // Billing plans
|
|
183
|
+
getFeatureFlags, // Feature flag definitions
|
|
184
|
+
getConsentTypes, // GDPR consent config
|
|
185
|
+
} from '@sylphx/sdk/server'
|
|
186
|
+
|
|
187
|
+
const config = await getAppConfig({
|
|
188
|
+
secretKey: process.env.SYLPHX_SECRET_KEY!,
|
|
189
|
+
appId: process.env.NEXT_PUBLIC_SYLPHX_APP_ID!,
|
|
190
|
+
})
|
|
191
|
+
// config.plans, config.featureFlags, config.oauthProviders, config.consentTypes
|
|
154
192
|
```
|
|
155
193
|
|
|
156
|
-
###
|
|
194
|
+
### Verify Webhooks
|
|
157
195
|
|
|
158
|
-
```
|
|
159
|
-
import {
|
|
196
|
+
```ts
|
|
197
|
+
import { verifyWebhook } from '@sylphx/sdk/server'
|
|
160
198
|
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
model: 'anthropic/claude-3.5-sonnet',
|
|
164
|
-
})
|
|
199
|
+
export async function POST(request: Request) {
|
|
200
|
+
const body = await request.text()
|
|
165
201
|
|
|
166
|
-
|
|
167
|
-
|
|
202
|
+
const result = await verifyWebhook({
|
|
203
|
+
payload: body,
|
|
204
|
+
signatureHeader: request.headers.get('x-webhook-signature'),
|
|
205
|
+
secret: process.env.SYLPHX_SECRET_KEY!,
|
|
206
|
+
})
|
|
168
207
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
208
|
+
if (!result.valid) {
|
|
209
|
+
return new Response('Unauthorized', { status: 401 })
|
|
210
|
+
}
|
|
172
211
|
|
|
173
|
-
|
|
212
|
+
const { event, data } = result.payload!
|
|
213
|
+
// handle event...
|
|
214
|
+
return Response.json({ received: true })
|
|
215
|
+
}
|
|
216
|
+
```
|
|
174
217
|
|
|
175
|
-
|
|
218
|
+
Or use the handler factory:
|
|
176
219
|
|
|
177
220
|
```ts
|
|
178
|
-
import {
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
221
|
+
import { createWebhookHandler } from '@sylphx/sdk/server'
|
|
222
|
+
|
|
223
|
+
export const POST = createWebhookHandler({
|
|
224
|
+
secret: process.env.SYLPHX_SECRET_KEY!,
|
|
225
|
+
handlers: {
|
|
226
|
+
'user.created': async (data) => { /* ... */ },
|
|
227
|
+
'subscription.updated': async (data) => { /* ... */ },
|
|
228
|
+
},
|
|
183
229
|
})
|
|
230
|
+
```
|
|
184
231
|
|
|
185
|
-
|
|
186
|
-
const users = await sylphx.database.query<{ id: string; email: string }>(
|
|
187
|
-
'SELECT id, email FROM users WHERE active = true LIMIT $1',
|
|
188
|
-
[100],
|
|
189
|
-
)
|
|
232
|
+
### JWT Verification
|
|
190
233
|
|
|
191
|
-
|
|
192
|
-
|
|
234
|
+
```ts
|
|
235
|
+
import { verifyAccessToken } from '@sylphx/sdk/server'
|
|
193
236
|
|
|
194
|
-
|
|
195
|
-
|
|
237
|
+
const payload = await verifyAccessToken(token, {
|
|
238
|
+
secretKey: process.env.SYLPHX_SECRET_KEY!,
|
|
239
|
+
})
|
|
240
|
+
// payload.sub, payload.email, payload.role, payload.app_id
|
|
196
241
|
```
|
|
197
242
|
|
|
198
|
-
|
|
199
|
-
> The platform manages connection pooling automatically.
|
|
200
|
-
|
|
201
|
-
### Storage
|
|
243
|
+
---
|
|
202
244
|
|
|
203
|
-
|
|
204
|
-
import { useStorage } from '@sylphx/sdk/react'
|
|
245
|
+
## React Hooks
|
|
205
246
|
|
|
206
|
-
|
|
247
|
+
### Auth
|
|
207
248
|
|
|
208
|
-
|
|
209
|
-
|
|
249
|
+
```tsx
|
|
250
|
+
import { useUser, useAuth } from '@sylphx/sdk/react'
|
|
210
251
|
|
|
211
|
-
|
|
212
|
-
const
|
|
252
|
+
const { user, isLoading, isSignedIn } = useUser()
|
|
253
|
+
const { signIn, signUp, signOut, forgotPassword } = useAuth()
|
|
213
254
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
console.log(`Upload progress: ${progress}%`)
|
|
217
|
-
}
|
|
255
|
+
await signIn({ email: 'user@example.com', password: '...' })
|
|
256
|
+
await signOut()
|
|
218
257
|
```
|
|
219
258
|
|
|
220
|
-
###
|
|
259
|
+
### Billing
|
|
221
260
|
|
|
222
261
|
```tsx
|
|
223
|
-
|
|
224
|
-
import { useFeatureFlag, useFeatureFlags } from '@sylphx/sdk/react'
|
|
225
|
-
const { isEnabled, variant, isLoading } = useFeatureFlag('new-dashboard')
|
|
226
|
-
const flags = useFeatureFlags(['dark-mode', 'beta-features'])
|
|
227
|
-
|
|
228
|
-
// Error tracking - capture exceptions and breadcrumbs
|
|
229
|
-
import { useErrorTracking } from '@sylphx/sdk/react'
|
|
230
|
-
const { captureException, addBreadcrumb, setRoute } = useErrorTracking()
|
|
231
|
-
|
|
232
|
-
// Referrals - referral program management
|
|
233
|
-
import { useReferral } from '@sylphx/sdk/react'
|
|
262
|
+
import { useBilling } from '@sylphx/sdk/react'
|
|
234
263
|
|
|
235
|
-
|
|
236
|
-
import { useConsent } from '@sylphx/sdk/react'
|
|
264
|
+
const { subscription, isPremium, plans, createCheckout, openPortal } = useBilling()
|
|
237
265
|
|
|
238
|
-
//
|
|
239
|
-
|
|
266
|
+
// Check access
|
|
267
|
+
if (!isPremium) return <UpgradePrompt />
|
|
240
268
|
|
|
241
|
-
//
|
|
242
|
-
|
|
269
|
+
// Start checkout
|
|
270
|
+
const url = await createCheckout('pro', 'monthly')
|
|
271
|
+
window.location.href = url
|
|
243
272
|
|
|
244
|
-
//
|
|
245
|
-
|
|
273
|
+
// Manage subscription
|
|
274
|
+
await openPortal()
|
|
246
275
|
```
|
|
247
276
|
|
|
248
|
-
|
|
277
|
+
### Analytics
|
|
249
278
|
|
|
250
|
-
|
|
279
|
+
```tsx
|
|
280
|
+
import { useAnalytics } from '@sylphx/sdk/react'
|
|
251
281
|
|
|
252
|
-
|
|
282
|
+
const { track, identify, page } = useAnalytics()
|
|
253
283
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
SignIn,
|
|
257
|
-
SignUp,
|
|
258
|
-
UserButton,
|
|
259
|
-
ForgotPassword,
|
|
260
|
-
ResetPassword,
|
|
261
|
-
VerifyEmail,
|
|
262
|
-
} from '@sylphx/sdk/react'
|
|
263
|
-
|
|
264
|
-
// Embedded sign-in form
|
|
265
|
-
<SignIn mode="embedded" afterSignInUrl="/dashboard" />
|
|
266
|
-
|
|
267
|
-
// Modal sign-in
|
|
268
|
-
<SignIn mode="modal" />
|
|
269
|
-
|
|
270
|
-
// User avatar with dropdown menu
|
|
271
|
-
<UserButton afterSignOutUrl="/" />
|
|
284
|
+
track('button_clicked', { button: 'upgrade' })
|
|
285
|
+
identify({ name: 'John', email: 'john@example.com' })
|
|
272
286
|
```
|
|
273
287
|
|
|
274
|
-
###
|
|
288
|
+
### Feature Flags
|
|
275
289
|
|
|
276
290
|
```tsx
|
|
277
|
-
import {
|
|
278
|
-
|
|
279
|
-
// Show only to signed-in users
|
|
280
|
-
<SignedIn>
|
|
281
|
-
<Dashboard />
|
|
282
|
-
</SignedIn>
|
|
283
|
-
|
|
284
|
-
// Show only to signed-out users
|
|
285
|
-
<SignedOut>
|
|
286
|
-
<SignIn mode="embedded" />
|
|
287
|
-
</SignedOut>
|
|
291
|
+
import { useFeatureFlag } from '@sylphx/sdk/react'
|
|
288
292
|
|
|
289
|
-
|
|
290
|
-
<
|
|
291
|
-
<AdminPanel />
|
|
292
|
-
</Protect>
|
|
293
|
+
const { isEnabled } = useFeatureFlag('new-dashboard')
|
|
294
|
+
if (isEnabled) return <NewDashboard />
|
|
293
295
|
```
|
|
294
296
|
|
|
295
|
-
###
|
|
297
|
+
### AI
|
|
296
298
|
|
|
297
299
|
```tsx
|
|
298
|
-
import {
|
|
300
|
+
import { useChat, useCompletion } from '@sylphx/sdk/react'
|
|
299
301
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// Current subscription card
|
|
304
|
-
<BillingCard />
|
|
302
|
+
const { messages, send, isLoading } = useChat({
|
|
303
|
+
model: 'anthropic/claude-3.5-sonnet',
|
|
304
|
+
})
|
|
305
305
|
|
|
306
|
-
|
|
307
|
-
<CheckoutButton planSlug="pro" interval="monthly">
|
|
308
|
-
Upgrade to Pro
|
|
309
|
-
</CheckoutButton>
|
|
306
|
+
await send('What is the meaning of life?')
|
|
310
307
|
```
|
|
311
308
|
|
|
312
|
-
###
|
|
309
|
+
### Storage
|
|
313
310
|
|
|
314
311
|
```tsx
|
|
315
|
-
import {
|
|
316
|
-
|
|
317
|
-
// Switch between orgs
|
|
318
|
-
<OrganizationSwitcher />
|
|
312
|
+
import { useStorage } from '@sylphx/sdk/react'
|
|
319
313
|
|
|
320
|
-
|
|
321
|
-
<MembersList />
|
|
314
|
+
const { upload, uploadAvatar, isUploading, progress } = useStorage()
|
|
322
315
|
|
|
323
|
-
|
|
324
|
-
|
|
316
|
+
const url = await upload(file, { path: 'documents/' })
|
|
317
|
+
const avatarUrl = await uploadAvatar(imageFile)
|
|
325
318
|
```
|
|
326
319
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
## Server-Side (Next.js)
|
|
330
|
-
|
|
331
|
-
### Get Current User
|
|
320
|
+
### More Hooks
|
|
332
321
|
|
|
333
322
|
```tsx
|
|
334
|
-
//
|
|
335
|
-
import {
|
|
323
|
+
import { useConsent } from '@sylphx/sdk/react' // GDPR consent
|
|
324
|
+
import { useFeatureFlags } from '@sylphx/sdk/react' // All flags at once
|
|
325
|
+
import { useNotifications } from '@sylphx/sdk/react' // In-app notifications
|
|
326
|
+
import { useReferral } from '@sylphx/sdk/react' // Referral program
|
|
327
|
+
import { useOrganization } from '@sylphx/sdk/react' // Multi-tenant orgs
|
|
328
|
+
import { useJobs } from '@sylphx/sdk/react' // Background jobs
|
|
329
|
+
import { useErrorTracking } from '@sylphx/sdk/react' // Error capture
|
|
330
|
+
```
|
|
336
331
|
|
|
337
|
-
|
|
338
|
-
const user = await currentUser()
|
|
332
|
+
---
|
|
339
333
|
|
|
340
|
-
|
|
341
|
-
redirect('/login')
|
|
342
|
-
}
|
|
334
|
+
## UI Components
|
|
343
335
|
|
|
344
|
-
|
|
345
|
-
}
|
|
336
|
+
### Auth
|
|
346
337
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const { userId, accessToken } = await auth()
|
|
338
|
+
```tsx
|
|
339
|
+
import { SignIn, SignUp, UserButton, SignedIn, SignedOut } from '@sylphx/sdk/react'
|
|
350
340
|
|
|
351
|
-
|
|
352
|
-
|
|
341
|
+
<SignedOut><SignIn mode="embedded" afterSignInUrl="/dashboard" /></SignedOut>
|
|
342
|
+
<SignedIn><UserButton afterSignOutUrl="/" /></SignedIn>
|
|
353
343
|
```
|
|
354
344
|
|
|
355
|
-
###
|
|
345
|
+
### Billing
|
|
356
346
|
|
|
357
347
|
```tsx
|
|
358
|
-
import {
|
|
348
|
+
import { PricingTable, CheckoutButton } from '@sylphx/sdk/react'
|
|
359
349
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
})
|
|
350
|
+
<PricingTable plans={plans} />
|
|
351
|
+
<CheckoutButton planSlug="pro" interval="monthly">Upgrade</CheckoutButton>
|
|
352
|
+
```
|
|
364
353
|
|
|
365
|
-
|
|
366
|
-
await sylphx.analytics.track.mutate({
|
|
367
|
-
event: 'purchase_completed',
|
|
368
|
-
userId: user.id,
|
|
369
|
-
properties: { amount: 99.99 },
|
|
370
|
-
})
|
|
354
|
+
### Route Protection
|
|
371
355
|
|
|
372
|
-
|
|
373
|
-
|
|
356
|
+
```tsx
|
|
357
|
+
import { Protect } from '@sylphx/sdk/react'
|
|
374
358
|
|
|
375
|
-
|
|
376
|
-
|
|
359
|
+
<Protect role="admin">
|
|
360
|
+
<AdminPanel />
|
|
361
|
+
</Protect>
|
|
377
362
|
```
|
|
378
363
|
|
|
379
364
|
---
|
|
380
365
|
|
|
381
|
-
##
|
|
366
|
+
## Pure Functions (Server or Client)
|
|
382
367
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
Creates a server-side API client with full TypeScript inference.
|
|
368
|
+
For non-React environments or maximum control:
|
|
386
369
|
|
|
387
370
|
```ts
|
|
388
|
-
|
|
389
|
-
appId: string, // Your app slug
|
|
390
|
-
appSecret: string, // sk_dev_*, sk_stg_*, or sk_prod_*
|
|
391
|
-
platformUrl?: string, // Default: https://sylphx.com
|
|
392
|
-
accessToken?: string, // User access token (optional)
|
|
393
|
-
})
|
|
394
|
-
```
|
|
371
|
+
import { createConfig, signIn, track, getPlans } from '@sylphx/sdk'
|
|
395
372
|
|
|
396
|
-
|
|
373
|
+
const config = createConfig({ secretKey: process.env.SYLPHX_SECRET_KEY! })
|
|
397
374
|
|
|
398
|
-
|
|
375
|
+
// Auth
|
|
376
|
+
const tokens = await signIn(config, { email, password })
|
|
377
|
+
const authedConfig = withToken(config, tokens.accessToken)
|
|
399
378
|
|
|
400
|
-
|
|
379
|
+
// Analytics
|
|
380
|
+
await track(config, { event: 'purchase', properties: { amount: 99 } })
|
|
401
381
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
| `user` | `getProfile`, `updateProfile`, `changePassword`, `getSecuritySettings`, `getLoginHistory`, `deleteAccount` |
|
|
406
|
-
| `billing` | `getPlans`, `getSubscription`, `createCheckout`, `createPortalSession`, `cancelSubscription` |
|
|
407
|
-
| `analytics` | `track`, `trackBatch`, `identify`, `pageView` |
|
|
408
|
-
| `notifications` | `list`, `markRead`, `getUnreadCount`, `getPreferences` |
|
|
409
|
-
| `referrals` | `getMyCode`, `redeem`, `getStats` |
|
|
410
|
-
| `flags` | `check`, `getAll`, `checkWithDetail`, `getAllWithDetail` |
|
|
411
|
-
| `storage` | `getUploadUrl`, `uploadAvatar` |
|
|
412
|
-
| `jobs` | `submit`, `getStatus`, `cancel`, `list` |
|
|
382
|
+
// Billing
|
|
383
|
+
const plans = await getPlans(config)
|
|
384
|
+
```
|
|
413
385
|
|
|
414
386
|
---
|
|
415
387
|
|
|
416
388
|
## Entry Points
|
|
417
389
|
|
|
418
|
-
| Import | Use
|
|
419
|
-
|
|
420
|
-
| `@sylphx/sdk` |
|
|
421
|
-
| `@sylphx/sdk/react` | React hooks, components,
|
|
422
|
-
| `@sylphx/sdk/
|
|
390
|
+
| Import path | Use for |
|
|
391
|
+
|---|---|
|
|
392
|
+
| `@sylphx/sdk` | Pure functions (server or client, no React) |
|
|
393
|
+
| `@sylphx/sdk/react` | React hooks, components, `SylphxProvider` |
|
|
394
|
+
| `@sylphx/sdk/server` | JWT verification, webhook verification, server client |
|
|
395
|
+
| `@sylphx/sdk/nextjs` | `createSylphxMiddleware`, `auth()`, `currentUser()` |
|
|
423
396
|
|
|
424
397
|
---
|
|
425
398
|
|
|
426
399
|
## TypeScript
|
|
427
400
|
|
|
428
|
-
|
|
401
|
+
All types are fully inferred. Import them directly:
|
|
429
402
|
|
|
430
|
-
```
|
|
431
|
-
import type { User, Plan, Subscription } from '@sylphx/sdk'
|
|
403
|
+
```ts
|
|
404
|
+
import type { User, Plan, Subscription, AppConfig } from '@sylphx/sdk'
|
|
405
|
+
import type { AuthResult } from '@sylphx/sdk/nextjs'
|
|
432
406
|
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Self-Hosting
|
|
411
|
+
|
|
412
|
+
If you're running your own Sylphx Platform deployment:
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
# .env.local — only needed for self-hosting
|
|
416
|
+
SYLPHX_PLATFORM_URL=https://platform.your-domain.com
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
You will not need this if you're using the hosted platform at [sylphx.com](https://sylphx.com).
|