@cedarjs/uploads 8.0.0-canary.3429 → 8.0.0-canary.3433
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 +7 -6
- package/dist/cleanupStaleUploads.d.ts +3 -4
- package/dist/cleanupStaleUploads.d.ts.map +1 -1
- package/dist/cleanupStaleUploads.js +2 -8
- package/dist/deleteFile.d.ts +15 -16
- package/dist/deleteFile.d.ts.map +1 -1
- package/dist/deleteFile.js +10 -49
- package/dist/derivedFiles.d.ts +189 -0
- package/dist/derivedFiles.d.ts.map +1 -0
- package/dist/derivedFiles.js +376 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/types.d.ts +56 -75
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/variants.d.ts +0 -212
- package/dist/variants.d.ts.map +0 -1
- package/dist/variants.js +0 -500
package/README.md
CHANGED
|
@@ -14,12 +14,13 @@ File uploads and storage for CedarJS apps.
|
|
|
14
14
|
uploads, and confirming them.
|
|
15
15
|
- **Lifecycle utilities** (`storeFile`, `deleteFile`, `cleanupStaleUploads`) for
|
|
16
16
|
server-generated files and explicit cleanup.
|
|
17
|
-
- **Derived files
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`
|
|
17
|
+
- **Derived files**, experimental: thumbnails, previews, a video's poster
|
|
18
|
+
frame, made from uploads or from files stored elsewhere (a third-party
|
|
19
|
+
API). `defineDerivedFiles()` takes pluggable sources and one generator per
|
|
20
|
+
variant, and keeps the bookkeeping in a `DerivedFile` table: each file
|
|
21
|
+
made once on first acquire, thrown errors retried with backoff, failures
|
|
22
|
+
remembered, `resetVariants()` to remake one variant, and `deleteFor()` (or
|
|
23
|
+
`deleteFile()` for uploads) to delete them with their source.
|
|
23
24
|
- **Content detection** (`detectContentType`, `acceptedContentType`) that
|
|
24
25
|
checks what an uploaded file really is from its bytes, not from its name or
|
|
25
26
|
the type the browser claimed: images, PDF, audio/video, and OpenDocument and
|
|
@@ -3,10 +3,9 @@ export interface CleanupStaleUploadsOptions {
|
|
|
3
3
|
db: UploadDatabase;
|
|
4
4
|
targets: StorageTargets;
|
|
5
5
|
/**
|
|
6
|
-
* Rows
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* one hour, well past the five-minute validity of a presigned upload URL.
|
|
6
|
+
* Rows still `pending` after this many milliseconds are claimed as
|
|
7
|
+
* `failed`. Defaults to one hour, well past the five-minute validity of a
|
|
8
|
+
* presigned upload URL.
|
|
10
9
|
*/
|
|
11
10
|
olderThan?: number;
|
|
12
11
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cleanupStaleUploads.d.ts","sourceRoot":"","sources":["../src/cleanupStaleUploads.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAK9E,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,cAAc,CAAA;IAClB,OAAO,EAAE,cAAc,CAAA;IACvB
|
|
1
|
+
{"version":3,"file":"cleanupStaleUploads.d.ts","sourceRoot":"","sources":["../src/cleanupStaleUploads.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAK9E,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,cAAc,CAAA;IAClB,OAAO,EAAE,cAAc,CAAA;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;CACzD;AAED,MAAM,WAAW,yBAAyB;IACxC,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAA;IACf,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,EAAE,EACF,OAAO,EACP,SAAoB,EACpB,WAAqB,EACrB,SAAe,EACf,OAC0E,GAC3E,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAmFjE"}
|
|
@@ -10,7 +10,6 @@ async function cleanupStaleUploads({
|
|
|
10
10
|
onError = (error, upload) => console.error(`[cedar uploads] cleanup failed for ${upload.id}:`, error)
|
|
11
11
|
}) {
|
|
12
12
|
const now = Date.now();
|
|
13
|
-
const staleBefore = new Date(now - olderThan);
|
|
14
13
|
let claimed = 0;
|
|
15
14
|
let deleted = 0;
|
|
16
15
|
let errors = 0;
|
|
@@ -37,19 +36,14 @@ async function cleanupStaleUploads({
|
|
|
37
36
|
}
|
|
38
37
|
};
|
|
39
38
|
const stale = await db.upload.findMany({
|
|
40
|
-
where: { status: "pending",
|
|
39
|
+
where: { status: "pending", createdAt: { lt: new Date(now - olderThan) } },
|
|
41
40
|
omit: { data: true },
|
|
42
41
|
orderBy: { createdAt: "asc" },
|
|
43
42
|
take: batchSize
|
|
44
43
|
});
|
|
45
44
|
for (const upload of stale) {
|
|
46
45
|
const { count } = await db.upload.updateMany({
|
|
47
|
-
|
|
48
|
-
where: {
|
|
49
|
-
id: upload.id,
|
|
50
|
-
status: "pending",
|
|
51
|
-
updatedAt: { lt: staleBefore }
|
|
52
|
-
},
|
|
46
|
+
where: { id: upload.id, status: "pending" },
|
|
53
47
|
data: { status: "failed" }
|
|
54
48
|
});
|
|
55
49
|
if (count !== 1) {
|
package/dist/deleteFile.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import type { StorageProvider,
|
|
2
|
-
export
|
|
1
|
+
import type { StorageProvider, UploadDatabase, UploadRecord } from './types.js';
|
|
2
|
+
export interface DeleteFileOptions {
|
|
3
3
|
db: UploadDatabase;
|
|
4
4
|
upload: Pick<UploadRecord, 'id' | 'storageKey'>;
|
|
5
|
-
targets?: undefined;
|
|
6
|
-
} | {
|
|
7
|
-
db: UploadDatabase & UploadVariantDatabase;
|
|
8
|
-
upload: Pick<UploadRecord, 'id' | 'storageKey'>;
|
|
9
5
|
/**
|
|
10
|
-
*
|
|
11
|
-
* files (
|
|
12
|
-
*
|
|
13
|
-
* variants.
|
|
6
|
+
* The app's derived files (`defineDerivedFiles()` with an `uploadSource()`).
|
|
7
|
+
* When given, the upload's derived files (thumbnails, previews) are deleted
|
|
8
|
+
* first.
|
|
14
9
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
derivedFiles?: {
|
|
11
|
+
deleteForUpload(upload: {
|
|
12
|
+
id: string;
|
|
13
|
+
}): Promise<number>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
17
16
|
/**
|
|
18
17
|
* Deletes a stored file: bytes first, then the `Upload` row. Bytes-first
|
|
19
18
|
* ordering means a crash between the two steps leaves a row whose object is
|
|
@@ -21,9 +20,9 @@ export type DeleteFileOptions = {
|
|
|
21
20
|
* order would leave an unreachable object nothing references. A missing
|
|
22
21
|
* object or row is tolerated, so the call is idempotent.
|
|
23
22
|
*
|
|
24
|
-
* Pass `
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Pass `derivedFiles` to delete the upload's derived files with it, both
|
|
24
|
+
* before and after the upload itself, so a derived file being made from it
|
|
25
|
+
* at the same moment is deleted too.
|
|
27
26
|
*/
|
|
28
|
-
export declare function deleteFile(target: StorageProvider,
|
|
27
|
+
export declare function deleteFile(target: StorageProvider, { db, upload, derivedFiles }: DeleteFileOptions): Promise<void>;
|
|
29
28
|
//# sourceMappingURL=deleteFile.d.ts.map
|
package/dist/deleteFile.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE/E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,cAAc,CAAA;IAClB,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,YAAY,CAAC,CAAA;IAC/C;;;;OAIG;IACH,YAAY,CAAC,EAAE;QACb,eAAe,CAAC,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KACzD,CAAA;CACF;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,eAAe,EACvB,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,iBAAiB,GAC9C,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
package/dist/deleteFile.js
CHANGED
|
@@ -1,58 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const MAX_VARIANT_ROUNDS = 3;
|
|
4
|
-
function isPrismaError(e, code) {
|
|
5
|
-
return typeof e === "object" && e !== null && "code" in e && e.code === code;
|
|
1
|
+
function isRecordNotFound(e) {
|
|
2
|
+
return typeof e === "object" && e !== null && "code" in e && e.code === "P2025";
|
|
6
3
|
}
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
(count) => count > 0,
|
|
10
|
-
() => false
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
function hasVariantsError(id, cause) {
|
|
14
|
-
return new UploadError(
|
|
15
|
-
"HAS_VARIANTS",
|
|
16
|
-
`Upload '${id}' has derived files (variants), so its row cannot be deleted on its own. Pass \`targets\` to deleteFile() to delete the variants with it, or call deleteVariants() first.`,
|
|
17
|
-
cause
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
async function deleteFile(target, options) {
|
|
21
|
-
const { upload } = options;
|
|
22
|
-
if (!options.targets && await hasVariantRows(options.db, upload.id)) {
|
|
23
|
-
throw hasVariantsError(upload.id);
|
|
24
|
-
}
|
|
4
|
+
async function deleteFile(target, { db, upload, derivedFiles }) {
|
|
5
|
+
await derivedFiles?.deleteForUpload(upload);
|
|
25
6
|
if (upload.storageKey) {
|
|
26
7
|
await target.delete(upload.storageKey);
|
|
27
8
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
await options.db.upload.delete({ where: { id: upload.id } });
|
|
37
|
-
return;
|
|
38
|
-
} catch (e) {
|
|
39
|
-
if (isPrismaError(e, "P2025")) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (!isPrismaError(e, "P2003")) {
|
|
43
|
-
throw e;
|
|
44
|
-
}
|
|
45
|
-
if (!options.targets) {
|
|
46
|
-
if (!await hasVariantRows(options.db, upload.id)) {
|
|
47
|
-
throw e;
|
|
48
|
-
}
|
|
49
|
-
throw hasVariantsError(upload.id, e);
|
|
50
|
-
}
|
|
51
|
-
if (round >= MAX_VARIANT_ROUNDS) {
|
|
52
|
-
throw e;
|
|
53
|
-
}
|
|
9
|
+
try {
|
|
10
|
+
await db.upload.delete({ where: { id: upload.id } });
|
|
11
|
+
} catch (e) {
|
|
12
|
+
if (!isRecordNotFound(e)) {
|
|
13
|
+
throw e;
|
|
54
14
|
}
|
|
55
15
|
}
|
|
16
|
+
await derivedFiles?.deleteForUpload(upload);
|
|
56
17
|
}
|
|
57
18
|
export {
|
|
58
19
|
deleteFile
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import type { DerivedFileDatabase, StorageProvider, StorageTargets, UploadDatabase, UploadRecord } from './types.js';
|
|
2
|
+
/** A source file, as a source's `read()` returns it. */
|
|
3
|
+
export interface DerivedFileSourceFile {
|
|
4
|
+
data: Uint8Array;
|
|
5
|
+
mimeType?: string;
|
|
6
|
+
/** Made files are named after it: `photo.jpg` gives `photo-thumb-164.webp`. */
|
|
7
|
+
filename?: string;
|
|
8
|
+
/** Copied to the made files' `Upload` rows. */
|
|
9
|
+
userId?: string | null;
|
|
10
|
+
organizationId?: string | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Where derived files are made from: uploads (`uploadSource()`), or files
|
|
14
|
+
* stored elsewhere, such as documents fetched from a third-party API.
|
|
15
|
+
*/
|
|
16
|
+
export interface DerivedFileSource<Ref = string> {
|
|
17
|
+
/** A stable string for a reference. Not needed for string references. */
|
|
18
|
+
key?: (ref: Ref) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Reads the whole source file. `null` means it does not exist: the
|
|
21
|
+
* acquire throws an `UploadError` with code `NOT_FOUND` and nothing is
|
|
22
|
+
* remembered. A thrown error is temporary and retried. A streaming variant
|
|
23
|
+
* can be added next to this later without changing it.
|
|
24
|
+
*/
|
|
25
|
+
read: (ref: Ref) => Promise<DerivedFileSourceFile | null> | DerivedFileSourceFile | null;
|
|
26
|
+
}
|
|
27
|
+
/** The file a generator makes. */
|
|
28
|
+
export interface DerivedFileOutput {
|
|
29
|
+
data: Uint8Array;
|
|
30
|
+
mimeType: string;
|
|
31
|
+
filename?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a generator is called with. It is an object so that other ways to
|
|
35
|
+
* read the source, such as `openSource()` (a stream) or `sourcePath()` (a
|
|
36
|
+
* temp file), can be added later without breaking any generator.
|
|
37
|
+
*/
|
|
38
|
+
export interface DerivedFileContext {
|
|
39
|
+
/** Its name in `sources`, its key (`upload:<id>`) and the app's reference. */
|
|
40
|
+
source: {
|
|
41
|
+
name: string;
|
|
42
|
+
key: string;
|
|
43
|
+
ref: unknown;
|
|
44
|
+
};
|
|
45
|
+
variant: string;
|
|
46
|
+
/** Reads the source file, once per attempt however often it is called. */
|
|
47
|
+
readSource(): Promise<DerivedFileSourceFile & {
|
|
48
|
+
data: Buffer;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Makes one derived file: a thumbnail, a PDF's drawn first page, a video's
|
|
53
|
+
* poster frame. Return `null` when this source can't have this variant; that
|
|
54
|
+
* is a permanent failure. A thrown error is temporary, and retried.
|
|
55
|
+
*/
|
|
56
|
+
export type DerivedFileGenerator = (context: DerivedFileContext) => Promise<DerivedFileOutput | null> | DerivedFileOutput | null;
|
|
57
|
+
export interface DerivedFileDefinition {
|
|
58
|
+
generate: DerivedFileGenerator;
|
|
59
|
+
/** Where this variant's files are stored. Defaults to the `target` option. */
|
|
60
|
+
target?: StorageProvider;
|
|
61
|
+
}
|
|
62
|
+
type RefOf<S> = S extends {
|
|
63
|
+
read: (ref: infer R) => unknown;
|
|
64
|
+
} ? R : never;
|
|
65
|
+
/** One source file, by source name: `{ upload: id }`, `{ remote: ref }`. */
|
|
66
|
+
export type DerivedFileSourceRef<Sources> = {
|
|
67
|
+
[K in keyof Sources & string]: {
|
|
68
|
+
[P in K]: RefOf<Sources[K]>;
|
|
69
|
+
};
|
|
70
|
+
}[keyof Sources & string];
|
|
71
|
+
/**
|
|
72
|
+
* `pending` means not ready yet: another process is making it, or a failed
|
|
73
|
+
* attempt is waiting for its retry.
|
|
74
|
+
*/
|
|
75
|
+
export type DerivedFileResult = {
|
|
76
|
+
status: 'completed';
|
|
77
|
+
upload: UploadRecord;
|
|
78
|
+
} | {
|
|
79
|
+
status: 'pending';
|
|
80
|
+
} | {
|
|
81
|
+
status: 'failed';
|
|
82
|
+
};
|
|
83
|
+
export interface DefineDerivedFilesOptions<Sources, Name extends string> {
|
|
84
|
+
db: DerivedFileDatabase;
|
|
85
|
+
/** Every storage target, to read and delete made files wherever they are. */
|
|
86
|
+
targets: StorageTargets;
|
|
87
|
+
/** Where made files are stored, unless a variant names its own target. */
|
|
88
|
+
target: StorageProvider;
|
|
89
|
+
/** By name: `{ upload: uploadSource({ db, targets }), remote: { read } }`. */
|
|
90
|
+
sources: Sources;
|
|
91
|
+
/** By name: `{ 'thumb-164': makeThumb, preview: { generate, target } }`. */
|
|
92
|
+
variants: Record<Name, DerivedFileGenerator | DerivedFileDefinition>;
|
|
93
|
+
/**
|
|
94
|
+
* How long to wait before each retry of a throwing generator or source:
|
|
95
|
+
* one retry per entry, then it is failed. Default 1 min, 5 min, 30 min,
|
|
96
|
+
* 2 h and 6 h, so it gives up about 8.5 hours after the first attempt.
|
|
97
|
+
* `[]` never retries.
|
|
98
|
+
*/
|
|
99
|
+
retryDelays?: readonly number[];
|
|
100
|
+
/**
|
|
101
|
+
* After this long, an attempt is assumed to have died and the next acquire
|
|
102
|
+
* starts a new one. Default ten minutes; keep it above the slowest
|
|
103
|
+
* generator's running time.
|
|
104
|
+
*/
|
|
105
|
+
claimTimeout?: number;
|
|
106
|
+
/** Called with what a generator or source throws. Default `console.error`. */
|
|
107
|
+
onError?: (error: unknown, info: {
|
|
108
|
+
source: string;
|
|
109
|
+
variant: string;
|
|
110
|
+
}) => void;
|
|
111
|
+
}
|
|
112
|
+
/** Derived files of uploads and of other sources. Experimental. */
|
|
113
|
+
export interface DerivedFiles<Sources, Name extends string> {
|
|
114
|
+
names: readonly Name[];
|
|
115
|
+
/**
|
|
116
|
+
* Where the variant stands, starting to make it if nobody has. Throws an
|
|
117
|
+
* `UploadError` with code `NOT_FOUND` if the source file doesn't exist.
|
|
118
|
+
*/
|
|
119
|
+
acquireVariant(source: DerivedFileSourceRef<Sources>, name: Name): Promise<DerivedFileResult>;
|
|
120
|
+
/**
|
|
121
|
+
* The variant's row and bytes, made now if needed; `null` if not ready or
|
|
122
|
+
* failed. Throws like `acquireVariant()` if the source file doesn't exist.
|
|
123
|
+
*/
|
|
124
|
+
acquireVariantData(source: DerivedFileSourceRef<Sources>, name: Name): Promise<{
|
|
125
|
+
upload: UploadRecord;
|
|
126
|
+
data: Buffer;
|
|
127
|
+
} | null>;
|
|
128
|
+
/** The variant's `Upload` row if it has been made. Never makes anything. */
|
|
129
|
+
findVariant(source: DerivedFileSourceRef<Sources>, name: Name): Promise<UploadRecord | null>;
|
|
130
|
+
/** `findVariant()` for many sources in two queries, in the order given. */
|
|
131
|
+
findVariants(sources: DerivedFileSourceRef<Sources>[], name: Name): Promise<(UploadRecord | null)[]>;
|
|
132
|
+
/**
|
|
133
|
+
* Deletes every file of one variant, made or failed, so each is made again
|
|
134
|
+
* on its next acquire. Use it after fixing a generator.
|
|
135
|
+
*/
|
|
136
|
+
resetVariants(name: Name, options?: {
|
|
137
|
+
batchSize?: number;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
deleted: number;
|
|
140
|
+
errors: number;
|
|
141
|
+
}>;
|
|
142
|
+
/** Deletes a source file's derived files. Returns how many. */
|
|
143
|
+
deleteFor(source: DerivedFileSourceRef<Sources>): Promise<number>;
|
|
144
|
+
/** `deleteFor()` through `uploadSource()`; what `deleteFile()` calls. */
|
|
145
|
+
deleteForUpload(upload: string | {
|
|
146
|
+
id: string;
|
|
147
|
+
}): Promise<number>;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Uploads as a source of derived files: `{ upload: id }`. Made files get
|
|
151
|
+
* the upload's owner and organization. An id with no `Upload` row reads as
|
|
152
|
+
* `null`, so acquiring its variants throws `NOT_FOUND`; an upload that isn't
|
|
153
|
+
* completed yet throws, and is retried. Pass `derivedFiles` to `deleteFile()`
|
|
154
|
+
* to delete an upload's derived files with it.
|
|
155
|
+
*/
|
|
156
|
+
export declare function uploadSource({ db, targets, }: {
|
|
157
|
+
db: UploadDatabase;
|
|
158
|
+
targets: StorageTargets;
|
|
159
|
+
}): DerivedFileSource<string | {
|
|
160
|
+
id: string;
|
|
161
|
+
}>;
|
|
162
|
+
/**
|
|
163
|
+
* Declares derived files (thumbnails, previews, poster frames), the
|
|
164
|
+
* functions that make them, and the sources they are made from: uploads, or
|
|
165
|
+
* files that live elsewhere. **Experimental.**
|
|
166
|
+
*
|
|
167
|
+
* Each made file is an ordinary `Upload` row; its bookkeeping is a row in
|
|
168
|
+
* the `DerivedFile` table. A file is made on first acquire, by one process
|
|
169
|
+
* at a time. A thrown error is retried after each of `retryDelays`; a
|
|
170
|
+
* `null` from a generator is remembered as failed until `resetVariants()`.
|
|
171
|
+
* A source file that doesn't exist throws `NOT_FOUND` and isn't remembered.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* export const derivedFiles = defineDerivedFiles({
|
|
175
|
+
* db,
|
|
176
|
+
* targets,
|
|
177
|
+
* target: targets.thumbnails,
|
|
178
|
+
* sources: {
|
|
179
|
+
* upload: uploadSource({ db, targets }),
|
|
180
|
+
* remote: { read: (ref: string) => fetchDocument(ref) },
|
|
181
|
+
* },
|
|
182
|
+
* variants: { 'thumb-164': makeThumb },
|
|
183
|
+
* })
|
|
184
|
+
*
|
|
185
|
+
* await derivedFiles.acquireVariant({ upload: uploadId }, 'thumb-164')
|
|
186
|
+
*/
|
|
187
|
+
export declare function defineDerivedFiles<Sources extends Record<string, DerivedFileSource<never>>, Name extends string>(options: DefineDerivedFilesOptions<Sources, Name>): DerivedFiles<Sources, Name>;
|
|
188
|
+
export {};
|
|
189
|
+
//# sourceMappingURL=derivedFiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivedFiles.d.ts","sourceRoot":"","sources":["../src/derivedFiles.ts"],"names":[],"mappings":"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"}
|