@suphark/files-client 0.0.0-stage → 0.3.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.
@@ -0,0 +1,746 @@
1
+ import { UploadApi, UploadSource, PerformUploadOptions } from '../index.js';
2
+ export { P as PiFilesError } from '../upload-D79TA4qU.js';
3
+ import * as _pi_files_contracts from '@pi/files-contracts';
4
+ import { CreateUploadInput, ReplaceFileInput } from '@pi/files-contracts';
5
+ import { PiFilesClient, PiFilesOptions } from '../index.js';
6
+ export { createPiFiles } from '../index.js';
7
+
8
+ /**
9
+ * ตรวจลายเซ็น webhook ของ Pi Files (header `x-pi-files-signature: t=<unix>,v1=<hex>`)
10
+ * secret ของแอปขอจากผู้ดูแลแพลตฟอร์ม (GET /api/v1/admin/apps/:id/webhook-secret)
11
+ *
12
+ * ```ts
13
+ * export async function POST(req: Request) {
14
+ * const body = await req.text();
15
+ * if (!verifyWebhookSignature(body, req.headers.get("x-pi-files-signature"), process.env.PI_FILES_WEBHOOK_SECRET!)) {
16
+ * return new Response("bad signature", { status: 401 });
17
+ * }
18
+ * const event = JSON.parse(body) as PiFilesWebhookEvent;
19
+ * …
20
+ * }
21
+ * ```
22
+ */
23
+ interface PiFilesWebhookEvent {
24
+ id: string;
25
+ event: "file.uploaded" | "file.replaced" | "file.trashed" | "file.restored" | "file.deleted" | "file.moved" | "file.missing" | "file.created" | "file.updated" | "folder.created" | "folder.updated" | "folder.deleted";
26
+ tenantId: string;
27
+ occurredAt: string;
28
+ /** ไม่มีในเหตุการณ์ folder.* */
29
+ file?: {
30
+ id: string;
31
+ filename: string;
32
+ mimeType: string;
33
+ sizeBytes: string;
34
+ versionCount: number | null;
35
+ module: string | null;
36
+ };
37
+ /** เฉพาะ folder.* */
38
+ folder?: {
39
+ id: string;
40
+ name: string;
41
+ };
42
+ /** เหตุการณ์จาก linked source — ancestorFolderIds = โฟลเดอร์ (id ของ Pi Files) จากจุดที่ผูกลงมา ใช้ map ไปชุดเอกสาร */
43
+ source?: {
44
+ id: string;
45
+ folderId?: string | null;
46
+ ancestorFolderIds: string[];
47
+ providerFileId?: string | null;
48
+ };
49
+ [extra: string]: unknown;
50
+ }
51
+ declare function verifyWebhookSignature(body: string, header: string | null | undefined, secret: string, { toleranceSeconds, now }?: {
52
+ toleranceSeconds?: number;
53
+ now?: number;
54
+ }): boolean;
55
+
56
+ type RouteCtx = {
57
+ params: Promise<Record<string, string | string[]>>;
58
+ };
59
+ /**
60
+ * helper สำหรับ Next.js route handlers ของ consumer app:
61
+ * - handlers.content → GET /api/files/[id]/content (browser ไม่เคยเห็น URL ของ Pi Files/R2)
62
+ * - handlers.preview → GET /api/files/[id]/preview?size=sm|lg (thumbnail webp ของไฟล์รูป)
63
+ * - handlers.uploads → app/api/files/uploads/[[...path]]/route.ts (proxy create/replace/parts/complete/abort ด้วย app key)
64
+ * อัปโหลดเวอร์ชันใหม่ทับไฟล์เดิม = POST <endpoint>/replace/<fileId> (useReplace ใช้ path นี้เองเมื่อ endpoint ไม่ใช่ของ Pi Files)
65
+ * consumer เป็นคนตรวจ session/สิทธิ์ของตัวเองใน callback
66
+ */
67
+ declare function createPiFilesNext(config: {
68
+ client: PiFilesClient;
69
+ }): {
70
+ client: {
71
+ options: PiFilesOptions;
72
+ uploads: {
73
+ create: (input: CreateUploadInput) => Promise<{
74
+ kind: "put";
75
+ uploadId: string;
76
+ fileId: string;
77
+ url: string;
78
+ method: "PUT";
79
+ headers: Record<string, string>;
80
+ expiresAt: string;
81
+ } | {
82
+ kind: "multipart";
83
+ uploadId: string;
84
+ fileId: string;
85
+ partSizeBytes: number;
86
+ partCount: number;
87
+ expiresAt: string;
88
+ }>;
89
+ partUrls: (uploadId: string, partNumbers: number[]) => Promise<{
90
+ parts: {
91
+ partNumber: number;
92
+ url: string;
93
+ expiresAt: string;
94
+ method?: "PUT" | "POST" | undefined;
95
+ headers?: Record<string, string> | undefined;
96
+ }[];
97
+ }>;
98
+ complete: (uploadId: string, parts?: _pi_files_contracts.CompleteUploadInput["parts"]) => Promise<{
99
+ id: string;
100
+ filename: string;
101
+ mimeType: string;
102
+ sizeBytes: string;
103
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
104
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
105
+ ownerType: "USER" | "APP";
106
+ ownerId: string;
107
+ appKey: string | null;
108
+ folderId: string | null;
109
+ etag: string | null;
110
+ checksumSha256: string | null;
111
+ versionCount: number;
112
+ refCount: number;
113
+ metadata: Record<string, unknown>;
114
+ createdById: string | null;
115
+ createdAt: string;
116
+ updatedAt: string;
117
+ trashedAt: string | null;
118
+ contentPath: string;
119
+ previewPath: string | null;
120
+ publicUrl: string | null;
121
+ storage: {
122
+ bucketKey: string;
123
+ bucketLabel: string | null;
124
+ kind: string;
125
+ providerName: string;
126
+ sourceUrl?: string | null | undefined;
127
+ linked?: boolean | undefined;
128
+ } | null;
129
+ }>;
130
+ abort: (uploadId: string) => Promise<void>;
131
+ };
132
+ uploadApi: UploadApi;
133
+ upload: (source: UploadSource, input: CreateUploadInput, opts?: PerformUploadOptions) => Promise<_pi_files_contracts.FileAssetDto>;
134
+ replace: (fileId: string, source: UploadSource, input: ReplaceFileInput, opts?: PerformUploadOptions) => Promise<_pi_files_contracts.FileAssetDto>;
135
+ files: {
136
+ grant: (fileId: string, input?: Partial<_pi_files_contracts.CreateGrantInput>) => Promise<{
137
+ url: string;
138
+ expiresAt: string;
139
+ }>;
140
+ get: (id: string) => Promise<{
141
+ id: string;
142
+ filename: string;
143
+ mimeType: string;
144
+ sizeBytes: string;
145
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
146
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
147
+ ownerType: "USER" | "APP";
148
+ ownerId: string;
149
+ appKey: string | null;
150
+ folderId: string | null;
151
+ etag: string | null;
152
+ checksumSha256: string | null;
153
+ versionCount: number;
154
+ refCount: number;
155
+ metadata: Record<string, unknown>;
156
+ createdById: string | null;
157
+ createdAt: string;
158
+ updatedAt: string;
159
+ trashedAt: string | null;
160
+ contentPath: string;
161
+ previewPath: string | null;
162
+ publicUrl: string | null;
163
+ storage: {
164
+ bucketKey: string;
165
+ bucketLabel: string | null;
166
+ kind: string;
167
+ providerName: string;
168
+ sourceUrl?: string | null | undefined;
169
+ linked?: boolean | undefined;
170
+ } | null;
171
+ }>;
172
+ access: (id: string) => Promise<{
173
+ provider: string;
174
+ bucketKey: string;
175
+ objectKey: string;
176
+ sourceUrl: string | null;
177
+ scope: "unknown" | "anyone" | "domain" | "restricted" | "pi-files";
178
+ domains: string[];
179
+ people: {
180
+ email: string;
181
+ role: string;
182
+ name: string | null;
183
+ }[];
184
+ publicLinkAllowed: boolean;
185
+ reason: string | null;
186
+ }>;
187
+ list: (query?: Partial<_pi_files_contracts.ListFilesQuery>) => Promise<{
188
+ items: _pi_files_contracts.FileAssetDto[];
189
+ nextCursor: string | null;
190
+ }>;
191
+ search: (query: Partial<_pi_files_contracts.SearchQuery> & {
192
+ q: string;
193
+ }) => Promise<{
194
+ items: _pi_files_contracts.FileAssetDto[];
195
+ nextCursor: string | null;
196
+ }>;
197
+ update: (id: string, patch: _pi_files_contracts.UpdateFileInput) => Promise<{
198
+ id: string;
199
+ filename: string;
200
+ mimeType: string;
201
+ sizeBytes: string;
202
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
203
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
204
+ ownerType: "USER" | "APP";
205
+ ownerId: string;
206
+ appKey: string | null;
207
+ folderId: string | null;
208
+ etag: string | null;
209
+ checksumSha256: string | null;
210
+ versionCount: number;
211
+ refCount: number;
212
+ metadata: Record<string, unknown>;
213
+ createdById: string | null;
214
+ createdAt: string;
215
+ updatedAt: string;
216
+ trashedAt: string | null;
217
+ contentPath: string;
218
+ previewPath: string | null;
219
+ publicUrl: string | null;
220
+ storage: {
221
+ bucketKey: string;
222
+ bucketLabel: string | null;
223
+ kind: string;
224
+ providerName: string;
225
+ sourceUrl?: string | null | undefined;
226
+ linked?: boolean | undefined;
227
+ } | null;
228
+ }>;
229
+ trash: (id: string) => Promise<{
230
+ id: string;
231
+ filename: string;
232
+ mimeType: string;
233
+ sizeBytes: string;
234
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
235
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
236
+ ownerType: "USER" | "APP";
237
+ ownerId: string;
238
+ appKey: string | null;
239
+ folderId: string | null;
240
+ etag: string | null;
241
+ checksumSha256: string | null;
242
+ versionCount: number;
243
+ refCount: number;
244
+ metadata: Record<string, unknown>;
245
+ createdById: string | null;
246
+ createdAt: string;
247
+ updatedAt: string;
248
+ trashedAt: string | null;
249
+ contentPath: string;
250
+ previewPath: string | null;
251
+ publicUrl: string | null;
252
+ storage: {
253
+ bucketKey: string;
254
+ bucketLabel: string | null;
255
+ kind: string;
256
+ providerName: string;
257
+ sourceUrl?: string | null | undefined;
258
+ linked?: boolean | undefined;
259
+ } | null;
260
+ }>;
261
+ delete: (id: string) => Promise<{
262
+ id: string;
263
+ filename: string;
264
+ mimeType: string;
265
+ sizeBytes: string;
266
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
267
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
268
+ ownerType: "USER" | "APP";
269
+ ownerId: string;
270
+ appKey: string | null;
271
+ folderId: string | null;
272
+ etag: string | null;
273
+ checksumSha256: string | null;
274
+ versionCount: number;
275
+ refCount: number;
276
+ metadata: Record<string, unknown>;
277
+ createdById: string | null;
278
+ createdAt: string;
279
+ updatedAt: string;
280
+ trashedAt: string | null;
281
+ contentPath: string;
282
+ previewPath: string | null;
283
+ publicUrl: string | null;
284
+ storage: {
285
+ bucketKey: string;
286
+ bucketLabel: string | null;
287
+ kind: string;
288
+ providerName: string;
289
+ sourceUrl?: string | null | undefined;
290
+ linked?: boolean | undefined;
291
+ } | null;
292
+ }>;
293
+ restore: (id: string) => Promise<{
294
+ id: string;
295
+ filename: string;
296
+ mimeType: string;
297
+ sizeBytes: string;
298
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
299
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
300
+ ownerType: "USER" | "APP";
301
+ ownerId: string;
302
+ appKey: string | null;
303
+ folderId: string | null;
304
+ etag: string | null;
305
+ checksumSha256: string | null;
306
+ versionCount: number;
307
+ refCount: number;
308
+ metadata: Record<string, unknown>;
309
+ createdById: string | null;
310
+ createdAt: string;
311
+ updatedAt: string;
312
+ trashedAt: string | null;
313
+ contentPath: string;
314
+ previewPath: string | null;
315
+ publicUrl: string | null;
316
+ storage: {
317
+ bucketKey: string;
318
+ bucketLabel: string | null;
319
+ kind: string;
320
+ providerName: string;
321
+ sourceUrl?: string | null | undefined;
322
+ linked?: boolean | undefined;
323
+ } | null;
324
+ }>;
325
+ batch: (input: _pi_files_contracts.BatchFilesInput) => Promise<{
326
+ ok: string[];
327
+ failed: {
328
+ id: string;
329
+ code: string;
330
+ detail: string;
331
+ }[];
332
+ }>;
333
+ contentUrl: (id: string, opts?: {
334
+ download?: boolean;
335
+ ttl?: number;
336
+ }) => Promise<{
337
+ url: string;
338
+ expiresAt: string;
339
+ }>;
340
+ stream: (id: string, opts?: {
341
+ range?: string | null;
342
+ download?: boolean;
343
+ signal?: AbortSignal;
344
+ }) => Promise<Response>;
345
+ contentPath: (id: string, opts?: {
346
+ download?: boolean;
347
+ }) => string;
348
+ preview: (id: string, opts?: {
349
+ size?: "sm" | "lg";
350
+ signal?: AbortSignal;
351
+ }) => Promise<Response>;
352
+ replace: (id: string, input: ReplaceFileInput) => Promise<{
353
+ kind: "put";
354
+ uploadId: string;
355
+ fileId: string;
356
+ url: string;
357
+ method: "PUT";
358
+ headers: Record<string, string>;
359
+ expiresAt: string;
360
+ } | {
361
+ kind: "multipart";
362
+ uploadId: string;
363
+ fileId: string;
364
+ partSizeBytes: number;
365
+ partCount: number;
366
+ expiresAt: string;
367
+ }>;
368
+ versions: (id: string) => Promise<{
369
+ versionNo: number;
370
+ current: boolean;
371
+ filename: string;
372
+ mimeType: string;
373
+ sizeBytes: string;
374
+ createdById: string | null;
375
+ createdAt: string;
376
+ expiresAt: string | null;
377
+ }[]>;
378
+ restoreVersion: (id: string, versionNo: number) => Promise<{
379
+ id: string;
380
+ filename: string;
381
+ mimeType: string;
382
+ sizeBytes: string;
383
+ status: "UPLOADING" | "ACTIVE" | "ORPHAN_CANDIDATE" | "TRASHED" | "PENDING_DELETE" | "MISSING" | "DELETED" | "ERROR";
384
+ visibility: "PRIVATE" | "TENANT" | "PUBLIC";
385
+ ownerType: "USER" | "APP";
386
+ ownerId: string;
387
+ appKey: string | null;
388
+ folderId: string | null;
389
+ etag: string | null;
390
+ checksumSha256: string | null;
391
+ versionCount: number;
392
+ refCount: number;
393
+ metadata: Record<string, unknown>;
394
+ createdById: string | null;
395
+ createdAt: string;
396
+ updatedAt: string;
397
+ trashedAt: string | null;
398
+ contentPath: string;
399
+ previewPath: string | null;
400
+ publicUrl: string | null;
401
+ storage: {
402
+ bucketKey: string;
403
+ bucketLabel: string | null;
404
+ kind: string;
405
+ providerName: string;
406
+ sourceUrl?: string | null | undefined;
407
+ linked?: boolean | undefined;
408
+ } | null;
409
+ }>;
410
+ deleteVersion: (id: string, versionNo: number) => Promise<{
411
+ ok: true;
412
+ }>;
413
+ versionContentUrl: (id: string, versionNo: number, opts?: {
414
+ download?: boolean;
415
+ ttl?: number;
416
+ }) => Promise<{
417
+ url: string;
418
+ expiresAt: string;
419
+ }>;
420
+ };
421
+ references: {
422
+ attach: (fileId: string, ref: _pi_files_contracts.FileReferenceInput) => Promise<{
423
+ featureKey: string;
424
+ entityType: string;
425
+ entityId: string;
426
+ role: string;
427
+ id: string;
428
+ appKey: string;
429
+ createdAt: string;
430
+ }>;
431
+ detach: (fileId: string, ref: _pi_files_contracts.FileReferenceInput) => Promise<{
432
+ ok: true;
433
+ refCount: number;
434
+ }>;
435
+ listOf: (fileId: string) => Promise<{
436
+ featureKey: string;
437
+ entityType: string;
438
+ entityId: string;
439
+ role: string;
440
+ id: string;
441
+ appKey: string;
442
+ createdAt: string;
443
+ }[]>;
444
+ move: (fileId: string, from: _pi_files_contracts.FileReferenceInput, to: _pi_files_contracts.FileReferenceInput) => Promise<{
445
+ featureKey: string;
446
+ entityType: string;
447
+ entityId: string;
448
+ role: string;
449
+ id: string;
450
+ appKey: string;
451
+ createdAt: string;
452
+ }>;
453
+ byEntity: (entityType: string, entityId: string, featureKey?: string) => Promise<{
454
+ reference: _pi_files_contracts.FileReferenceDto;
455
+ file: _pi_files_contracts.FileAssetDto;
456
+ }[]>;
457
+ };
458
+ folders: {
459
+ get: (id?: string) => Promise<{
460
+ folder: {
461
+ id: string;
462
+ name: string;
463
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
464
+ ownerType: "USER" | "APP";
465
+ ownerId: string;
466
+ parentId: string | null;
467
+ path: string;
468
+ depth: number;
469
+ status: "ACTIVE" | "TRASHED";
470
+ createdAt: string;
471
+ updatedAt: string;
472
+ sourceId?: string | null | undefined;
473
+ externalId?: string | null | undefined;
474
+ };
475
+ access: "view" | "owner" | "edit";
476
+ breadcrumb: {
477
+ id: string;
478
+ name: string;
479
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
480
+ }[];
481
+ children: {
482
+ id: string;
483
+ name: string;
484
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
485
+ ownerType: "USER" | "APP";
486
+ ownerId: string;
487
+ parentId: string | null;
488
+ path: string;
489
+ depth: number;
490
+ status: "ACTIVE" | "TRASHED";
491
+ createdAt: string;
492
+ updatedAt: string;
493
+ sourceId?: string | null | undefined;
494
+ externalId?: string | null | undefined;
495
+ }[];
496
+ }>;
497
+ tree: (root?: string, depth?: number) => Promise<unknown>;
498
+ create: (input: _pi_files_contracts.CreateFolderInput) => Promise<{
499
+ id: string;
500
+ name: string;
501
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
502
+ ownerType: "USER" | "APP";
503
+ ownerId: string;
504
+ parentId: string | null;
505
+ path: string;
506
+ depth: number;
507
+ status: "ACTIVE" | "TRASHED";
508
+ createdAt: string;
509
+ updatedAt: string;
510
+ sourceId?: string | null | undefined;
511
+ externalId?: string | null | undefined;
512
+ }>;
513
+ update: (id: string, patch: _pi_files_contracts.UpdateFolderInput) => Promise<{
514
+ id: string;
515
+ name: string;
516
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
517
+ ownerType: "USER" | "APP";
518
+ ownerId: string;
519
+ parentId: string | null;
520
+ path: string;
521
+ depth: number;
522
+ status: "ACTIVE" | "TRASHED";
523
+ createdAt: string;
524
+ updatedAt: string;
525
+ sourceId?: string | null | undefined;
526
+ externalId?: string | null | undefined;
527
+ }>;
528
+ trash: (id: string) => Promise<{
529
+ ok: true;
530
+ }>;
531
+ restore: (id: string) => Promise<{
532
+ id: string;
533
+ name: string;
534
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
535
+ ownerType: "USER" | "APP";
536
+ ownerId: string;
537
+ parentId: string | null;
538
+ path: string;
539
+ depth: number;
540
+ status: "ACTIVE" | "TRASHED";
541
+ createdAt: string;
542
+ updatedAt: string;
543
+ sourceId?: string | null | undefined;
544
+ externalId?: string | null | undefined;
545
+ }>;
546
+ contents: (id: string, opts?: {
547
+ recursive?: boolean;
548
+ }) => Promise<{
549
+ folderId: string;
550
+ sourceId: string | null;
551
+ items: {
552
+ id: string;
553
+ isFolder: boolean;
554
+ name: string;
555
+ relativePath: string;
556
+ parentId: string | null;
557
+ mimeType: string | null;
558
+ sizeBytes: string | null;
559
+ md5: string | null;
560
+ modifiedTime: string | null;
561
+ providerFileId: string | null;
562
+ webViewLink: string | null;
563
+ status: string;
564
+ }[];
565
+ }>;
566
+ ensurePath: (id: string, names: string[]) => Promise<{
567
+ id: string;
568
+ name: string;
569
+ kind: "USER_ROOT" | "APP_ROOT" | "NORMAL";
570
+ ownerType: "USER" | "APP";
571
+ ownerId: string;
572
+ parentId: string | null;
573
+ path: string;
574
+ depth: number;
575
+ status: "ACTIVE" | "TRASHED";
576
+ createdAt: string;
577
+ updatedAt: string;
578
+ sourceId?: string | null | undefined;
579
+ externalId?: string | null | undefined;
580
+ }>;
581
+ };
582
+ sources: {
583
+ link: (input: _pi_files_contracts.LinkSourceInput) => Promise<{
584
+ id: string;
585
+ appKey: string;
586
+ bucketKey: string;
587
+ folderId: string;
588
+ externalFolderId: string;
589
+ sourceUrl: string;
590
+ label: string | null;
591
+ status: "ACTIVE" | "ERROR" | "PAUSED";
592
+ lastSyncedAt: string | null;
593
+ lastError: string | null;
594
+ createdAt: string;
595
+ stats?: {
596
+ folders: number;
597
+ files: number;
598
+ created: number;
599
+ updated: number;
600
+ removed: number;
601
+ } | undefined;
602
+ }>;
603
+ list: () => Promise<{
604
+ id: string;
605
+ appKey: string;
606
+ bucketKey: string;
607
+ folderId: string;
608
+ externalFolderId: string;
609
+ sourceUrl: string;
610
+ label: string | null;
611
+ status: "ACTIVE" | "ERROR" | "PAUSED";
612
+ lastSyncedAt: string | null;
613
+ lastError: string | null;
614
+ createdAt: string;
615
+ stats?: {
616
+ folders: number;
617
+ files: number;
618
+ created: number;
619
+ updated: number;
620
+ removed: number;
621
+ } | undefined;
622
+ }[]>;
623
+ get: (id: string) => Promise<{
624
+ id: string;
625
+ appKey: string;
626
+ bucketKey: string;
627
+ folderId: string;
628
+ externalFolderId: string;
629
+ sourceUrl: string;
630
+ label: string | null;
631
+ status: "ACTIVE" | "ERROR" | "PAUSED";
632
+ lastSyncedAt: string | null;
633
+ lastError: string | null;
634
+ createdAt: string;
635
+ stats?: {
636
+ folders: number;
637
+ files: number;
638
+ created: number;
639
+ updated: number;
640
+ removed: number;
641
+ } | undefined;
642
+ }>;
643
+ sync: (id: string) => Promise<{
644
+ id: string;
645
+ appKey: string;
646
+ bucketKey: string;
647
+ folderId: string;
648
+ externalFolderId: string;
649
+ sourceUrl: string;
650
+ label: string | null;
651
+ status: "ACTIVE" | "ERROR" | "PAUSED";
652
+ lastSyncedAt: string | null;
653
+ lastError: string | null;
654
+ createdAt: string;
655
+ stats?: {
656
+ folders: number;
657
+ files: number;
658
+ created: number;
659
+ updated: number;
660
+ removed: number;
661
+ } | undefined;
662
+ }>;
663
+ unlink: (id: string) => Promise<{
664
+ ok: true;
665
+ files: number;
666
+ folders: number;
667
+ }>;
668
+ };
669
+ quota: {
670
+ get: (scope?: "user" | "app" | "tenant") => Promise<{
671
+ scope: "app" | "tenant" | "user";
672
+ scopeId: string;
673
+ bytesUsed: string;
674
+ fileCount: number;
675
+ quotaBytes: string | null;
676
+ }>;
677
+ };
678
+ manifest: {
679
+ sync: (input: _pi_files_contracts.FilesManifest) => Promise<{
680
+ created: string[];
681
+ updated: string[];
682
+ deprecated: string[];
683
+ }>;
684
+ };
685
+ migration: {
686
+ adopt: (input: _pi_files_contracts.AdoptFileInput) => Promise<{
687
+ status: "created" | "existing";
688
+ fileId: string;
689
+ }>;
690
+ };
691
+ withUser: (token: string) => /*elided*/ any;
692
+ };
693
+ handlers: {
694
+ content: (opts: {
695
+ /** map request → fileId + ตรวจสิทธิ์ของ consumer; คืน null = 404, คืน Response = ส่งออกเลย (เช่น 401) */
696
+ resolve: (request: Request, params: Record<string, string | string[]>) => Promise<{
697
+ fileId: string;
698
+ download?: boolean;
699
+ filename?: string;
700
+ } | Response | null>;
701
+ /**
702
+ * redirect (default): 302 ไป presigned URL ของ storage — ถูกสุด, browser คง Range header ข้าม redirect
703
+ * stream: proxy bytes ผ่าน consumer → Pi Files → storage (URL ไม่หมดอายุ, กิน function time 2 ชั้น)
704
+ */
705
+ strategy?: "redirect" | "stream";
706
+ }) => (request: Request, ctx: RouteCtx) => Promise<Response>;
707
+ preview: (opts: {
708
+ /** map request → fileId + ตรวจสิทธิ์ของ consumer; คืน null = 404, คืน Response = ส่งออกเลย */
709
+ resolve: (request: Request, params: Record<string, string | string[]>) => Promise<{
710
+ fileId: string;
711
+ } | Response | null>;
712
+ }) => (request: Request, ctx: RouteCtx) => Promise<Response>;
713
+ uploads: (opts: {
714
+ /**
715
+ * ตรวจ session ของ consumer ทุก action; สำหรับ create ต้องคืน input ที่ server กำหนดเอง
716
+ * (featureKey / reference / onBehalfOfUserId / folderId) ทับค่าที่ browser ส่งมา
717
+ * คืน Response = ปฏิเสธ (เช่น 401/403)
718
+ */
719
+ authorize: (request: Request, action: {
720
+ kind: "create";
721
+ body: Partial<CreateUploadInput>;
722
+ }
723
+ /** อัปโหลดเวอร์ชันใหม่ทับ fileId — consumer ต้องตรวจว่าผู้ใช้แก้ไฟล์นี้ได้ */
724
+ | {
725
+ kind: "replace";
726
+ fileId: string;
727
+ body: Partial<ReplaceFileInput>;
728
+ } | {
729
+ kind: "parts" | "complete" | "abort";
730
+ uploadId: string;
731
+ }) => Promise<{
732
+ input?: Partial<CreateUploadInput>;
733
+ } | Response | null>;
734
+ }) => {
735
+ POST: (request: Request, ctx: RouteCtx) => Promise<Response>;
736
+ DELETE: (request: Request, ctx: RouteCtx) => Promise<Response>;
737
+ };
738
+ };
739
+ /** header สำหรับเรียก Pi Files เองจาก server code ของ consumer */
740
+ authHeader: () => Promise<Record<string, string>>;
741
+ url: (path: string) => string;
742
+ };
743
+ type PiFilesNext = ReturnType<typeof createPiFilesNext>;
744
+
745
+ export { PiFilesClient, PiFilesOptions, createPiFilesNext, verifyWebhookSignature };
746
+ export type { PiFilesNext, PiFilesWebhookEvent };