@cedarjs/uploads 7.0.1-next.333 → 7.0.1-next.467
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 +11 -0
- package/dist/authenticator.d.ts +2 -2
- package/dist/authenticator.d.ts.map +1 -1
- package/dist/cleanupStaleUploads.d.ts +4 -3
- package/dist/cleanupStaleUploads.d.ts.map +1 -1
- package/dist/cleanupStaleUploads.js +8 -2
- package/dist/contentTypes.d.ts +74 -0
- package/dist/contentTypes.d.ts.map +1 -0
- package/dist/contentTypes.js +78 -0
- package/dist/deleteFile.d.ts +19 -4
- package/dist/deleteFile.d.ts.map +1 -1
- package/dist/deleteFile.js +49 -8
- package/dist/detectContentType.d.ts +168 -0
- package/dist/detectContentType.d.ts.map +1 -0
- package/dist/detectContentType.js +443 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -1
- package/dist/fastify/plugin.d.ts +30 -2
- package/dist/fastify/plugin.d.ts.map +1 -1
- package/dist/fastify/plugin.js +38 -10
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -0
- package/dist/keys.d.ts +3 -1
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +2 -1
- package/dist/profiles.d.ts +8 -2
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +5 -4
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +16 -0
- package/dist/services.d.ts +24 -6
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +45 -10
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/variants.d.ts +207 -0
- package/dist/variants.d.ts.map +1 -0
- package/dist/variants.js +498 -0
- package/dist/verifyStoredContentType.d.ts +19 -0
- package/dist/verifyStoredContentType.d.ts.map +1 -0
- package/dist/verifyStoredContentType.js +41 -0
- package/dist/webhooks/s3.d.ts +17 -8
- package/dist/webhooks/s3.d.ts.map +1 -1
- package/dist/webhooks/s3.js +22 -3
- package/package.json +18 -18
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { ContentDisposition, StorageProvider, StorageTargets, UploadVariantDatabase, UploadVariantRecord } from './types.js';
|
|
2
|
+
/** The file a variant generator returns. */
|
|
3
|
+
export interface UploadVariantFile {
|
|
4
|
+
/** The derived file's bytes. */
|
|
5
|
+
data: Uint8Array;
|
|
6
|
+
/** MIME type of `data`, for example `image/webp`. */
|
|
7
|
+
mimeType: string;
|
|
8
|
+
/**
|
|
9
|
+
* Filename for the derived file's `Upload` row. Defaults to the source's
|
|
10
|
+
* filename without its extension, plus the variant name and the extension
|
|
11
|
+
* of `mimeType`: `photo.jpg` becomes `photo-thumb-164.webp`.
|
|
12
|
+
*/
|
|
13
|
+
filename?: string;
|
|
14
|
+
}
|
|
15
|
+
/** What a variant generator is called with. */
|
|
16
|
+
export interface UploadVariantContext {
|
|
17
|
+
/** The source file's `Upload` row, without its inline `data`. */
|
|
18
|
+
source: UploadVariantRecord;
|
|
19
|
+
/** Name of the variant being made, for example `'thumb-164'`. */
|
|
20
|
+
variant: string;
|
|
21
|
+
/** Reads the source file's bytes from whichever target holds them. */
|
|
22
|
+
readSource(): Promise<Buffer>;
|
|
23
|
+
/**
|
|
24
|
+
* Reads another variant of the same source, making it first if it does
|
|
25
|
+
* not exist yet. Returns `null` when that variant could not be made. This
|
|
26
|
+
* is how one derived file is made from another, for example a PDF's
|
|
27
|
+
* thumbnail cut from its drawn first page (`readVariant('preview')`).
|
|
28
|
+
*/
|
|
29
|
+
readVariant(name: string): Promise<Buffer | null>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Makes one derived file (variant) from its source: a thumbnail from a
|
|
33
|
+
* photo, a preview image from a PDF, a poster frame from a video. This is
|
|
34
|
+
* the only part the app writes; the uploads package stores the result,
|
|
35
|
+
* links it to its source, and keeps track of it.
|
|
36
|
+
*
|
|
37
|
+
* Return `null` when this source cannot have this variant (a file type the
|
|
38
|
+
* generator does not handle). Both `null` and a thrown error are remembered
|
|
39
|
+
* as a failure and not retried until `retryFailedAfter` has passed.
|
|
40
|
+
*/
|
|
41
|
+
export type UploadVariantGenerator = (context: UploadVariantContext) => Promise<UploadVariantFile | null> | UploadVariantFile | null;
|
|
42
|
+
/** A variant generator plus where its files are stored. */
|
|
43
|
+
export interface UploadVariantDefinition {
|
|
44
|
+
generate: UploadVariantGenerator;
|
|
45
|
+
/** Storage target for this variant's files. Defaults to the `target` option. */
|
|
46
|
+
target?: StorageProvider;
|
|
47
|
+
}
|
|
48
|
+
export interface DefineUploadVariantsOptions<Name extends string> {
|
|
49
|
+
db: UploadVariantDatabase;
|
|
50
|
+
/**
|
|
51
|
+
* Every configured storage target. Used to read sources and to read and
|
|
52
|
+
* delete variants wherever they are stored.
|
|
53
|
+
*/
|
|
54
|
+
targets: StorageTargets;
|
|
55
|
+
/** Storage target new variant files are written to, unless a variant names its own. */
|
|
56
|
+
target: StorageProvider;
|
|
57
|
+
/**
|
|
58
|
+
* The variants, by name, each with the function that makes it:
|
|
59
|
+
* `{ 'thumb-164': makeThumb, preview: makePdfPreview }`. Names may use
|
|
60
|
+
* letters, digits, `.`, `_` and `-`.
|
|
61
|
+
*/
|
|
62
|
+
variants: Record<Name, UploadVariantGenerator | UploadVariantDefinition>;
|
|
63
|
+
/**
|
|
64
|
+
* How long a variant that could not be made is left alone before the
|
|
65
|
+
* next request tries again, in milliseconds. Defaults to one day.
|
|
66
|
+
*/
|
|
67
|
+
retryFailedAfter?: number;
|
|
68
|
+
/**
|
|
69
|
+
* How long a claim to make a variant is honored, in milliseconds. A
|
|
70
|
+
* request that finds a claim older than this assumes its maker died and
|
|
71
|
+
* makes the variant itself. Defaults to ten minutes; set it above the
|
|
72
|
+
* slowest generator's running time.
|
|
73
|
+
*/
|
|
74
|
+
claimTimeout?: number;
|
|
75
|
+
/**
|
|
76
|
+
* How often a request waiting for another process to finish making the
|
|
77
|
+
* same variant checks again, in milliseconds. Defaults to 250.
|
|
78
|
+
*/
|
|
79
|
+
pollInterval?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Called when a generator throws or its result cannot be stored. Defaults
|
|
82
|
+
* to `console.error`. The failure is remembered either way.
|
|
83
|
+
*/
|
|
84
|
+
onError?: (error: unknown, info: {
|
|
85
|
+
sourceId: string;
|
|
86
|
+
variant: string;
|
|
87
|
+
}) => void;
|
|
88
|
+
}
|
|
89
|
+
/** What `regenerateVariants()` did. */
|
|
90
|
+
export interface RegenerateVariantsResult {
|
|
91
|
+
/** Variant files deleted, made or failed alike. */
|
|
92
|
+
deleted: number;
|
|
93
|
+
/** Variants made again. */
|
|
94
|
+
made: number;
|
|
95
|
+
/** Variants that could not be made again (remembered as failed). */
|
|
96
|
+
failed: number;
|
|
97
|
+
/** Variants that could not be deleted; reported through `onError`. */
|
|
98
|
+
errors: number;
|
|
99
|
+
}
|
|
100
|
+
/** A source upload, by id or by its row. */
|
|
101
|
+
export type UploadVariantSource = string | {
|
|
102
|
+
id: string;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Derived files (variants) of uploads: thumbnails, previews, poster frames.
|
|
106
|
+
* Returned by `defineUploadVariants()`.
|
|
107
|
+
*/
|
|
108
|
+
export interface UploadVariants<Name extends string> {
|
|
109
|
+
/** The configured variant names. */
|
|
110
|
+
names: readonly Name[];
|
|
111
|
+
/**
|
|
112
|
+
* The variant's `Upload` row, made now if it does not exist yet. Returns
|
|
113
|
+
* `null` when it could not be made and `retryFailedAfter` has not passed.
|
|
114
|
+
*
|
|
115
|
+
* Making a variant happens once: concurrent calls in this process share
|
|
116
|
+
* one attempt, and across processes a claim row decides who makes it
|
|
117
|
+
* while the others wait for the result.
|
|
118
|
+
*/
|
|
119
|
+
getVariant(source: UploadVariantSource, name: Name): Promise<UploadVariantRecord | null>;
|
|
120
|
+
/**
|
|
121
|
+
* The variant's `Upload` row if it has been made, or `null`. Never makes
|
|
122
|
+
* anything; use it where making on demand would be too slow, such as a
|
|
123
|
+
* list page.
|
|
124
|
+
*/
|
|
125
|
+
findVariant(source: UploadVariantSource, name: Name): Promise<UploadVariantRecord | null>;
|
|
126
|
+
/**
|
|
127
|
+
* The made variants of many sources in one query, keyed by source id.
|
|
128
|
+
* Sources without that variant are left out. Never makes anything.
|
|
129
|
+
*/
|
|
130
|
+
findVariants(sourceIds: string[], name: Name): Promise<Map<string, UploadVariantRecord>>;
|
|
131
|
+
/**
|
|
132
|
+
* The variant's row and bytes, made now if it does not exist yet, or
|
|
133
|
+
* `null` when it could not be made.
|
|
134
|
+
*/
|
|
135
|
+
readVariant(source: UploadVariantSource, name: Name): Promise<{
|
|
136
|
+
upload: UploadVariantRecord;
|
|
137
|
+
data: Buffer;
|
|
138
|
+
} | null>;
|
|
139
|
+
/**
|
|
140
|
+
* A URL a browser can load the variant from, made now if it does not
|
|
141
|
+
* exist yet: a signed URL for object storage, a `data:` URI for database
|
|
142
|
+
* targets. `null` when the variant could not be made.
|
|
143
|
+
*/
|
|
144
|
+
getVariantUrl(source: UploadVariantSource, name: Name, options?: {
|
|
145
|
+
expiresIn?: number;
|
|
146
|
+
disposition?: ContentDisposition;
|
|
147
|
+
}): Promise<string | null>;
|
|
148
|
+
/**
|
|
149
|
+
* Remakes every variant called `name`, for every source that has one
|
|
150
|
+
* (made or failed), and leaves other variants alone. Use it after fixing
|
|
151
|
+
* a generator. Each old file is deleted, then the variant is made again
|
|
152
|
+
* unless `remake` is `false`, in which case it is made on its next read.
|
|
153
|
+
*/
|
|
154
|
+
regenerateVariants(name: Name, options?: {
|
|
155
|
+
remake?: boolean;
|
|
156
|
+
batchSize?: number;
|
|
157
|
+
}): Promise<RegenerateVariantsResult>;
|
|
158
|
+
/**
|
|
159
|
+
* Deletes all variants of a source, bytes first, then rows. `deleteFile()`
|
|
160
|
+
* does this for you when given `targets`.
|
|
161
|
+
*/
|
|
162
|
+
deleteVariants(source: UploadVariantSource): Promise<number>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Deletes every derived file (variant) of `source`: bytes first, then rows,
|
|
166
|
+
* like `deleteFile()`. Returns how many were deleted. `deleteFile()` calls
|
|
167
|
+
* this when given `targets`, so a source never goes without its variants.
|
|
168
|
+
*/
|
|
169
|
+
export declare function deleteVariants(source: UploadVariantSource, { db, targets }: {
|
|
170
|
+
db: UploadVariantDatabase;
|
|
171
|
+
targets: StorageTargets;
|
|
172
|
+
}): Promise<number>;
|
|
173
|
+
/**
|
|
174
|
+
* Declares the derived files (variants) uploads can have, such as
|
|
175
|
+
* thumbnails, previews or a video's poster frame, each with the function
|
|
176
|
+
* that makes it. **Experimental.**
|
|
177
|
+
*
|
|
178
|
+
* The app supplies only the generators. The uploads package keeps the
|
|
179
|
+
* bookkeeping: each variant is an `Upload` row linked to its source by
|
|
180
|
+
* `sourceId` and named by `variant`; it is made on first read, once even
|
|
181
|
+
* when several requests or processes ask at the same moment; a variant
|
|
182
|
+
* that cannot be made is remembered and tried again after
|
|
183
|
+
* `retryFailedAfter`; `regenerateVariants()` remakes every variant of one
|
|
184
|
+
* name; and `deleteFile()` with `targets` deletes a source's variants with
|
|
185
|
+
* it.
|
|
186
|
+
*
|
|
187
|
+
* The package does not make images or read videos itself. A generator is
|
|
188
|
+
* any function from source bytes to new bytes, using sharp, pdf.js, ffmpeg
|
|
189
|
+
* or a third-party service as the app sees fit.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* export const uploadVariants = defineUploadVariants({
|
|
193
|
+
* db,
|
|
194
|
+
* targets,
|
|
195
|
+
* target: targets.thumbnails,
|
|
196
|
+
* variants: {
|
|
197
|
+
* 'thumb-164': async ({ readSource }) => ({
|
|
198
|
+
* data: await sharp(await readSource()).resize(164, 164).webp().toBuffer(),
|
|
199
|
+
* mimeType: 'image/webp',
|
|
200
|
+
* }),
|
|
201
|
+
* },
|
|
202
|
+
* })
|
|
203
|
+
*
|
|
204
|
+
* const thumb = await uploadVariants.getVariant(photo.uploadId, 'thumb-164')
|
|
205
|
+
*/
|
|
206
|
+
export declare function defineUploadVariants<Name extends string>(options: DefineUploadVariantsOptions<Name>): UploadVariants<Name>;
|
|
207
|
+
//# sourceMappingURL=variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variants.d.ts","sourceRoot":"","sources":["../src/variants.ts"],"names":[],"mappings":"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"}
|