@trokky/trokky 3.4.1 → 3.5.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.
Files changed (28) hide show
  1. package/dist/adapters/s3-media/index-key.d.ts +52 -0
  2. package/dist/adapters/s3-media/index-key.d.ts.map +1 -0
  3. package/dist/adapters/s3-media/index-key.js +91 -0
  4. package/dist/adapters/s3-media/index-key.js.map +1 -0
  5. package/dist/adapters/s3-media/index.d.ts +3 -0
  6. package/dist/adapters/s3-media/index.d.ts.map +1 -0
  7. package/dist/adapters/s3-media/index.js +12 -0
  8. package/dist/adapters/s3-media/index.js.map +1 -0
  9. package/dist/adapters/s3-media/s3-client.d.ts +112 -0
  10. package/dist/adapters/s3-media/s3-client.d.ts.map +1 -0
  11. package/dist/adapters/s3-media/s3-client.js +261 -0
  12. package/dist/adapters/s3-media/s3-client.js.map +1 -0
  13. package/dist/adapters/s3-media/s3-media-adapter.d.ts +118 -0
  14. package/dist/adapters/s3-media/s3-media-adapter.d.ts.map +1 -0
  15. package/dist/adapters/s3-media/s3-media-adapter.js +631 -0
  16. package/dist/adapters/s3-media/s3-media-adapter.js.map +1 -0
  17. package/dist/adapters/s3-media/types.d.ts +63 -0
  18. package/dist/adapters/s3-media/types.d.ts.map +1 -0
  19. package/dist/adapters/s3-media/types.js +2 -0
  20. package/dist/adapters/s3-media/types.js.map +1 -0
  21. package/dist/core/types/storage-adapters.d.ts +7 -0
  22. package/dist/core/types/storage-adapters.d.ts.map +1 -1
  23. package/dist/integrations/express/config.d.ts +6 -1
  24. package/dist/integrations/express/config.d.ts.map +1 -1
  25. package/dist/integrations/express/config.js.map +1 -1
  26. package/dist/integrations/express/integration.js +3 -3
  27. package/dist/integrations/express/integration.js.map +1 -1
  28. package/package.json +6 -1
