@oxyhq/services 5.12.10 → 5.13.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.
- package/lib/commonjs/core/OxyServices.js +83 -5
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +60 -8
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/core/OxyServices.js +83 -5
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +60 -8
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/typescript/core/OxyServices.d.ts +35 -1
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts +15 -0
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/OxyServices.ts +91 -7
- package/src/ui/screens/FileManagementScreen.tsx +90 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileManagementScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/FileManagementScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAgBjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAO5D,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;AAErE,MAAM,WAAW,yBAA0B,SAAQ,eAAe;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAExC,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;IAE5C,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,uBAAuB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FileManagementScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/FileManagementScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAgBjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAK3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAO5D,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;AAErE,MAAM,WAAW,yBAA0B,SAAQ,eAAe;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAExC,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;IAE5C,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtD;;;OAGG;IACH,WAAW,CAAC,EAAE;QACV,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACL;AAOD,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA84D7D,CAAC;AAszBF,eAAe,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/services",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.13.0",
|
|
4
4
|
"description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
package/src/core/OxyServices.ts
CHANGED
|
@@ -1349,14 +1349,12 @@ export class OxyServices {
|
|
|
1349
1349
|
/**
|
|
1350
1350
|
* Link asset to an entity
|
|
1351
1351
|
*/
|
|
1352
|
-
async assetLink(fileId: string, app: string, entityType: string, entityId: string, visibility?: 'private' | 'public' | 'unlisted'): Promise<any> {
|
|
1352
|
+
async assetLink(fileId: string, app: string, entityType: string, entityId: string, visibility?: 'private' | 'public' | 'unlisted', webhookUrl?: string): Promise<any> {
|
|
1353
1353
|
try {
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
visibility
|
|
1359
|
-
});
|
|
1354
|
+
const body: any = { app, entityType, entityId };
|
|
1355
|
+
if (visibility) body.visibility = visibility;
|
|
1356
|
+
if (webhookUrl) body.webhookUrl = webhookUrl;
|
|
1357
|
+
const res = await this.client.post(`/api/assets/${fileId}/links`, body);
|
|
1360
1358
|
return res.data;
|
|
1361
1359
|
} catch (error) {
|
|
1362
1360
|
throw this.handleError(error);
|
|
@@ -1508,6 +1506,92 @@ export class OxyServices {
|
|
|
1508
1506
|
}
|
|
1509
1507
|
}
|
|
1510
1508
|
|
|
1509
|
+
// ============================================================================
|
|
1510
|
+
// DEVELOPER API METHODS
|
|
1511
|
+
// ============================================================================
|
|
1512
|
+
|
|
1513
|
+
/**
|
|
1514
|
+
* Get developer apps for the current user
|
|
1515
|
+
*/
|
|
1516
|
+
async getDeveloperApps(): Promise<any[]> {
|
|
1517
|
+
try {
|
|
1518
|
+
const res = await this.client.get('/api/developer/apps');
|
|
1519
|
+
return res.data;
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
throw this.handleError(error);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* Create a new developer app
|
|
1527
|
+
*/
|
|
1528
|
+
async createDeveloperApp(data: {
|
|
1529
|
+
name: string;
|
|
1530
|
+
description?: string;
|
|
1531
|
+
webhookUrl?: string;
|
|
1532
|
+
scopes?: string[];
|
|
1533
|
+
}): Promise<any> {
|
|
1534
|
+
try {
|
|
1535
|
+
const res = await this.client.post('/api/developer/apps', data);
|
|
1536
|
+
return res.data;
|
|
1537
|
+
} catch (error) {
|
|
1538
|
+
throw this.handleError(error);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
/**
|
|
1543
|
+
* Get a specific developer app
|
|
1544
|
+
*/
|
|
1545
|
+
async getDeveloperApp(appId: string): Promise<any> {
|
|
1546
|
+
try {
|
|
1547
|
+
const res = await this.client.get(`/api/developer/apps/${appId}`);
|
|
1548
|
+
return res.data;
|
|
1549
|
+
} catch (error) {
|
|
1550
|
+
throw this.handleError(error);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
/**
|
|
1555
|
+
* Update a developer app
|
|
1556
|
+
*/
|
|
1557
|
+
async updateDeveloperApp(appId: string, data: {
|
|
1558
|
+
name?: string;
|
|
1559
|
+
description?: string;
|
|
1560
|
+
webhookUrl?: string;
|
|
1561
|
+
scopes?: string[];
|
|
1562
|
+
}): Promise<any> {
|
|
1563
|
+
try {
|
|
1564
|
+
const res = await this.client.patch(`/api/developer/apps/${appId}`, data);
|
|
1565
|
+
return res.data;
|
|
1566
|
+
} catch (error) {
|
|
1567
|
+
throw this.handleError(error);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* Regenerate API secret for a developer app
|
|
1573
|
+
*/
|
|
1574
|
+
async regenerateDeveloperAppSecret(appId: string): Promise<any> {
|
|
1575
|
+
try {
|
|
1576
|
+
const res = await this.client.post(`/api/developer/apps/${appId}/regenerate-secret`);
|
|
1577
|
+
return res.data;
|
|
1578
|
+
} catch (error) {
|
|
1579
|
+
throw this.handleError(error);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
/**
|
|
1584
|
+
* Delete a developer app
|
|
1585
|
+
*/
|
|
1586
|
+
async deleteDeveloperApp(appId: string): Promise<any> {
|
|
1587
|
+
try {
|
|
1588
|
+
const res = await this.client.delete(`/api/developer/apps/${appId}`);
|
|
1589
|
+
return res.data;
|
|
1590
|
+
} catch (error) {
|
|
1591
|
+
throw this.handleError(error);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1511
1595
|
// ============================================================================
|
|
1512
1596
|
// LOCATION METHODS
|
|
1513
1597
|
// ============================================================================
|
|
@@ -50,11 +50,26 @@ export interface FileManagementScreenProps extends BaseScreenProps {
|
|
|
50
50
|
*/
|
|
51
51
|
afterSelect?: 'close' | 'back' | 'none';
|
|
52
52
|
allowUploadInSelectMode?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Default visibility for uploaded files in this screen
|
|
55
|
+
* Useful for third-party apps that want files to be public (e.g., GIF selector)
|
|
56
|
+
*/
|
|
57
|
+
defaultVisibility?: 'private' | 'public' | 'unlisted';
|
|
58
|
+
/**
|
|
59
|
+
* Link context for tracking file usage by third-party apps
|
|
60
|
+
* When provided, selected files will be linked to this entity
|
|
61
|
+
*/
|
|
62
|
+
linkContext?: {
|
|
63
|
+
app: string; // App identifier (e.g., 'chat-app', 'post-composer')
|
|
64
|
+
entityType: string; // Type of entity (e.g., 'message', 'post', 'profile')
|
|
65
|
+
entityId: string; // Unique ID of the entity using this file
|
|
66
|
+
webhookUrl?: string; // Optional webhook URL to receive file events
|
|
67
|
+
};
|
|
53
68
|
}
|
|
54
69
|
|
|
55
70
|
// Add this helper function near the top (after imports):
|
|
56
|
-
async function uploadFileRaw(file: File | Blob, userId: string, oxyServices: any) {
|
|
57
|
-
return await oxyServices.uploadRawFile(file);
|
|
71
|
+
async function uploadFileRaw(file: File | Blob, userId: string, oxyServices: any, visibility?: 'private' | 'public' | 'unlisted') {
|
|
72
|
+
return await oxyServices.uploadRawFile(file, visibility);
|
|
58
73
|
}
|
|
59
74
|
|
|
60
75
|
const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
@@ -73,6 +88,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
73
88
|
disabledMimeTypes = [],
|
|
74
89
|
afterSelect = 'close',
|
|
75
90
|
allowUploadInSelectMode = true,
|
|
91
|
+
defaultVisibility = 'private',
|
|
92
|
+
linkContext,
|
|
76
93
|
}) => {
|
|
77
94
|
const { user, oxyServices } = useOxy();
|
|
78
95
|
|
|
@@ -133,7 +150,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
133
150
|
}
|
|
134
151
|
}, [initialSelectedIds]);
|
|
135
152
|
|
|
136
|
-
const toggleSelect = useCallback((file: FileMetadata) => {
|
|
153
|
+
const toggleSelect = useCallback(async (file: FileMetadata) => {
|
|
137
154
|
if (!selectMode) return;
|
|
138
155
|
if (disabledMimeTypes.length) {
|
|
139
156
|
const blocked = disabledMimeTypes.some(mt => file.contentType === mt || file.contentType.startsWith(mt.endsWith('/') ? mt : mt + '/'));
|
|
@@ -142,6 +159,37 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
142
159
|
return;
|
|
143
160
|
}
|
|
144
161
|
}
|
|
162
|
+
|
|
163
|
+
// Update file visibility if it differs from defaultVisibility
|
|
164
|
+
const fileVisibility = (file.metadata as any)?.visibility || 'private';
|
|
165
|
+
if (fileVisibility !== defaultVisibility) {
|
|
166
|
+
try {
|
|
167
|
+
await oxyServices.assetUpdateVisibility(file.id, defaultVisibility);
|
|
168
|
+
console.log(`Updated file ${file.id} visibility from ${fileVisibility} to ${defaultVisibility}`);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('Failed to update file visibility:', error);
|
|
171
|
+
// Continue anyway - selection shouldn't fail if visibility update fails
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Link file to entity if linkContext is provided
|
|
176
|
+
if (linkContext) {
|
|
177
|
+
try {
|
|
178
|
+
await oxyServices.assetLink(
|
|
179
|
+
file.id,
|
|
180
|
+
linkContext.app,
|
|
181
|
+
linkContext.entityType,
|
|
182
|
+
linkContext.entityId,
|
|
183
|
+
defaultVisibility,
|
|
184
|
+
(linkContext as any).webhookUrl
|
|
185
|
+
);
|
|
186
|
+
console.log(`Linked file ${file.id} to ${linkContext.app}/${linkContext.entityType}/${linkContext.entityId}`);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error('Failed to link file:', error);
|
|
189
|
+
// Continue anyway - selection shouldn't fail if linking fails
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
145
193
|
if (!multiSelect) {
|
|
146
194
|
onSelect?.(file);
|
|
147
195
|
if (afterSelect === 'back') {
|
|
@@ -165,16 +213,51 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
165
213
|
}
|
|
166
214
|
return next;
|
|
167
215
|
});
|
|
168
|
-
}, [selectMode, multiSelect, onSelect, onClose, goBack, disabledMimeTypes, maxSelection, afterSelect]);
|
|
216
|
+
}, [selectMode, multiSelect, onSelect, onClose, goBack, disabledMimeTypes, maxSelection, afterSelect, defaultVisibility, oxyServices, linkContext]);
|
|
169
217
|
|
|
170
|
-
const confirmMultiSelection = useCallback(() => {
|
|
218
|
+
const confirmMultiSelection = useCallback(async () => {
|
|
171
219
|
if (!selectMode || !multiSelect) return;
|
|
172
220
|
const map: Record<string, FileMetadata> = {};
|
|
173
221
|
files.forEach(f => { map[f.id] = f; });
|
|
174
222
|
const chosen = Array.from(selectedIds).map(id => map[id]).filter(Boolean);
|
|
223
|
+
|
|
224
|
+
// Update visibility and link files if needed
|
|
225
|
+
const updatePromises = chosen.map(async (file) => {
|
|
226
|
+
// Update visibility if needed
|
|
227
|
+
const fileVisibility = (file.metadata as any)?.visibility || 'private';
|
|
228
|
+
if (fileVisibility !== defaultVisibility) {
|
|
229
|
+
try {
|
|
230
|
+
await oxyServices.assetUpdateVisibility(file.id, defaultVisibility);
|
|
231
|
+
console.log(`Updated file ${file.id} visibility from ${fileVisibility} to ${defaultVisibility}`);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error(`Failed to update visibility for ${file.id}:`, error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Link file to entity if linkContext provided
|
|
238
|
+
if (linkContext) {
|
|
239
|
+
try {
|
|
240
|
+
await oxyServices.assetLink(
|
|
241
|
+
file.id,
|
|
242
|
+
linkContext.app,
|
|
243
|
+
linkContext.entityType,
|
|
244
|
+
linkContext.entityId,
|
|
245
|
+
defaultVisibility,
|
|
246
|
+
(linkContext as any).webhookUrl
|
|
247
|
+
);
|
|
248
|
+
console.log(`Linked file ${file.id} to ${linkContext.app}/${linkContext.entityType}/${linkContext.entityId}`);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error(`Failed to link file ${file.id}:`, error);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Wait for all updates (but don't block on failures)
|
|
256
|
+
await Promise.allSettled(updatePromises);
|
|
257
|
+
|
|
175
258
|
onConfirmSelection?.(chosen);
|
|
176
259
|
onClose?.();
|
|
177
|
-
}, [selectMode, multiSelect, selectedIds, files, onConfirmSelection, onClose]);
|
|
260
|
+
}, [selectMode, multiSelect, selectedIds, files, onConfirmSelection, onClose, defaultVisibility, oxyServices, linkContext]);
|
|
178
261
|
|
|
179
262
|
const endUpload = useCallback(() => {
|
|
180
263
|
const started = uploadStartRef.current;
|
|
@@ -434,7 +517,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
434
517
|
variants: [],
|
|
435
518
|
};
|
|
436
519
|
useFileStore.getState().addFile(optimisticFile, { prepend: true });
|
|
437
|
-
const result = await uploadFileRaw(raw, targetUserId, oxyServices);
|
|
520
|
+
const result = await uploadFileRaw(raw, targetUserId, oxyServices, defaultVisibility);
|
|
438
521
|
// Attempt to refresh file list incrementally – fetch single file metadata if API allows
|
|
439
522
|
if (result?.file || result?.files?.[0]) {
|
|
440
523
|
const f = result.file || result.files[0];
|