@linkforty/core 1.4.3 → 1.5.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/LICENSE +620 -21
- package/README.md +247 -126
- package/dist/lib/database.d.ts.map +1 -1
- package/dist/lib/database.js +2 -14
- package/dist/lib/database.js.map +1 -1
- package/dist/lib/event-emitter.d.ts +1 -1
- package/dist/lib/event-emitter.d.ts.map +1 -1
- package/dist/lib/fingerprint.d.ts.map +1 -1
- package/dist/lib/fingerprint.js +3 -1
- package/dist/lib/fingerprint.js.map +1 -1
- package/dist/routes/analytics.d.ts.map +1 -1
- package/dist/routes/analytics.js +22 -19
- package/dist/routes/analytics.js.map +1 -1
- package/dist/routes/debug.d.ts.map +1 -1
- package/dist/routes/debug.js +11 -13
- package/dist/routes/debug.js.map +1 -1
- package/dist/routes/links.d.ts.map +1 -1
- package/dist/routes/links.js +62 -34
- package/dist/routes/links.js.map +1 -1
- package/dist/routes/sdk.d.ts.map +1 -1
- package/dist/routes/sdk.js +214 -2
- package/dist/routes/sdk.js.map +1 -1
- package/dist/routes/webhooks.d.ts.map +1 -1
- package/dist/routes/webhooks.js +40 -24
- package/dist/routes/webhooks.js.map +1 -1
- package/dist/types/index.d.ts +1 -29
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
# LinkForty Core
|
|
5
5
|
|
|
6
|
-
**Open-source deeplink
|
|
6
|
+
**Open-source deeplink framework with device detection, analytics, and smart routing**
|
|
7
7
|
|
|
8
|
-
LinkForty Core is a
|
|
8
|
+
LinkForty Core is a TypeScript deeplink framework built on Fastify + PostgreSQL. It provides the engine for creating, managing, and tracking smart links with device-specific routing, targeting rules, QR codes, deferred deep linking, and webhook integrations. Auth, UI, and user management are not included — bring your own, or use separate packages like `@linkforty/ui`.
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/@linkforty/core)
|
|
@@ -13,18 +13,25 @@
|
|
|
13
13
|
[](https://codecov.io/gh/linkforty/core)
|
|
14
14
|
[](https://hub.docker.com/r/linkforty/core)
|
|
15
15
|
[](https://hub.docker.com/r/linkforty/core)
|
|
16
|
-
[](https://www.gnu.org/licenses/agpl-3.0)
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
**Smart Link Routing** - Create short links with device-specific URLs for iOS, Android, and web \
|
|
21
|
+
**Device Detection** - Automatic detection and routing based on user device \
|
|
22
|
+
**Click Analytics** - Track clicks with geolocation, device type, platform, and more \
|
|
23
|
+
**UTM Parameters** - Built-in support for UTM campaign tracking \
|
|
24
|
+
**Targeting Rules** - Filter by country, device, and language before redirecting \
|
|
25
|
+
**QR Code Generation** - Generate QR codes (PNG/SVG) for any link \
|
|
26
|
+
**Deferred Deep Linking** - Probabilistic fingerprint matching for install attribution \
|
|
27
|
+
**Webhooks** - Event-driven integrations with HMAC-signed payloads and retry logic \
|
|
28
|
+
**OG Preview Pages** - Social media scraper detection with Open Graph meta tags \
|
|
29
|
+
**iOS Universal Links & Android App Links** - Serve `.well-known` files automatically \
|
|
30
|
+
**Link Expiration** - Set expiration dates for time-sensitive links \
|
|
31
|
+
**Redis Caching** - Optional Redis support for high-performance link lookups \
|
|
32
|
+
**PostgreSQL Storage** - Reliable data persistence with full SQL capabilities \
|
|
33
|
+
**TypeScript** - Fully typed API for better developer experience \
|
|
34
|
+
**No Auth Included** - Bring your own authentication; `userId` is optional for multi-tenant scoping
|
|
28
35
|
|
|
29
36
|
## Installation
|
|
30
37
|
|
|
@@ -81,17 +88,21 @@ docker run -d \
|
|
|
81
88
|
```
|
|
82
89
|
|
|
83
90
|
**Features:**
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
91
|
+
- Pre-built multi-architecture images (AMD64 + ARM64)
|
|
92
|
+
- Automatic updates with version tags
|
|
93
|
+
- Non-root user for security
|
|
94
|
+
- Built-in health checks
|
|
95
|
+
- Supply chain attestations (SBOM + Provenance)
|
|
89
96
|
|
|
90
97
|
See [DOCKER.md](DOCKER.md) for complete deployment guide.
|
|
91
98
|
|
|
92
99
|
## API Reference
|
|
93
100
|
|
|
94
|
-
###
|
|
101
|
+
### Links
|
|
102
|
+
|
|
103
|
+
#### Create a Link
|
|
104
|
+
|
|
105
|
+
`userId` is optional. When provided, the link is scoped to that user (multi-tenant mode). When omitted, the link has no owner (single-tenant mode).
|
|
95
106
|
|
|
96
107
|
```bash
|
|
97
108
|
POST /api/links
|
|
@@ -101,57 +112,54 @@ Content-Type: application/json
|
|
|
101
112
|
"userId": "user-uuid",
|
|
102
113
|
"originalUrl": "https://example.com",
|
|
103
114
|
"title": "My Link",
|
|
104
|
-
"
|
|
105
|
-
"
|
|
115
|
+
"description": "Summer campaign link",
|
|
116
|
+
"iosAppStoreUrl": "https://apps.apple.com/app/id123456",
|
|
117
|
+
"androidAppStoreUrl": "https://play.google.com/store/apps/details?id=com.example",
|
|
106
118
|
"webFallbackUrl": "https://example.com/product/123",
|
|
119
|
+
"appScheme": "myapp",
|
|
120
|
+
"iosUniversalLink": "https://example.com/app/product/123",
|
|
121
|
+
"androidAppLink": "https://example.com/app/product/123",
|
|
122
|
+
"deepLinkPath": "/product/123",
|
|
123
|
+
"deepLinkParameters": { "ref": "campaign-1" },
|
|
107
124
|
"utmParameters": {
|
|
108
125
|
"source": "twitter",
|
|
109
126
|
"medium": "social",
|
|
110
127
|
"campaign": "summer-sale"
|
|
111
128
|
},
|
|
129
|
+
"ogTitle": "Check out this deal",
|
|
130
|
+
"ogDescription": "50% off summer sale",
|
|
131
|
+
"ogImageUrl": "https://example.com/og-image.png",
|
|
132
|
+
"targetingRules": {
|
|
133
|
+
"countries": ["US", "CA"],
|
|
134
|
+
"devices": ["ios", "android"],
|
|
135
|
+
"languages": ["en"]
|
|
136
|
+
},
|
|
137
|
+
"attributionWindowHours": 168,
|
|
112
138
|
"customCode": "summer-sale",
|
|
113
|
-
"expiresAt": "
|
|
139
|
+
"expiresAt": "2026-12-31T23:59:59Z"
|
|
114
140
|
}
|
|
115
141
|
```
|
|
116
142
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
{
|
|
121
|
-
"id": "link-uuid",
|
|
122
|
-
"userId": "user-uuid",
|
|
123
|
-
"short_code": "summer-sale",
|
|
124
|
-
"original_url": "https://example.com",
|
|
125
|
-
"title": "My Link",
|
|
126
|
-
"ios_url": "myapp://product/123",
|
|
127
|
-
"android_url": "myapp://product/123",
|
|
128
|
-
"web_fallback_url": "https://example.com/product/123",
|
|
129
|
-
"utmParameters": {
|
|
130
|
-
"source": "twitter",
|
|
131
|
-
"medium": "social",
|
|
132
|
-
"campaign": "summer-sale"
|
|
133
|
-
},
|
|
134
|
-
"is_active": true,
|
|
135
|
-
"expires_at": "2024-12-31T23:59:59Z",
|
|
136
|
-
"created_at": "2024-01-01T00:00:00Z",
|
|
137
|
-
"updated_at": "2024-01-01T00:00:00Z",
|
|
138
|
-
"clickCount": 0
|
|
139
|
-
}
|
|
140
|
-
```
|
|
143
|
+
All fields except `originalUrl` are optional.
|
|
141
144
|
|
|
142
|
-
|
|
145
|
+
#### Get All Links
|
|
143
146
|
|
|
144
147
|
```bash
|
|
148
|
+
# Single-tenant (all links)
|
|
149
|
+
GET /api/links
|
|
150
|
+
|
|
151
|
+
# Multi-tenant (scoped to user)
|
|
145
152
|
GET /api/links?userId=user-uuid
|
|
146
153
|
```
|
|
147
154
|
|
|
148
|
-
|
|
155
|
+
#### Get a Specific Link
|
|
149
156
|
|
|
150
157
|
```bash
|
|
158
|
+
GET /api/links/:id
|
|
151
159
|
GET /api/links/:id?userId=user-uuid
|
|
152
160
|
```
|
|
153
161
|
|
|
154
|
-
|
|
162
|
+
#### Update a Link
|
|
155
163
|
|
|
156
164
|
```bash
|
|
157
165
|
PUT /api/links/:id?userId=user-uuid
|
|
@@ -163,62 +171,99 @@ Content-Type: application/json
|
|
|
163
171
|
}
|
|
164
172
|
```
|
|
165
173
|
|
|
166
|
-
|
|
174
|
+
#### Duplicate a Link
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
POST /api/links/:id/duplicate?userId=user-uuid
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Delete a Link
|
|
167
181
|
|
|
168
182
|
```bash
|
|
169
183
|
DELETE /api/links/:id?userId=user-uuid
|
|
170
184
|
```
|
|
171
185
|
|
|
172
|
-
###
|
|
186
|
+
### Analytics
|
|
187
|
+
|
|
188
|
+
#### Get Analytics Overview
|
|
173
189
|
|
|
174
190
|
```bash
|
|
191
|
+
# All links
|
|
192
|
+
GET /api/analytics/overview?days=30
|
|
193
|
+
|
|
194
|
+
# Scoped to user
|
|
175
195
|
GET /api/analytics/overview?userId=user-uuid&days=30
|
|
176
196
|
```
|
|
177
197
|
|
|
178
|
-
|
|
198
|
+
Returns: `totalClicks`, `uniqueClicks`, `clicksByDate`, `clicksByCountry`, `clicksByDevice`, `clicksByPlatform`, `topLinks`
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{ "device": "mobile", "clicks": 789 }
|
|
192
|
-
],
|
|
193
|
-
"clicksByPlatform": [
|
|
194
|
-
{ "platform": "iOS", "clicks": 456 }
|
|
195
|
-
],
|
|
196
|
-
"topLinks": [
|
|
197
|
-
{
|
|
198
|
-
"id": "link-uuid",
|
|
199
|
-
"shortCode": "summer-sale",
|
|
200
|
-
"title": "My Link",
|
|
201
|
-
"originalUrl": "https://example.com",
|
|
202
|
-
"totalClicks": 123,
|
|
203
|
-
"uniqueClicks": 67
|
|
204
|
-
}
|
|
205
|
-
]
|
|
206
|
-
}
|
|
200
|
+
#### Get Link-Specific Analytics
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
GET /api/analytics/links/:linkId?days=30
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Redirect
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
GET /:shortCode
|
|
210
|
+
GET /:templateSlug/:shortCode
|
|
207
211
|
```
|
|
208
212
|
|
|
209
|
-
|
|
213
|
+
Automatically redirects users to the appropriate URL based on device type (iOS/Android/web), evaluates targeting rules, and tracks the click asynchronously.
|
|
214
|
+
|
|
215
|
+
### QR Codes
|
|
210
216
|
|
|
211
217
|
```bash
|
|
212
|
-
GET /api/
|
|
218
|
+
GET /api/links/:id/qr?format=png&size=300
|
|
219
|
+
GET /api/links/:id/qr?format=svg
|
|
213
220
|
```
|
|
214
221
|
|
|
215
|
-
###
|
|
222
|
+
### Webhooks
|
|
216
223
|
|
|
217
224
|
```bash
|
|
218
|
-
GET
|
|
225
|
+
GET /api/webhooks?userId=user-uuid
|
|
226
|
+
POST /api/webhooks # Body: { name, url, events, userId? }
|
|
227
|
+
GET /api/webhooks/:id?userId=user-uuid
|
|
228
|
+
PUT /api/webhooks/:id?userId=user-uuid
|
|
229
|
+
DELETE /api/webhooks/:id?userId=user-uuid
|
|
230
|
+
POST /api/webhooks/:id/test?userId=user-uuid
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Events: `click_event`, `install_event`, `conversion_event`. Payloads are HMAC SHA-256 signed.
|
|
234
|
+
|
|
235
|
+
### Mobile SDK Endpoints
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
POST /api/sdk/v1/install # Report app install, get deferred deep link
|
|
239
|
+
GET /api/sdk/v1/attribution/:fingerprint # Debug attribution lookups
|
|
240
|
+
POST /api/sdk/v1/event # Track in-app conversion events
|
|
241
|
+
GET /api/sdk/v1/resolve/:shortCode # Resolve link to deep link data (no redirect)
|
|
242
|
+
GET /api/sdk/v1/health # Health check
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Debug & Testing
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
POST /api/debug/simulate # Simulate a link click with custom parameters
|
|
249
|
+
WS /api/debug/live?userId=user-uuid # WebSocket live click event stream
|
|
250
|
+
GET /api/debug/user-agents # Common UA strings for testing
|
|
251
|
+
GET /api/debug/countries # Common countries list
|
|
252
|
+
GET /api/debug/languages # Common languages list
|
|
219
253
|
```
|
|
220
254
|
|
|
221
|
-
|
|
255
|
+
### Well-Known Routes
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
GET /.well-known/apple-app-site-association # iOS Universal Links
|
|
259
|
+
GET /.well-known/assetlinks.json # Android App Links
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### OG Preview
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
GET /:shortCode/preview # OG meta tag page for social scrapers
|
|
266
|
+
```
|
|
222
267
|
|
|
223
268
|
## Configuration
|
|
224
269
|
|
|
@@ -251,39 +296,50 @@ REDIS_URL=redis://localhost:6379
|
|
|
251
296
|
PORT=3000
|
|
252
297
|
NODE_ENV=production
|
|
253
298
|
CORS_ORIGIN=*
|
|
299
|
+
|
|
300
|
+
# Mobile SDK (optional — for iOS Universal Links and Android App Links)
|
|
301
|
+
IOS_TEAM_ID=ABC123XYZ
|
|
302
|
+
IOS_BUNDLE_ID=com.yourcompany.yourapp
|
|
303
|
+
ANDROID_PACKAGE_NAME=com.yourcompany.yourapp
|
|
304
|
+
ANDROID_SHA256_FINGERPRINTS=AA:BB:CC:DD:...
|
|
305
|
+
|
|
306
|
+
# Custom domain for QR code URLs (optional)
|
|
307
|
+
SHORTLINK_DOMAIN=yourdomain.com
|
|
254
308
|
```
|
|
255
309
|
|
|
256
310
|
## Database Schema
|
|
257
311
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
| Column | Type | Description |
|
|
261
|
-
|---------------|--------------|-----------------------|
|
|
262
|
-
| id | UUID | Primary key |
|
|
263
|
-
| email | VARCHAR(255) | Unique email |
|
|
264
|
-
| name | VARCHAR(255) | User name |
|
|
265
|
-
| password_hash | VARCHAR(255) | Hashed password |
|
|
266
|
-
| created_at | TIMESTAMP | Creation timestamp |
|
|
267
|
-
| updated_at | TIMESTAMP | Last update timestamp |
|
|
312
|
+
Core does not create a `users` table. Authentication and user management are the consumer's responsibility. The `user_id` column on `links` and `webhooks` is optional (nullable, no foreign key) — use it for multi-tenant scoping when your auth layer provides a user identity.
|
|
268
313
|
|
|
269
314
|
### Links Table
|
|
270
315
|
|
|
271
|
-
| Column
|
|
272
|
-
|
|
273
|
-
| id
|
|
274
|
-
| user_id
|
|
275
|
-
| short_code
|
|
276
|
-
| original_url
|
|
277
|
-
| title
|
|
278
|
-
|
|
|
279
|
-
|
|
|
280
|
-
|
|
|
281
|
-
|
|
|
282
|
-
|
|
|
283
|
-
|
|
|
284
|
-
|
|
|
285
|
-
|
|
|
286
|
-
|
|
|
316
|
+
| Column | Type | Description |
|
|
317
|
+
|-------------------------|--------------|------------------------------------------|
|
|
318
|
+
| id | UUID | Primary key |
|
|
319
|
+
| user_id | UUID | Optional owner/tenant identifier |
|
|
320
|
+
| short_code | VARCHAR(20) | Unique short code |
|
|
321
|
+
| original_url | TEXT | Original URL |
|
|
322
|
+
| title | VARCHAR(255) | Link title |
|
|
323
|
+
| description | TEXT | Link description |
|
|
324
|
+
| ios_app_store_url | TEXT | iOS App Store URL |
|
|
325
|
+
| android_app_store_url | TEXT | Android Play Store URL |
|
|
326
|
+
| web_fallback_url | TEXT | Web fallback URL |
|
|
327
|
+
| app_scheme | VARCHAR(255) | URI scheme (e.g., "myapp") |
|
|
328
|
+
| ios_universal_link | TEXT | iOS Universal Link URL |
|
|
329
|
+
| android_app_link | TEXT | Android App Link URL |
|
|
330
|
+
| deep_link_path | TEXT | In-app destination path |
|
|
331
|
+
| deep_link_parameters | JSONB | Custom app parameters |
|
|
332
|
+
| utm_parameters | JSONB | UTM tracking parameters |
|
|
333
|
+
| targeting_rules | JSONB | Country/device/language targeting |
|
|
334
|
+
| og_title | VARCHAR(255) | Open Graph title |
|
|
335
|
+
| og_description | TEXT | Open Graph description |
|
|
336
|
+
| og_image_url | TEXT | Open Graph image URL |
|
|
337
|
+
| og_type | VARCHAR(50) | Open Graph type (default: "website") |
|
|
338
|
+
| attribution_window_hours| INTEGER | Install attribution window (default: 168)|
|
|
339
|
+
| is_active | BOOLEAN | Active status |
|
|
340
|
+
| expires_at | TIMESTAMP | Expiration date |
|
|
341
|
+
| created_at | TIMESTAMP | Creation timestamp |
|
|
342
|
+
| updated_at | TIMESTAMP | Last update timestamp |
|
|
287
343
|
|
|
288
344
|
### Click Events Table
|
|
289
345
|
|
|
@@ -294,7 +350,7 @@ CORS_ORIGIN=*
|
|
|
294
350
|
| clicked_at | TIMESTAMP | Click timestamp |
|
|
295
351
|
| ip_address | INET | User IP address |
|
|
296
352
|
| user_agent | TEXT | User agent string |
|
|
297
|
-
| device_type | VARCHAR(20) | Device type (
|
|
353
|
+
| device_type | VARCHAR(20) | Device type (ios/android/web)|
|
|
298
354
|
| platform | VARCHAR(20) | Platform (iOS/Android/Web) |
|
|
299
355
|
| country_code | CHAR(2) | Country code |
|
|
300
356
|
| country_name | VARCHAR(100) | Country name |
|
|
@@ -308,6 +364,68 @@ CORS_ORIGIN=*
|
|
|
308
364
|
| utm_campaign | VARCHAR(255) | UTM campaign |
|
|
309
365
|
| referrer | TEXT | Referrer URL |
|
|
310
366
|
|
|
367
|
+
### Device Fingerprints Table
|
|
368
|
+
|
|
369
|
+
| Column | Type | Description |
|
|
370
|
+
|------------------|-------------|-------------------------------------|
|
|
371
|
+
| id | UUID | Primary key |
|
|
372
|
+
| click_id | UUID | Foreign key to click_events |
|
|
373
|
+
| fingerprint_hash | VARCHAR(64) | SHA-256 hash of fingerprint signals |
|
|
374
|
+
| ip_address | INET | IP address |
|
|
375
|
+
| user_agent | TEXT | User agent string |
|
|
376
|
+
| timezone | VARCHAR(100)| Timezone |
|
|
377
|
+
| language | VARCHAR(10) | Browser language |
|
|
378
|
+
| screen_width | INTEGER | Screen width |
|
|
379
|
+
| screen_height | INTEGER | Screen height |
|
|
380
|
+
| platform | VARCHAR(50) | Platform |
|
|
381
|
+
| platform_version | VARCHAR(50) | Platform version |
|
|
382
|
+
| created_at | TIMESTAMP | Creation timestamp |
|
|
383
|
+
|
|
384
|
+
### Install Events Table
|
|
385
|
+
|
|
386
|
+
| Column | Type | Description |
|
|
387
|
+
|-------------------------|-------------|------------------------------------|
|
|
388
|
+
| id | UUID | Primary key |
|
|
389
|
+
| link_id | UUID | Attributed link (nullable) |
|
|
390
|
+
| click_id | UUID | Attributed click (nullable) |
|
|
391
|
+
| fingerprint_hash | VARCHAR(64) | Device fingerprint hash |
|
|
392
|
+
| confidence_score | DECIMAL | Match confidence (0-100) |
|
|
393
|
+
| installed_at | TIMESTAMP | Install timestamp |
|
|
394
|
+
| first_open_at | TIMESTAMP | First app open |
|
|
395
|
+
| deep_link_retrieved | BOOLEAN | Whether deferred link was fetched |
|
|
396
|
+
| deep_link_data | JSONB | Deferred deep link data |
|
|
397
|
+
| attribution_window_hours| INTEGER | Attribution window used (default: 168) |
|
|
398
|
+
| device_id | VARCHAR(255)| Optional device identifier |
|
|
399
|
+
| created_at | TIMESTAMP | Creation timestamp |
|
|
400
|
+
|
|
401
|
+
### In-App Events Table
|
|
402
|
+
|
|
403
|
+
| Column | Type | Description |
|
|
404
|
+
|-----------------|--------------|------------------------------|
|
|
405
|
+
| id | UUID | Primary key |
|
|
406
|
+
| install_id | UUID | Foreign key to install_events|
|
|
407
|
+
| event_name | VARCHAR(255) | Event name |
|
|
408
|
+
| event_data | JSONB | Custom event properties |
|
|
409
|
+
| event_timestamp | TIMESTAMP | When the event occurred |
|
|
410
|
+
| created_at | TIMESTAMP | Creation timestamp |
|
|
411
|
+
|
|
412
|
+
### Webhooks Table
|
|
413
|
+
|
|
414
|
+
| Column | Type | Description |
|
|
415
|
+
|------------|--------------|----------------------------------|
|
|
416
|
+
| id | UUID | Primary key |
|
|
417
|
+
| user_id | UUID | Optional owner/tenant identifier |
|
|
418
|
+
| name | VARCHAR(255) | Webhook name |
|
|
419
|
+
| url | TEXT | Delivery URL |
|
|
420
|
+
| secret | VARCHAR(255) | HMAC signing secret |
|
|
421
|
+
| events | TEXT[] | Subscribed event types |
|
|
422
|
+
| is_active | BOOLEAN | Active status |
|
|
423
|
+
| retry_count| INTEGER | Max retries (default: 3) |
|
|
424
|
+
| timeout_ms | INTEGER | Request timeout (default: 10000) |
|
|
425
|
+
| headers | JSONB | Custom HTTP headers |
|
|
426
|
+
| created_at | TIMESTAMP | Creation timestamp |
|
|
427
|
+
| updated_at | TIMESTAMP | Last update timestamp |
|
|
428
|
+
|
|
311
429
|
## Utilities
|
|
312
430
|
|
|
313
431
|
### Generate Short Code
|
|
@@ -389,7 +507,7 @@ await fastify.listen({ port: 3000 });
|
|
|
389
507
|
|
|
390
508
|
LinkForty can be deployed in multiple ways depending on your needs:
|
|
391
509
|
|
|
392
|
-
###
|
|
510
|
+
### Production Deployment (Recommended)
|
|
393
511
|
|
|
394
512
|
Deploy to managed platforms with minimal DevOps overhead:
|
|
395
513
|
|
|
@@ -399,11 +517,11 @@ Deploy to managed platforms with minimal DevOps overhead:
|
|
|
399
517
|
- Auto-scaling and SSL included
|
|
400
518
|
- Starting at ~$10-15/month
|
|
401
519
|
|
|
402
|
-
[View Fly.io deployment guide
|
|
520
|
+
[View Fly.io deployment guide](infra/fly.io/DEPLOYMENT.md)
|
|
403
521
|
|
|
404
522
|
See [`infra/`](infra/) directory for all deployment options and platform-specific guides.
|
|
405
523
|
|
|
406
|
-
###
|
|
524
|
+
### Docker Deployment (Recommended for Self-Hosting)
|
|
407
525
|
|
|
408
526
|
**Production-ready Docker images available on Docker Hub:**
|
|
409
527
|
|
|
@@ -424,7 +542,7 @@ docker compose up -d
|
|
|
424
542
|
```yaml
|
|
425
543
|
services:
|
|
426
544
|
linkforty:
|
|
427
|
-
image: linkforty/core:v1.
|
|
545
|
+
image: linkforty/core:v1.5.0 # Pin to specific version
|
|
428
546
|
```
|
|
429
547
|
|
|
430
548
|
See [DOCKER.md](DOCKER.md) for complete deployment guide including:
|
|
@@ -456,8 +574,8 @@ See [`infra/CONTRIBUTING.md`](infra/CONTRIBUTING.md) to add support for addition
|
|
|
456
574
|
|
|
457
575
|
- **Redis caching**: 5-minute TTL on link lookups reduces database queries by 90%
|
|
458
576
|
- **Database indexes**: Optimized queries for fast link lookups and analytics
|
|
459
|
-
- **Async click tracking**: Non-blocking click event logging
|
|
460
|
-
- **Connection pooling**: Efficient database connection management
|
|
577
|
+
- **Async click tracking**: Non-blocking click event logging via `setImmediate()`
|
|
578
|
+
- **Connection pooling**: Efficient database connection management (min 2, max 10)
|
|
461
579
|
|
|
462
580
|
## Security
|
|
463
581
|
|
|
@@ -465,6 +583,8 @@ See [`infra/CONTRIBUTING.md`](infra/CONTRIBUTING.md) to add support for addition
|
|
|
465
583
|
- **Input validation**: Zod schema validation on all inputs
|
|
466
584
|
- **CORS configuration**: Configurable CORS for API access control
|
|
467
585
|
- **Link expiration**: Automatic handling of expired links
|
|
586
|
+
- **Webhook signing**: HMAC SHA-256 signed payloads
|
|
587
|
+
- **No auth included**: Core does not include authentication. The optional `userId` parameter provides data scoping but does not verify identity. Add your own auth middleware as needed.
|
|
468
588
|
|
|
469
589
|
## Mobile SDK Integration
|
|
470
590
|
|
|
@@ -556,12 +676,12 @@ LinkForty Core supports iOS Universal Links and Android App Links for seamless d
|
|
|
556
676
|
|
|
557
677
|
### Available Mobile SDKs
|
|
558
678
|
|
|
559
|
-
- **React Native**: `npm install @linkforty/react-native
|
|
560
|
-
- **iOS**: Coming soon
|
|
561
|
-
- **Android**: Coming soon
|
|
679
|
+
- **React Native**: `npm install @linkforty/mobile-sdk-react-native`
|
|
680
|
+
- **iOS Native**: Coming soon
|
|
681
|
+
- **Android Native**: Coming soon
|
|
562
682
|
- **Flutter**: Coming soon
|
|
563
683
|
|
|
564
|
-
See [SDK Integration Guide](https://docs.linkforty.com/
|
|
684
|
+
See [SDK Integration Guide](https://docs.linkforty.com/sdks/react-native/overview) for detailed documentation.
|
|
565
685
|
|
|
566
686
|
### Testing Domain Verification
|
|
567
687
|
|
|
@@ -583,12 +703,13 @@ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for det
|
|
|
583
703
|
|
|
584
704
|
## License
|
|
585
705
|
|
|
586
|
-
|
|
706
|
+
AGPL-3.0 - see [LICENSE](LICENSE) file for details.
|
|
587
707
|
|
|
588
708
|
## Related Projects
|
|
589
709
|
|
|
590
710
|
- **@linkforty/ui** - React UI components for link management
|
|
591
|
-
-
|
|
711
|
+
- **@linkforty/mobile-sdk-react-native** - React Native SDK for deferred deep linking
|
|
712
|
+
- **[LinkForty Cloud](https://linkforty.com)** - Hosted SaaS version with authentication, teams, billing, and more
|
|
592
713
|
|
|
593
714
|
## Support
|
|
594
715
|
|
|
@@ -600,8 +721,8 @@ MIT License - see [LICENSE](LICENSE) file for details.
|
|
|
600
721
|
- [Fastify](https://www.fastify.io/) - Fast web framework
|
|
601
722
|
- [PostgreSQL](https://www.postgresql.org/) - Powerful database
|
|
602
723
|
- [Redis](https://redis.io/) - In-memory cache
|
|
724
|
+
- [Zod](https://zod.dev/) - TypeScript-first schema validation
|
|
603
725
|
- [nanoid](https://github.com/ai/nanoid) - Unique ID generation
|
|
604
726
|
- [geoip-lite](https://github.com/geoip-lite/node-geoip) - IP geolocation
|
|
605
727
|
- [ua-parser-js](https://github.com/faisalman/ua-parser-js) - User agent parsing
|
|
606
|
-
|
|
607
|
-
|
|
728
|
+
- [qrcode](https://github.com/soldair/node-qrcode) - QR code generation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/lib/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,eAAO,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;AA6BvB,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,eAAoB,
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/lib/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,eAAO,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;AA6BvB,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,eAAoB,iBA2VrE"}
|
package/dist/lib/database.js
CHANGED
|
@@ -38,22 +38,11 @@ export async function initializeDatabase(options = {}) {
|
|
|
38
38
|
});
|
|
39
39
|
const client = await connectWithRetry();
|
|
40
40
|
try {
|
|
41
|
-
// Users table
|
|
42
|
-
await client.query(`
|
|
43
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
44
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
45
|
-
email VARCHAR(255) UNIQUE NOT NULL,
|
|
46
|
-
name VARCHAR(255) NOT NULL,
|
|
47
|
-
password_hash VARCHAR(255) NOT NULL,
|
|
48
|
-
created_at TIMESTAMP DEFAULT NOW(),
|
|
49
|
-
updated_at TIMESTAMP DEFAULT NOW()
|
|
50
|
-
)
|
|
51
|
-
`);
|
|
52
41
|
// Links table
|
|
53
42
|
await client.query(`
|
|
54
43
|
CREATE TABLE IF NOT EXISTS links (
|
|
55
44
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
56
|
-
user_id UUID
|
|
45
|
+
user_id UUID,
|
|
57
46
|
short_code VARCHAR(20) UNIQUE NOT NULL,
|
|
58
47
|
original_url TEXT NOT NULL,
|
|
59
48
|
title VARCHAR(255),
|
|
@@ -149,7 +138,7 @@ export async function initializeDatabase(options = {}) {
|
|
|
149
138
|
await client.query(`
|
|
150
139
|
CREATE TABLE IF NOT EXISTS webhooks (
|
|
151
140
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
152
|
-
user_id UUID
|
|
141
|
+
user_id UUID,
|
|
153
142
|
name VARCHAR(255) NOT NULL,
|
|
154
143
|
url TEXT NOT NULL,
|
|
155
144
|
secret VARCHAR(255) NOT NULL,
|
|
@@ -328,7 +317,6 @@ export async function initializeDatabase(options = {}) {
|
|
|
328
317
|
await client.query('CREATE INDEX IF NOT EXISTS idx_clicks_link_id ON click_events(link_id)');
|
|
329
318
|
await client.query('CREATE INDEX IF NOT EXISTS idx_clicks_timestamp ON click_events(clicked_at DESC)');
|
|
330
319
|
await client.query('CREATE INDEX IF NOT EXISTS idx_clicks_link_date ON click_events(link_id, clicked_at DESC)');
|
|
331
|
-
await client.query('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)');
|
|
332
320
|
// Indexes for deferred deep linking
|
|
333
321
|
await client.query('CREATE INDEX IF NOT EXISTS idx_fingerprints_hash ON device_fingerprints(fingerprint_hash)');
|
|
334
322
|
await client.query('CREATE INDEX IF NOT EXISTS idx_fingerprints_click_id ON device_fingerprints(click_id)');
|
package/dist/lib/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/lib/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAUpB,MAAM,CAAC,IAAI,EAAW,CAAC;AAEvB,+CAA+C;AAC/C,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,qDAAqD;AACrD,KAAK,UAAU,gBAAgB,CAAC,aAAqB,EAAE,EAAE,YAAoB,IAAI;IAC/E,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;YAC5D,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBAC1D,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB;gBAC1E,OAAO,CAAC,GAAG,CAAC,+BAA+B,OAAO,wBAAwB,KAAK,OAAO,CAAC,CAAC;gBACxF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAC;gBACzE,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;AAC1C,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAA2B,EAAE;IACpE,kBAAkB;IAClB,EAAE,GAAG,IAAI,IAAI,CAAC;QACZ,gBAAgB,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,yDAAyD;QACtH,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK;QAClF,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC;QAC3B,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE;KAC7B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAExC,IAAI,CAAC;QACH,cAAc;QACd,MAAM,MAAM,CAAC,KAAK,CAAC
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/lib/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../../src/lib/event-emitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,uBAAqB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"event-emitter.d.ts","sourceRoot":"","sources":["../../src/lib/event-emitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,uBAAqB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,UAAU,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAG1B,aAAa,CAAC,EAAE;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IAGF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,cAAc,QAEvD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,GAC5C,MAAM,IAAI,CAOZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CACjB;AAcD;;GAEG;AACH,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAcrE;AA0CD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,eAAe,EAC7B,YAAY,EAAE,eAAe,GAC5B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CA+D7C;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,kBAAkB,EAAE,eAAe,EACnC,sBAAsB,GAAE,MAAyC,GAChE,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAgFlC;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,eAAe,EAAE,eAAe,EAChC,QAAQ,CAAC,EAAE,MAAM,EACjB,sBAAsB,GAAE,MAAyC,GAChE,OAAO,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,GAAG,CAAC;CACnB,CAAC,
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/lib/fingerprint.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;CACjB;AAcD;;GAEG;AACH,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD;;GAEG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAcrE;AA0CD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,eAAe,EAC7B,YAAY,EAAE,eAAe,GAC5B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CA+D7C;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,kBAAkB,EAAE,eAAe,EACnC,sBAAsB,GAAE,MAAyC,GAChE,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAgFlC;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,eAAe,GAC/B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,eAAe,EAAE,eAAe,EAChC,QAAQ,CAAC,EAAE,MAAM,EACjB,sBAAsB,GAAE,MAAyC,GAChE,OAAO,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,GAAG,CAAC;CACnB,CAAC,CAgJD"}
|