@@ -0,0 +1,118 @@
1
+ /**
2
+ * S3-compatible media storage adapter.
3
+ *
4
+ * Talks SigV4 over HTTP, so it reaches R2 from a Node process, and MinIO, Backblaze B2, Spaces,
5
+ * Ceph or AWS from anywhere. `CloudflareR2Adapter` is the better choice *inside* a Worker — a
6
+ * binding is faster and needs no credentials — and the two share a key layout on purpose, so
7
+ * one bucket can be handed from a Worker to a Node server and back.
8
+ *
9
+ * The layout, identical to the R2 adapter's:
10
+ *
11
+ * files/<id> the bytes
12
+ * meta/<id>.json the record — the only authority for existence
13
+ * variants/<id>/<name> variant bytes, format in user metadata
14
+ * index/... the listing cache, see index-key.ts
15
+ *
16
+ * What differs, and why:
17
+ *
18
+ * - **The listing is a join, not a sweep.** R2's `list()` can return `customMetadata`;
19
+ * `ListObjectsV2` cannot return user metadata at all. So the sortable fields are encoded into
20
+ * keys under `index/`, and `listMedia` enumerates ids from `meta/`, reads fields from the
21
+ * index, and falls back to reading the record for any id the index does not cover.
22
+ * - **The index must never be the enumeration.** Writes go bytes → record → index and deletes
23
+ * reverse that, so an interrupted operation leaves a record with no index entry. If the index
24
+ * were authoritative that file would exist and never be listed — a ghost. Enumerating from
25
+ * `meta/` makes a missing entry cost one GET instead of hiding a file, and `cleanup()`
26
+ * rebuilds it.
27
+ * - **`listVariants` HEADs each variant.** The format lives in user metadata and a listing does
28
+ * not carry it. A file has a handful of variants, so this is a handful of requests, and it
29
+ * keeps the R2 invariant that variant keys carry no format — re-encoding a variant to another
30
+ * format overwrites it instead of leaving both behind.
31
+ */
32
+ import type { MediaFile, MediaMetadata } from '../../core/types/index.js';
33
+ import type { MediaListOptions, MediaListResult, MediaStorageAdapter, MediaVariant } from '../../core/types/storage-adapters.js';
34
+ import type { S3MediaAdapterConfig } from './types.js';
35
+ export declare class S3MediaAdapter implements MediaStorageAdapter {
36
+ private readonly s3;
37
+ private readonly prefix;
38
+ private readonly publicBaseUrl?;
39
+ private readonly urlExpiry;
40
+ private readonly maxFileSize;
41
+ private readonly silent;
42
+ private readonly logger;
43
+ constructor(config: S3MediaAdapterConfig);
44
+ private fileKey;
45
+ private recordKey;
46
+ private variantKey;
47
+ private variantPrefix;
48
+ private recordPrefix;
49
+ uploadFile(file: File, metadata: MediaMetadata): Promise<MediaFile>;
50
+ getFile(id: string): Promise<MediaFile | null>;
51
+ updateFile(id: string, metadata: Record<string, any>): Promise<MediaFile>;
52
+ getFileContent(id: string): Promise<ArrayBuffer | null>;
53
+ getFileUrl(id: string, options?: {
54
+ expiresIn?: number;
55
+ }): Promise<string | null>;
56
+ fileExists(id: string): Promise<boolean>;
57
+ getFileSize(id: string): Promise<number | null>;
58
+ deleteFile(id: string): Promise<void>;
59
+ listMedia(options?: MediaListOptions): Promise<MediaListResult>;
60
+ saveVariantFile(parentId: string, variantName: string, buffer: Buffer, format: string): Promise<string>;
61
+ getVariantContent(parentId: string, variantName: string): Promise<ArrayBuffer | null>;
62
+ getVariantUrl(parentId: string, variantName: string, options?: {
63
+ expiresIn?: number;
64
+ }): Promise<string | null>;
65
+ listVariants(parentId: string): Promise<MediaVariant[]>;
66
+ deleteVariantFiles(parentId: string): Promise<void>;
67
+ deleteVariant(parentId: string, variantName: string): Promise<void>;
68
+ healthCheck(): Promise<boolean>;
69
+ getStorageInfo(): Promise<{
70
+ totalFiles: number;
71
+ totalSize: number;
72
+ availableSpace?: number;
73
+ usedSpace?: number;
74
+ [key: string]: unknown;
75
+ }>;
76
+ /**
77
+ * Reconcile the bucket against its records, which are the only authority.
78
+ *
79
+ * Three jobs, and the order they are listed in is the order of how much they matter:
80
+ *
81
+ * 1. **Rebuild missing index entries.** An upload interrupted after the record but before the
82
+ * index — or a delete interrupted the other way — leaves a file that `getFile` serves and
83
+ * no listing shows. `listMedia` already heals the symptom by reading the record; this
84
+ * removes the cost.
85
+ * 2. **Drop orphaned bytes.** Anything under `files/` or `variants/` whose id has no record.
86
+ * 3. **Drop stale index entries.** Unreachable by an interruption under these write orders,
87
+ * but reachable by a partial restore or by a re-upload whose old-entry delete failed.
88
+ *
89
+ * Returns the number of objects written or deleted.
90
+ */
91
+ cleanup(): Promise<number>;
92
+ private writeRecord;
93
+ private readRecord;
94
+ private writeIndexEntry;
95
+ /**
96
+ * Every index key for an id, whatever epoch it carries.
97
+ *
98
+ * One prefix listing rather than a sweep of the whole index — which is the entire reason the
99
+ * key puts the id before the timestamp. This runs on every upload.
100
+ */
101
+ private deleteIndexEntries;
102
+ private listRecordIds;
103
+ /**
104
+ * Every record in the bucket, with its listable fields.
105
+ *
106
+ * Two key-only listings — `meta/` for the ids, `index/` for the fields — joined by id. The
107
+ * records are the authority for *which* files exist; the index only saves reading them. An id
108
+ * the index does not cover (a bucket written by the R2 adapter, a hand-copied object, an
109
+ * interrupted upload) falls back to a real read, so it is never silently invisible.
110
+ */
111
+ private listIndex;
112
+ /** Every request here is a network round trip, so fan out — but not without a ceiling. */
113
+ private mapWithConcurrency;
114
+ private sortIndex;
115
+ private toMediaFile;
116
+ private validateMediaMetadata;
117
+ }
118
+ //# sourceMappingURL=s3-media-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3-media-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/s3-media/s3-media-adapter.ts"],"names":[],"mappings":"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"}