transloadit 4.12.0 → 4.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/README.md +231 -23
- package/dist/Transloadit.d.ts +55 -1
- package/dist/Transloadit.d.ts.map +1 -1
- package/dist/Transloadit.js +143 -2
- package/dist/Transloadit.js.map +1 -1
- package/dist/alphalib/types/assemblyStatus.d.ts +574 -198
- package/dist/alphalib/types/assemblyStatus.d.ts.map +1 -1
- package/dist/alphalib/types/assemblyStatus.js +17 -0
- package/dist/alphalib/types/assemblyStatus.js.map +1 -1
- package/dist/alphalib/types/robots/_index.d.ts +205 -93
- package/dist/alphalib/types/robots/_index.d.ts.map +1 -1
- package/dist/alphalib/types/robots/_index.js +8 -0
- package/dist/alphalib/types/robots/_index.js.map +1 -1
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts +4 -4
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts.map +1 -1
- package/dist/alphalib/types/robots/_instructions-primitives.js +2 -0
- package/dist/alphalib/types/robots/_instructions-primitives.js.map +1 -1
- package/dist/alphalib/types/robots/file-serve.d.ts +12 -0
- package/dist/alphalib/types/robots/file-serve.d.ts.map +1 -1
- package/dist/alphalib/types/robots/file-serve.js +9 -3
- package/dist/alphalib/types/robots/file-serve.js.map +1 -1
- package/dist/alphalib/types/robots/transloadit-import.d.ts +195 -0
- package/dist/alphalib/types/robots/transloadit-import.d.ts.map +1 -0
- package/dist/alphalib/types/robots/transloadit-import.js +108 -0
- package/dist/alphalib/types/robots/transloadit-import.js.map +1 -0
- package/dist/alphalib/types/robots/transloadit-store.d.ts +441 -0
- package/dist/alphalib/types/robots/transloadit-store.d.ts.map +1 -0
- package/dist/alphalib/types/robots/transloadit-store.js +69 -0
- package/dist/alphalib/types/robots/transloadit-store.js.map +1 -0
- package/dist/alphalib/types/robots/video-ondemand.d.ts +8 -8
- package/dist/alphalib/types/storageAsset.d.ts +226 -0
- package/dist/alphalib/types/storageAsset.d.ts.map +1 -0
- package/dist/alphalib/types/storageAsset.js +67 -0
- package/dist/alphalib/types/storageAsset.js.map +1 -0
- package/dist/alphalib/types/template.d.ts.map +1 -1
- package/dist/alphalib/types/template.js +5 -2
- package/dist/alphalib/types/template.js.map +1 -1
- package/dist/alphalib/types/templateCredential.d.ts +2 -2
- package/dist/cli/commands/BaseCommand.d.ts +3 -1
- package/dist/cli/commands/BaseCommand.d.ts.map +1 -1
- package/dist/cli/commands/BaseCommand.js +3 -2
- package/dist/cli/commands/BaseCommand.js.map +1 -1
- package/dist/cli/commands/assemblies.d.ts.map +1 -1
- package/dist/cli/commands/assemblies.js +9 -4
- package/dist/cli/commands/assemblies.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +6 -0
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +21 -2
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/image.d.ts +15 -0
- package/dist/cli/commands/image.d.ts.map +1 -0
- package/dist/cli/commands/image.js +234 -0
- package/dist/cli/commands/image.js.map +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +15 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/login.d.ts +24 -0
- package/dist/cli/commands/login.d.ts.map +1 -0
- package/dist/cli/commands/login.js +275 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/storage.d.ts +58 -0
- package/dist/cli/commands/storage.d.ts.map +1 -0
- package/dist/cli/commands/storage.js +589 -0
- package/dist/cli/commands/storage.js.map +1 -0
- package/dist/cli/commands/templates.d.ts.map +1 -1
- package/dist/cli/commands/templates.js +10 -6
- package/dist/cli/commands/templates.js.map +1 -1
- package/dist/cli/deviceLogin.d.ts +11 -0
- package/dist/cli/deviceLogin.d.ts.map +1 -0
- package/dist/cli/deviceLogin.js +187 -0
- package/dist/cli/deviceLogin.js.map +1 -0
- package/dist/cli/helpers.d.ts +23 -1
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/helpers.js +159 -25
- package/dist/cli/helpers.js.map +1 -1
- package/dist/cli/secretInput.d.ts +3 -0
- package/dist/cli/secretInput.d.ts.map +1 -0
- package/dist/cli/secretInput.js +11 -0
- package/dist/cli/secretInput.js.map +1 -0
- package/dist/cli/storageCatalog.d.ts +19 -0
- package/dist/cli/storageCatalog.d.ts.map +1 -0
- package/dist/cli/storageCatalog.js +129 -0
- package/dist/cli/storageCatalog.js.map +1 -0
- package/dist/cli/storagePublic.d.ts +3 -0
- package/dist/cli/storagePublic.d.ts.map +1 -0
- package/dist/cli/storagePublic.js +15 -0
- package/dist/cli/storagePublic.js.map +1 -0
- package/dist/cli/storageReceipts.d.ts +67 -0
- package/dist/cli/storageReceipts.d.ts.map +1 -0
- package/dist/cli/storageReceipts.js +242 -0
- package/dist/cli/storageReceipts.js.map +1 -0
- package/dist/cli/storageSnippets.d.ts +11 -0
- package/dist/cli/storageSnippets.d.ts.map +1 -0
- package/dist/cli/storageSnippets.js +89 -0
- package/dist/cli/storageSnippets.js.map +1 -0
- package/dist/storageImage.d.ts +40 -0
- package/dist/storageImage.d.ts.map +1 -0
- package/dist/storageImage.js +181 -0
- package/dist/storageImage.js.map +1 -0
- package/dist/storagePublicPrefixes.d.ts +62 -0
- package/dist/storagePublicPrefixes.d.ts.map +1 -0
- package/dist/storagePublicPrefixes.js +35 -0
- package/dist/storagePublicPrefixes.js.map +1 -0
- package/dist/storageResults.d.ts +31 -0
- package/dist/storageResults.d.ts.map +1 -0
- package/dist/storageResults.js +79 -0
- package/dist/storageResults.js.map +1 -0
- package/package.json +8 -3
- package/src/Transloadit.ts +251 -4
- package/src/alphalib/types/assemblyStatus.ts +17 -0
- package/src/alphalib/types/robots/_index.ts +28 -0
- package/src/alphalib/types/robots/_instructions-primitives.ts +2 -0
- package/src/alphalib/types/robots/file-serve.ts +11 -3
- package/src/alphalib/types/robots/transloadit-import.ts +154 -0
- package/src/alphalib/types/robots/transloadit-store.ts +98 -0
- package/src/alphalib/types/storageAsset.ts +88 -0
- package/src/alphalib/types/template.ts +3 -0
- package/src/cli/commands/BaseCommand.ts +4 -2
- package/src/cli/commands/assemblies.ts +13 -5
- package/src/cli/commands/auth.ts +26 -3
- package/src/cli/commands/image.ts +282 -0
- package/src/cli/commands/index.ts +27 -1
- package/src/cli/commands/login.ts +334 -0
- package/src/cli/commands/storage.ts +733 -0
- package/src/cli/commands/templates.ts +14 -7
- package/src/cli/deviceLogin.ts +226 -0
- package/src/cli/helpers.ts +204 -27
- package/src/cli/secretInput.ts +12 -0
- package/src/cli/storageCatalog.ts +192 -0
- package/src/cli/storagePublic.ts +15 -0
- package/src/cli/storageReceipts.ts +307 -0
- package/src/cli/storageSnippets.ts +96 -0
- package/src/storageImage.ts +266 -0
- package/src/storagePublicPrefixes.ts +39 -0
- package/src/storageResults.ts +119 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { chmod, lstat, open, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, join } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { storedAssetSchema } from "../alphalib/types/storageAsset.js";
|
|
6
|
+
import { normalizeStoragePublicPrefix } from "../storagePublicPrefixes.js";
|
|
7
|
+
import { ensureError, isErrnoException } from "./types.js";
|
|
8
|
+
// Keep every JSON key verbatim: a Storage filename may be "__proto__", which z.record strips.
|
|
9
|
+
const receiptsSchema = z.custom((value) => typeof value === 'object' && value !== null && !Array.isArray(value));
|
|
10
|
+
const deliveryParameterSchema = z.union([z.string(), z.number(), z.boolean()]);
|
|
11
|
+
/** Project identity and rendering metadata (including optional preview pixels), without credentials. */
|
|
12
|
+
export const storageCatalogSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
workspace: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/),
|
|
15
|
+
apiOrigin: z.string().url().optional(),
|
|
16
|
+
public: z.array(z.string().refine((prefix) => {
|
|
17
|
+
try {
|
|
18
|
+
return normalizeStoragePublicPrefix(prefix) === prefix;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}, 'Expected a normalized public directory')),
|
|
24
|
+
images: receiptsSchema,
|
|
25
|
+
delivery: z
|
|
26
|
+
.object({
|
|
27
|
+
baseUrl: z.string().url().optional(),
|
|
28
|
+
urlParams: z
|
|
29
|
+
.record(z.string(), z.union([deliveryParameterSchema, z.array(deliveryParameterSchema)]))
|
|
30
|
+
.optional(),
|
|
31
|
+
})
|
|
32
|
+
.passthrough()
|
|
33
|
+
.optional(),
|
|
34
|
+
})
|
|
35
|
+
.passthrough();
|
|
36
|
+
/** Default project catalog; --receipts can select a separate project explicitly. */
|
|
37
|
+
export const defaultStorageCatalog = 'transloadit.images.json';
|
|
38
|
+
/** Non-production login origins are explicit transport overrides, never rendering credentials. */
|
|
39
|
+
export function storageCatalogDelivery(endpoint) {
|
|
40
|
+
if (!endpoint)
|
|
41
|
+
return undefined;
|
|
42
|
+
const { origin } = new URL(endpoint);
|
|
43
|
+
if (origin === 'https://api2.transloadit.com')
|
|
44
|
+
return undefined;
|
|
45
|
+
return { baseUrl: `${origin}/file/{workspace}`, urlParams: { cdn: 'required' } };
|
|
46
|
+
}
|
|
47
|
+
const imageReceiptSchema = storedAssetSchema.extend({
|
|
48
|
+
width: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
49
|
+
height: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
|
|
50
|
+
});
|
|
51
|
+
const typesHeader = '// Generated by transloadit storage. Commit this file with the image catalog; do not edit.';
|
|
52
|
+
/** The single conventional type-registration file beside a CLI catalog. */
|
|
53
|
+
export function storageTypesPath(catalog) {
|
|
54
|
+
return join(dirname(catalog), 'transloadit-images.d.ts');
|
|
55
|
+
}
|
|
56
|
+
function catalogTypes(catalog, file) {
|
|
57
|
+
// Canonical LF keeps generated output deterministic; Git controls checkout-specific EOL conversion.
|
|
58
|
+
const properties = Object.entries(catalog.images)
|
|
59
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
60
|
+
.flatMap(([path, receipt]) => {
|
|
61
|
+
const dimensions = imageReceiptSchema.safeParse(receipt);
|
|
62
|
+
// Legacy entries remain on disk, but require native recovery before they are usable sources.
|
|
63
|
+
if (!dimensions.success)
|
|
64
|
+
return [];
|
|
65
|
+
const { width, height, asset_id, version_id, workspace } = dimensions.data;
|
|
66
|
+
const name = JSON.stringify(path);
|
|
67
|
+
return ` ${name}: { path: ${name}; workspace: ${JSON.stringify(workspace)}; asset_id: ${JSON.stringify(asset_id)}; version_id: ${JSON.stringify(version_id)}; width: ${width}; height: ${height}; thumbhash?: string; hasAlpha?: boolean }`;
|
|
68
|
+
});
|
|
69
|
+
return [
|
|
70
|
+
typesHeader,
|
|
71
|
+
...(file === undefined ? [] : [`// Catalog: ${JSON.stringify(basename(file))}`]),
|
|
72
|
+
"import '@transloadit/viewer/next'",
|
|
73
|
+
'',
|
|
74
|
+
"declare module '@transloadit/viewer/next' {",
|
|
75
|
+
' interface RegisteredStorageImages {',
|
|
76
|
+
...properties,
|
|
77
|
+
' }',
|
|
78
|
+
'}',
|
|
79
|
+
'',
|
|
80
|
+
].join('\n');
|
|
81
|
+
}
|
|
82
|
+
async function readReceipts(file) {
|
|
83
|
+
try {
|
|
84
|
+
const info = await lstat(file);
|
|
85
|
+
if (!info.isFile())
|
|
86
|
+
throw new Error('Expected a regular JSON file, not a symlink or directory');
|
|
87
|
+
return {
|
|
88
|
+
catalog: storageCatalogSchema.parse(JSON.parse(await readFile(file, 'utf8'))),
|
|
89
|
+
mode: info.mode & 0o777,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (isErrnoException(error) && error.code === 'ENOENT')
|
|
94
|
+
return {};
|
|
95
|
+
const reason = error instanceof SyntaxError
|
|
96
|
+
? 'invalid JSON'
|
|
97
|
+
: error instanceof z.ZodError
|
|
98
|
+
? `invalid catalog field ${error.issues[0]?.path.join('.') || 'workspace/public/images'}`
|
|
99
|
+
: ensureError(error).message;
|
|
100
|
+
throw new Error(`Cannot read receipts ${JSON.stringify(file)}: ${reason}`, { cause: error });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Read a project binding without creating a catalog or making a network request. */
|
|
104
|
+
export async function readStorageCatalog(file) {
|
|
105
|
+
return (await readReceipts(file)).catalog;
|
|
106
|
+
}
|
|
107
|
+
/** A workspace override selects another workspace, never another key or implicit project rebinding. */
|
|
108
|
+
export function assertStorageWorkspace(actual, project, requested) {
|
|
109
|
+
if (!storageCatalogSchema.shape.workspace.safeParse(actual).success)
|
|
110
|
+
throw new Error(`Invalid Storage Workspace ${JSON.stringify(actual)}: expected a URL-safe slug beginning with a letter or digit.`);
|
|
111
|
+
if (requested !== undefined && requested !== actual)
|
|
112
|
+
throw new Error(`Selected credentials belong to ${actual}, not ${requested}. Nothing uploaded.`);
|
|
113
|
+
if (project !== undefined && project !== actual && requested === undefined)
|
|
114
|
+
throw new Error(`Project uses ${project}; the selected credentials belong to ${actual}. Nothing uploaded.`);
|
|
115
|
+
}
|
|
116
|
+
const receiptOriginSchema = z.object({ apiOrigin: z.string().url().optional() });
|
|
117
|
+
/** Delivery hosts do not prove provenance; a matching Workspace slug is not an API identity. */
|
|
118
|
+
export function assertStorageCatalogOrigin(catalog, endpoint, file) {
|
|
119
|
+
const mismatch = () => new Error(`Catalog ${JSON.stringify(file)} belongs to another API environment. Use --receipts for a separate catalog; the existing file was preserved.`);
|
|
120
|
+
if (catalog?.apiOrigin !== undefined && new URL(catalog.apiOrigin).origin !== endpoint)
|
|
121
|
+
throw mismatch();
|
|
122
|
+
if (catalog !== undefined &&
|
|
123
|
+
catalog.apiOrigin === undefined &&
|
|
124
|
+
Object.keys(catalog.images).length === 0 &&
|
|
125
|
+
(catalog.public.length > 0 || catalog.delivery !== undefined))
|
|
126
|
+
throw new Error(`Catalog ${JSON.stringify(file)} has no verified API origin. Run storage receipts sync into a new --receipts file using the original API --endpoint, then review and replace this catalog. The existing file was preserved.`);
|
|
127
|
+
for (const [path, value] of Object.entries(catalog?.images ?? {})) {
|
|
128
|
+
const previous = receiptOriginSchema.safeParse(value);
|
|
129
|
+
if (!previous.success ||
|
|
130
|
+
(previous.data.apiOrigin === undefined && catalog?.apiOrigin === undefined))
|
|
131
|
+
throw new Error(`Catalog ${JSON.stringify(file)} has no verified API origin for ${JSON.stringify(path)}. Run storage receipts sync into a new --receipts file using the original API --endpoint, then review and replace this catalog. The existing file was preserved.`);
|
|
132
|
+
if (previous.data.apiOrigin !== undefined &&
|
|
133
|
+
new URL(previous.data.apiOrigin).origin !== endpoint)
|
|
134
|
+
throw mismatch();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Serializes CLI receipt writers and replaces a catalog only after the complete update succeeds.
|
|
139
|
+
* onCheckpoint observes a completed rename even if interruption or cleanup subsequently fails.
|
|
140
|
+
*/
|
|
141
|
+
export async function updateStorageReceipts(file, update, onCheckpoint) {
|
|
142
|
+
const lockPath = `${file}.lock`;
|
|
143
|
+
const temporary = join(dirname(file), `.${basename(file)}.${randomUUID()}.tmp`);
|
|
144
|
+
const typesFile = storageTypesPath(file);
|
|
145
|
+
if (basename(file) === 'transloadit-images.d.ts')
|
|
146
|
+
throw new Error('The catalog cannot use the generated declarations filename transloadit-images.d.ts');
|
|
147
|
+
const typesTemporary = `${temporary}.d.ts`;
|
|
148
|
+
const cancellation = new AbortController();
|
|
149
|
+
const cancel = () => cancellation.abort(new Error('Storage command canceled. Check Storage before retrying a write.'));
|
|
150
|
+
// The first interrupt is cooperative; a forced exit/crash still leaves a lock for inspection.
|
|
151
|
+
process.once('SIGINT', cancel);
|
|
152
|
+
process.once('SIGTERM', cancel);
|
|
153
|
+
let lock;
|
|
154
|
+
let typesLock;
|
|
155
|
+
let retainTemporary = false;
|
|
156
|
+
try {
|
|
157
|
+
lock = await open(lockPath, 'wx', 0o600).catch((error) => {
|
|
158
|
+
if (isErrnoException(error) && error.code === 'EEXIST') {
|
|
159
|
+
throw new Error(`The receipts file is locked by another storage store or receipts sync. Remove ${lockPath} only after confirming no writer is running.`, { cause: error });
|
|
160
|
+
}
|
|
161
|
+
throw error;
|
|
162
|
+
});
|
|
163
|
+
cancellation.signal.throwIfAborted();
|
|
164
|
+
// Different catalog filenames still share one ambient type-registration file.
|
|
165
|
+
typesLock = await open(`${typesFile}.lock`, 'wx', 0o600).catch((error) => {
|
|
166
|
+
throw new Error(`Generated declarations are locked: ${typesFile}. Wait for the other catalog writer.`, { cause: error });
|
|
167
|
+
});
|
|
168
|
+
const { catalog, mode } = await readReceipts(file);
|
|
169
|
+
const typesInfo = await lstat(typesFile).catch((error) => {
|
|
170
|
+
if (isErrnoException(error) && error.code === 'ENOENT')
|
|
171
|
+
return undefined;
|
|
172
|
+
throw error;
|
|
173
|
+
});
|
|
174
|
+
if (typesInfo !== undefined && !typesInfo.isFile())
|
|
175
|
+
throw new Error(`Expected a regular generated types file: ${typesFile}`);
|
|
176
|
+
if (typesInfo !== undefined &&
|
|
177
|
+
(await readFile(typesFile, 'utf8')).split(/\r?\n/, 1)[0] !== typesHeader)
|
|
178
|
+
throw new Error(`Refusing to overwrite handwritten declarations in ${typesFile}. Move them to a separate file before retrying.`);
|
|
179
|
+
if (typesInfo !== undefined) {
|
|
180
|
+
const existing = (await readFile(typesFile, 'utf8')).replaceAll('\r\n', '\n');
|
|
181
|
+
const owner = existing.split('\n')[1];
|
|
182
|
+
const expectedOwner = `// Catalog: ${JSON.stringify(basename(file))}`;
|
|
183
|
+
// Upgrade older generated files only when they exactly describe this existing catalog.
|
|
184
|
+
if (owner !== expectedOwner && !(catalog !== undefined && existing === catalogTypes(catalog)))
|
|
185
|
+
throw new Error(`Generated declarations in ${typesFile} belong to ${owner?.startsWith('// Catalog: ') ? owner.slice(12) : 'another catalog'}. Use --receipts in a separate directory; the active catalog was preserved.`);
|
|
186
|
+
}
|
|
187
|
+
const updated = await update(catalog, cancellation.signal);
|
|
188
|
+
// An explicit one-off workspace override must not mix two workspaces in one catalog.
|
|
189
|
+
if (updated === undefined) {
|
|
190
|
+
cancellation.signal.throwIfAborted();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (!storageCatalogSchema.safeParse(updated).success)
|
|
194
|
+
throw new Error('Cannot write an invalid Storage catalog; check its Workspace, public prefixes and delivery configuration.');
|
|
195
|
+
// Once a remote write returned a receipt, finish its atomic checkpoint even if interrupted.
|
|
196
|
+
// New catalogs are ordinary source files: let the kernel apply umask, without reading it.
|
|
197
|
+
await writeFile(temporary, `${JSON.stringify(updated, null, 2)}\n`, {
|
|
198
|
+
flag: 'wx',
|
|
199
|
+
mode: mode === undefined ? 0o666 : 0o600,
|
|
200
|
+
});
|
|
201
|
+
retainTemporary = true;
|
|
202
|
+
if (mode !== undefined)
|
|
203
|
+
await chmod(temporary, mode);
|
|
204
|
+
await writeFile(typesTemporary, catalogTypes(updated, file), { flag: 'wx', mode: 0o666 });
|
|
205
|
+
if (typesInfo !== undefined)
|
|
206
|
+
await chmod(typesTemporary, typesInfo.mode & 0o777);
|
|
207
|
+
await rename(temporary, file);
|
|
208
|
+
retainTemporary = false;
|
|
209
|
+
onCheckpoint?.();
|
|
210
|
+
// The catalog is the authoritative checkpoint. A failure replacing derived types must
|
|
211
|
+
// never discard a verified upload; sync can regenerate declarations without another write.
|
|
212
|
+
await rename(typesTemporary, typesFile).catch((error) => {
|
|
213
|
+
throw new Error(`Catalog saved, but cannot update ${typesFile}. Run storage receipts sync to regenerate types without re-uploading.`, { cause: error });
|
|
214
|
+
});
|
|
215
|
+
cancellation.signal.throwIfAborted();
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
if (retainTemporary)
|
|
219
|
+
throw new Error(`${ensureError(error).message}\nComplete catalog retained at ${JSON.stringify(temporary)}.`, { cause: error });
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
try {
|
|
224
|
+
if (typesLock !== undefined) {
|
|
225
|
+
await typesLock.close();
|
|
226
|
+
await rm(`${typesFile}.lock`, { force: true });
|
|
227
|
+
}
|
|
228
|
+
if (lock !== undefined) {
|
|
229
|
+
await lock.close();
|
|
230
|
+
await rm(lockPath, { force: true });
|
|
231
|
+
if (!retainTemporary)
|
|
232
|
+
await rm(temporary, { force: true });
|
|
233
|
+
await rm(typesTemporary, { force: true });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
process.off('SIGINT', cancel);
|
|
238
|
+
process.off('SIGTERM', cancel);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=storageReceipts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageReceipts.js","sourceRoot":"","sources":["../../src/cli/storageReceipts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Locate ordinary Next.js app directories without assuming the consumer's source layout. */
|
|
2
|
+
export declare function nextAppRoot(): '' | 'src/' | undefined;
|
|
3
|
+
/** Advice only: never execute or rewrite a consumer's Next config after a successful upload. */
|
|
4
|
+
export declare function storageImageConfigAdvice(): Promise<string>;
|
|
5
|
+
/** Private redirect delivery needs an application authorizer and key, not the CLI login key. */
|
|
6
|
+
export declare function storageImagePrivateAdvice(path: string, receipts?: string): string;
|
|
7
|
+
/** An empty-safe scaffold showing the first receipt in the initialized directory. */
|
|
8
|
+
export declare function storageImagePage(receiptsImport: string, prefix: string, receipts?: string): string;
|
|
9
|
+
/** Rendering-only variable names; values belong in the application's secret configuration. */
|
|
10
|
+
export declare function storageImageEnvBlock(publicOnly: boolean): string;
|
|
11
|
+
//# sourceMappingURL=storageSnippets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageSnippets.d.ts","sourceRoot":"","sources":["../../src/cli/storageSnippets.ts"],"names":[],"mappings":"AAKA,6FAA6F;AAC7F,wBAAgB,WAAW,IAAI,EAAE,GAAG,MAAM,GAAG,SAAS,CAIrD;AAED,gGAAgG;AAChG,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAYhE;AAED,gGAAgG;AAChG,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAOjF;AAUD,qFAAqF;AACrF,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAwCR;AAED,8FAA8F;AAC9F,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAEhE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { statSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { quoteCliArgument } from "./helpers.js";
|
|
4
|
+
/** Locate ordinary Next.js app directories without assuming the consumer's source layout. */
|
|
5
|
+
export function nextAppRoot() {
|
|
6
|
+
if (statSync('app', { throwIfNoEntry: false })?.isDirectory())
|
|
7
|
+
return '';
|
|
8
|
+
if (statSync('src/app', { throwIfNoEntry: false })?.isDirectory())
|
|
9
|
+
return 'src/';
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
/** Advice only: never execute or rewrite a consumer's Next config after a successful upload. */
|
|
13
|
+
export async function storageImageConfigAdvice() {
|
|
14
|
+
for (const file of ['next.config.ts', 'next.config.mjs', 'next.config.js']) {
|
|
15
|
+
// An unavailable optional hint must not turn a completed Storage write into a CLI failure.
|
|
16
|
+
const source = await readFile(file, 'utf8').catch(() => undefined);
|
|
17
|
+
if (source === undefined)
|
|
18
|
+
continue;
|
|
19
|
+
if (source.includes('withTransloaditImages'))
|
|
20
|
+
return '';
|
|
21
|
+
const commonJsAdvice = file.endsWith('.js')
|
|
22
|
+
? '\nFor CommonJS, rename next.config.js to next.config.mjs and convert require/module.exports to import/export before using this ESM example.'
|
|
23
|
+
: '';
|
|
24
|
+
return `\n${file} is not wrapped yet. Keep your existing config in nextConfig and wrap its export:${commonJsAdvice}\nimport { withTransloaditImages } from '@transloadit/viewer/next/config'\nexport default withTransloaditImages(nextConfig)`;
|
|
25
|
+
}
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
/** Private redirect delivery needs an application authorizer and key, not the CLI login key. */
|
|
29
|
+
export function storageImagePrivateAdvice(path, receipts) {
|
|
30
|
+
const prefix = path.slice(0, path.lastIndexOf('/') + 1);
|
|
31
|
+
if (prefix === '')
|
|
32
|
+
return '\nThis object is private. Configure per-object authorization explicitly, or store it under a directory to use image init --private. Set TRANSLOADIT_SMART_CDN_KEY/SECRET for rendering.';
|
|
33
|
+
const catalogOption = receipts === undefined ? '' : ` --receipts=${quoteCliArgument(receipts)}`;
|
|
34
|
+
// Stop option parsing explicitly: Storage paths are data, including names starting with a dash.
|
|
35
|
+
return `\nThis directory is private. Rendering needs transloadit.authorize.ts and ${nextAppRoot() ?? ''}app/api/storage-images/route.ts (npx transloadit image init --private${catalogOption} -- ${quoteCliArgument(prefix)}) and TRANSLOADIT_SMART_CDN_KEY/SECRET. Restart next dev after adding them.`;
|
|
36
|
+
}
|
|
37
|
+
function relativeImport(path) {
|
|
38
|
+
return path.startsWith('./') || path.startsWith('../') ? path : `./${path}`;
|
|
39
|
+
}
|
|
40
|
+
function sourceString(value) {
|
|
41
|
+
return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'").replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll('\u2028', '\\u2028').replaceAll('\u2029', '\\u2029')}'`;
|
|
42
|
+
}
|
|
43
|
+
/** An empty-safe scaffold showing the first receipt in the initialized directory. */
|
|
44
|
+
export function storageImagePage(receiptsImport, prefix, receipts) {
|
|
45
|
+
const catalogOption = receipts === undefined ? '' : ` --receipts=${quoteCliArgument(receipts)}`;
|
|
46
|
+
const command = `npx transloadit storage store${catalogOption}${prefix.startsWith('-') ? ' --' : ''} ./hero.jpg ${quoteCliArgument(`${prefix}hero.jpg`)}`;
|
|
47
|
+
return [
|
|
48
|
+
"import { Image } from '@transloadit/viewer/next'",
|
|
49
|
+
`import catalog from ${sourceString(relativeImport(receiptsImport))}`,
|
|
50
|
+
'',
|
|
51
|
+
'export default function Page() {',
|
|
52
|
+
` const path = Object.keys(catalog.images).find((path) => path.startsWith(${sourceString(prefix)}))`,
|
|
53
|
+
' if (path === undefined)',
|
|
54
|
+
' return (',
|
|
55
|
+
' <p>',
|
|
56
|
+
` Run <code>{${sourceString(command)}}</code> to add your`,
|
|
57
|
+
' first image.',
|
|
58
|
+
' </p>',
|
|
59
|
+
' )',
|
|
60
|
+
' // Object.keys only returns own catalog keys, including when the catalog is still empty.',
|
|
61
|
+
' const src = path as keyof typeof catalog.images',
|
|
62
|
+
' // Replace the filename-derived alt with a description, or an empty string if decorative.',
|
|
63
|
+
' const alt = path',
|
|
64
|
+
" .slice(path.lastIndexOf('/') + 1)",
|
|
65
|
+
" .replace(/\\.[^.]+$/, '')",
|
|
66
|
+
" .replaceAll(/[-_]+/g, ' ')",
|
|
67
|
+
' return (',
|
|
68
|
+
' <Image',
|
|
69
|
+
' storage',
|
|
70
|
+
' src={src}',
|
|
71
|
+
' alt={alt}',
|
|
72
|
+
' width={960}',
|
|
73
|
+
' preload',
|
|
74
|
+
' errorFallback={',
|
|
75
|
+
' <p role="status">',
|
|
76
|
+
' This image could not be loaded. Check the Storage path and delivery configuration.',
|
|
77
|
+
' </p>',
|
|
78
|
+
' }',
|
|
79
|
+
' />',
|
|
80
|
+
' )',
|
|
81
|
+
'}',
|
|
82
|
+
'',
|
|
83
|
+
].join('\n');
|
|
84
|
+
}
|
|
85
|
+
/** Rendering-only variable names; values belong in the application's secret configuration. */
|
|
86
|
+
export function storageImageEnvBlock(publicOnly) {
|
|
87
|
+
return publicOnly ? '' : 'TRANSLOADIT_KEY=\nTRANSLOADIT_SECRET=\n';
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=storageSnippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageSnippets.js","sourceRoot":"","sources":["../../src/cli/storageSnippets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,6FAA6F;AAC7F,MAAM,UAAU,WAAW;IACzB,IAAI,QAAQ,CAAC,KAAK,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE;QAAE,OAAO,EAAE,CAAA;IACxE,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE;QAAE,OAAO,MAAM,CAAA;IAChF,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,EAAE,CAAC;QAC3E,2FAA2F;QAC3F,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QAClE,IAAI,MAAM,KAAK,SAAS;YAAE,SAAQ;QAClC,IAAI,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAAE,OAAO,EAAE,CAAA;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzC,CAAC,CAAC,6IAA6I;YAC/I,CAAC,CAAC,EAAE,CAAA;QACN,OAAO,KAAK,IAAI,oFAAoF,cAAc,6HAA6H,CAAA;IACjP,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,yBAAyB,CAAC,IAAY,EAAE,QAAiB;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IACvD,IAAI,MAAM,KAAK,EAAE;QACf,OAAO,yLAAyL,CAAA;IAClM,MAAM,aAAa,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC/F,gGAAgG;IAChG,OAAO,6EAA6E,WAAW,EAAE,IAAI,EAAE,wEAAwE,aAAa,OAAO,gBAAgB,CAAC,MAAM,CAAC,6EAA6E,CAAA;AAC1S,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;AAC7E,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAA;AACrL,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,gBAAgB,CAC9B,cAAsB,EACtB,MAAc,EACd,QAAiB;IAEjB,MAAM,aAAa,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAA;IAC/F,MAAM,OAAO,GAAG,gCAAgC,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,eAAe,gBAAgB,CAAC,GAAG,MAAM,UAAU,CAAC,EAAE,CAAA;IACzJ,OAAO;QACL,kDAAkD;QAClD,uBAAuB,YAAY,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,EAAE;QACrE,EAAE;QACF,kCAAkC;QAClC,6EAA6E,YAAY,CAAC,MAAM,CAAC,IAAI;QACrG,2BAA2B;QAC3B,cAAc;QACd,WAAW;QACX,sBAAsB,YAAY,CAAC,OAAO,CAAC,sBAAsB;QACjE,sBAAsB;QACtB,YAAY;QACZ,OAAO;QACP,4FAA4F;QAC5F,mDAAmD;QACnD,6FAA6F;QAC7F,oBAAoB;QACpB,uCAAuC;QACvC,+BAA+B;QAC/B,gCAAgC;QAChC,YAAY;QACZ,YAAY;QACZ,eAAe;QACf,iBAAiB;QACjB,iBAAiB;QACjB,mBAAmB;QACnB,eAAe;QACf,uBAAuB;QACvB,2BAA2B;QAC3B,8FAA8F;QAC9F,cAAc;QACd,SAAS;QACT,QAAQ;QACR,KAAK;QACL,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,oBAAoB,CAAC,UAAmB;IACtD,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,yCAAyC,CAAA;AACpE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { StoredAsset } from './alphalib/types/storageAsset.ts';
|
|
2
|
+
import type { CreateAssemblyOptions, Transloadit } from './Transloadit.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Verified Storage metadata that can be saved and passed directly to an image renderer.
|
|
5
|
+
* Width and height reflect EXIF auto-orientation, matching Storage preview delivery.
|
|
6
|
+
*/
|
|
7
|
+
export interface StoredImageReceipt extends Readonly<StoredAsset> {
|
|
8
|
+
/** Present as true only when the locally decoded original has an alpha channel. */
|
|
9
|
+
readonly hasAlpha?: boolean;
|
|
10
|
+
readonly height: number;
|
|
11
|
+
readonly md5hash: string;
|
|
12
|
+
/** Optional base64 ThumbHash of the original pixels, for an inline blur placeholder. */
|
|
13
|
+
readonly thumbhash?: string;
|
|
14
|
+
readonly width: number;
|
|
15
|
+
}
|
|
16
|
+
/** One explicit destination, with the existing Assembly upload and polling controls. */
|
|
17
|
+
export interface StoreImageOptions extends Pick<CreateAssemblyOptions, 'chunkSize' | 'onAssemblyProgress' | 'onUploadProgress' | 'signal' | 'timeout'> {
|
|
18
|
+
/** Complete relative Storage filename. Directories and interpolation expressions are rejected. */
|
|
19
|
+
path: string;
|
|
20
|
+
/** Explicit opt-in replacement of an existing path; defaults to false. */
|
|
21
|
+
overwrite?: boolean;
|
|
22
|
+
/** Observe verified metadata. Not awaited; sync and async observer errors cannot undo a write. */
|
|
23
|
+
onReceipt?: (receipt: StoredImageReceipt, input: StoredImageExpectation, assemblyId: string | undefined) => void | Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/** Trusted upload facts used to correlate a stored result with an application-owned upload. */
|
|
26
|
+
export interface StoredImageExpectation {
|
|
27
|
+
path: string;
|
|
28
|
+
size: number;
|
|
29
|
+
md5hash: string;
|
|
30
|
+
}
|
|
31
|
+
/** Recovers one original's receipt without re-uploading or trusting notification payloads. */
|
|
32
|
+
export interface GetStoredImageReceiptOptions {
|
|
33
|
+
assemblyId: string;
|
|
34
|
+
expected: StoredImageExpectation;
|
|
35
|
+
}
|
|
36
|
+
/** Stores one original without overwriting; receipt validation occurs after the Storage write. */
|
|
37
|
+
export declare function storeImage(client: Transloadit, filePath: string, options: StoreImageOptions): Promise<StoredImageReceipt>;
|
|
38
|
+
/** Fetches authoritative Assembly status and applies the same validation as a local image store. */
|
|
39
|
+
export declare function getStoredImageReceipt(client: Transloadit, options: GetStoredImageReceiptOptions): Promise<StoredImageReceipt>;
|
|
40
|
+
//# sourceMappingURL=storageImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageImage.d.ts","sourceRoot":"","sources":["../src/storageImage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAY1E;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,QAAQ,CAAC,WAAW,CAAC;IAC/D,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,wFAAwF;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,wFAAwF;AACxF,MAAM,WAAW,iBACf,SAAQ,IAAI,CACV,qBAAqB,EACrB,WAAW,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,QAAQ,GAAG,SAAS,CAC/E;IACD,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kGAAkG;IAClG,SAAS,CAAC,EAAE,CACV,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,sBAAsB,EAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,KAC3B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED,+FAA+F;AAC/F,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,8FAA8F;AAC9F,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,sBAAsB,CAAA;CACjC;AAoED,kGAAkG;AAClG,wBAAsB,UAAU,CAC9B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAyE7B;AAED,oGAAoG;AACpG,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,kBAAkB,CAAC,CAU7B"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createReadStream } from 'node:fs';
|
|
3
|
+
import debug from 'debug';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { ApiError } from "./ApiError.js";
|
|
6
|
+
import { storedAssetSchema } from "./alphalib/types/storageAsset.js";
|
|
7
|
+
import InconsistentResponseError from "./InconsistentResponseError.js";
|
|
8
|
+
const positiveIntegerSchema = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
|
|
9
|
+
const receiptRequestSchema = z.object({
|
|
10
|
+
assemblyId: z.string().regex(/^[A-Za-z0-9_-]+$/),
|
|
11
|
+
expected: z.object({
|
|
12
|
+
path: z.string(),
|
|
13
|
+
size: positiveIntegerSchema,
|
|
14
|
+
md5hash: z.string().regex(/^[a-f0-9]{32}$/),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
const completedImageSchema = z.object({
|
|
18
|
+
ok: z.literal('ASSEMBLY_COMPLETED'),
|
|
19
|
+
results: z.object({
|
|
20
|
+
':original': z.tuple([
|
|
21
|
+
storedAssetSchema.extend({
|
|
22
|
+
md5hash: storedAssetSchema.shape.md5hash.unwrap(),
|
|
23
|
+
height: positiveIntegerSchema,
|
|
24
|
+
width: positiveIntegerSchema,
|
|
25
|
+
size: positiveIntegerSchema,
|
|
26
|
+
}),
|
|
27
|
+
]),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
function validateDestination(path) {
|
|
31
|
+
if (typeof path !== 'string' ||
|
|
32
|
+
path.trim() !== path ||
|
|
33
|
+
Buffer.byteLength(path) > 1024 ||
|
|
34
|
+
path.normalize('NFC') !== path ||
|
|
35
|
+
/[\p{Cc}\p{Cs}\\|]/u.test(path) ||
|
|
36
|
+
path.includes('${') ||
|
|
37
|
+
path.split('/').some((segment) => segment.trim() === '' || segment === '.' || segment === '..')) {
|
|
38
|
+
throw new TypeError('Storage path must be a complete relative filename without interpolation');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function imagePlaceholderMetadata(bytes) {
|
|
42
|
+
try {
|
|
43
|
+
const [{ default: sharp }, { rgbaToThumbHash }] = await Promise.all([
|
|
44
|
+
import('sharp'),
|
|
45
|
+
import('thumbhash'),
|
|
46
|
+
]);
|
|
47
|
+
const image = sharp(bytes, { limitInputPixels: 40_000_000 });
|
|
48
|
+
// Read original-channel metadata, not the alpha channel added for ThumbHash's RGBA input.
|
|
49
|
+
const { hasAlpha } = await image.metadata();
|
|
50
|
+
const { data, info } = await image
|
|
51
|
+
.autoOrient()
|
|
52
|
+
.resize(100, 100, { fit: 'inside', withoutEnlargement: true })
|
|
53
|
+
.ensureAlpha()
|
|
54
|
+
.raw()
|
|
55
|
+
.timeout({ seconds: 2 })
|
|
56
|
+
.toBuffer({ resolveWithObject: true });
|
|
57
|
+
return {
|
|
58
|
+
thumbhash: Buffer.from(rgbaToThumbHash(info.width, info.height, data)).toString('base64'),
|
|
59
|
+
...(hasAlpha ? { hasAlpha: true } : {}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// A locally unsupported/oversized image can still be stored and decoded by the origin.
|
|
64
|
+
debug('transloadit:warn')('Omitted optional ThumbHash: local image decoding was unavailable');
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Stores one original without overwriting; receipt validation occurs after the Storage write. */
|
|
69
|
+
export async function storeImage(client, filePath, options) {
|
|
70
|
+
const { path, chunkSize, onAssemblyProgress, onUploadProgress, onReceipt, overwrite, signal, timeout, } = options;
|
|
71
|
+
validateDestination(path);
|
|
72
|
+
if (overwrite !== undefined && typeof overwrite !== 'boolean')
|
|
73
|
+
throw new TypeError('overwrite must be a boolean');
|
|
74
|
+
signal?.throwIfAborted();
|
|
75
|
+
const checksum = createHash('md5');
|
|
76
|
+
// Reuse the checksum read, bounded independently of file size; uploads still stream from disk.
|
|
77
|
+
let thumbnailChunks = [];
|
|
78
|
+
let size = 0;
|
|
79
|
+
for await (const chunk of createReadStream(filePath, { signal })) {
|
|
80
|
+
checksum.update(chunk);
|
|
81
|
+
size += chunk.length;
|
|
82
|
+
if (size > 32 * 1024 * 1024)
|
|
83
|
+
thumbnailChunks = undefined;
|
|
84
|
+
else
|
|
85
|
+
thumbnailChunks?.push(chunk);
|
|
86
|
+
}
|
|
87
|
+
if (size === 0)
|
|
88
|
+
throw new Error('Cannot store an empty image');
|
|
89
|
+
const md5hash = checksum.digest('hex');
|
|
90
|
+
signal?.throwIfAborted();
|
|
91
|
+
const placeholder = thumbnailChunks === undefined
|
|
92
|
+
? undefined
|
|
93
|
+
: await imagePlaceholderMetadata(Buffer.concat(thumbnailChunks));
|
|
94
|
+
thumbnailChunks = undefined;
|
|
95
|
+
signal?.throwIfAborted();
|
|
96
|
+
const assembly = await client.createAssembly({
|
|
97
|
+
chunkSize,
|
|
98
|
+
files: { image: filePath },
|
|
99
|
+
onAssemblyProgress,
|
|
100
|
+
onUploadProgress,
|
|
101
|
+
params: {
|
|
102
|
+
steps: {
|
|
103
|
+
stored: {
|
|
104
|
+
robot: '/transloadit/store',
|
|
105
|
+
use: ':original',
|
|
106
|
+
path,
|
|
107
|
+
conflict_strategy: overwrite === true ? 'overwrite' : 'error',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
signal,
|
|
112
|
+
timeout,
|
|
113
|
+
waitForCompletion: true,
|
|
114
|
+
});
|
|
115
|
+
const input = { path, size, md5hash };
|
|
116
|
+
// API2 can watermark uploads before Robots run; this exact write's result describes stored bytes.
|
|
117
|
+
const receipt = validateReceipt(assembly, input, true);
|
|
118
|
+
// A watermark or other origin-side rewrite makes the local pixels the wrong placeholder.
|
|
119
|
+
const withPlaceholder = placeholder === undefined || receipt.md5hash !== md5hash || receipt.size !== size
|
|
120
|
+
? receipt
|
|
121
|
+
: { ...receipt, ...placeholder };
|
|
122
|
+
const observerFailed = () => {
|
|
123
|
+
debug('transloadit:warn')('Ignored onReceipt observer failure after a completed Storage write');
|
|
124
|
+
};
|
|
125
|
+
try {
|
|
126
|
+
// Neither a stalled observer nor its rejection may hide a successfully stored receipt.
|
|
127
|
+
void Promise.resolve(onReceipt?.({ ...withPlaceholder }, input, assembly.assembly_id)).catch(observerFailed);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
observerFailed();
|
|
131
|
+
}
|
|
132
|
+
return withPlaceholder;
|
|
133
|
+
}
|
|
134
|
+
/** Fetches authoritative Assembly status and applies the same validation as a local image store. */
|
|
135
|
+
export async function getStoredImageReceipt(client, options) {
|
|
136
|
+
const { assemblyId, expected } = receiptRequestSchema.parse(options);
|
|
137
|
+
validateDestination(expected.path);
|
|
138
|
+
const assembly = await client.getAssembly(assemblyId);
|
|
139
|
+
if (assembly.assembly_id !== assemblyId) {
|
|
140
|
+
throw new InconsistentResponseError('The response did not match the requested Assembly', {
|
|
141
|
+
cause: { assemblyId },
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return validateReceipt(assembly, expected);
|
|
145
|
+
}
|
|
146
|
+
function validateReceipt(assembly, expected, acceptTransformed = false) {
|
|
147
|
+
const { path, size, md5hash } = expected;
|
|
148
|
+
if (typeof assembly.error === 'string')
|
|
149
|
+
throw new ApiError({ body: assembly });
|
|
150
|
+
if (assembly.ok === 'ASSEMBLY_CANCELED') {
|
|
151
|
+
throw new InconsistentResponseError('The Storage Assembly ended with ASSEMBLY_CANCELED', {
|
|
152
|
+
cause: { assemblyId: assembly.assembly_id },
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (assembly.ok === 'ASSEMBLY_UPLOADING' ||
|
|
156
|
+
assembly.ok === 'ASSEMBLY_EXECUTING' ||
|
|
157
|
+
assembly.ok === 'ASSEMBLY_REPLAYING') {
|
|
158
|
+
throw new InconsistentResponseError(`The Storage Assembly is not complete (${assembly.ok})`, {
|
|
159
|
+
cause: { assemblyId: assembly.assembly_id },
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const parsed = completedImageSchema.safeParse(assembly);
|
|
163
|
+
const result = parsed.success ? parsed.data.results[':original'][0] : undefined;
|
|
164
|
+
const originals = assembly.results?.[':original'];
|
|
165
|
+
const receiptCheck = {
|
|
166
|
+
originalCount: Array.isArray(originals) ? originals.length : 0,
|
|
167
|
+
metadataValid: parsed.success,
|
|
168
|
+
pathMatches: result === undefined ? undefined : result.path === path,
|
|
169
|
+
sizeMatches: result === undefined ? undefined : result.size === size,
|
|
170
|
+
md5Matches: result === undefined ? undefined : result.md5hash === md5hash,
|
|
171
|
+
};
|
|
172
|
+
if (result === undefined ||
|
|
173
|
+
result.path !== path ||
|
|
174
|
+
(!acceptTransformed && (!receiptCheck.sizeMatches || !receiptCheck.md5Matches))) {
|
|
175
|
+
throw new InconsistentResponseError('The Assembly did not return a matching Storage image receipt', {
|
|
176
|
+
cause: { assemblyId: assembly.assembly_id, receiptCheck },
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=storageImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storageImage.js","sourceRoot":"","sources":["../src/storageImage.ts"],"names":[],"mappings":"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"}
|