diff --git a/.cursor/rules/coding-style.mdc b/.cursor/rules/coding-style.mdc index 0e26fb6..5fc81a2 100644 --- a/.cursor/rules/coding-style.mdc +++ b/.cursor/rules/coding-style.mdc @@ -29,3 +29,4 @@ Coding style: - Use descriptive names: PascalCase for components/types, camelCase for variables/methods/schemas - Alphabetize imports, group by source type (built-in/external/internal) - Favor US English over UK English, so `summarizeError` over `summarise Error` +- Favor `.replaceAll('a', 'b)` over `.replace(/a/g, 'b')` or `.replace(new RegExp('a', 'g'), 'b')` when the only need for regeses was replacing all strings. That's usually both easier to read and more performant. diff --git a/package.json b/package.json index 16aa9c5..88b4fa4 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@aws-sdk/client-s3": "^3.891.0", "@aws-sdk/s3-request-presigner": "^3.891.0", + "@transloadit/sev-logger": "^0.0.15", "debug": "^4.4.3", "form-data": "^4.0.4", "got": "14.4.9", diff --git a/src/alphalib/lib/nativeGlobby.ts b/src/alphalib/lib/nativeGlobby.ts new file mode 100644 index 0000000..61d0dcd --- /dev/null +++ b/src/alphalib/lib/nativeGlobby.ts @@ -0,0 +1,244 @@ +import type { GlobOptionsWithoutFileTypes } from 'node:fs' +import * as fs from 'node:fs' +import { glob as fsGlob, stat as statAsync } from 'node:fs/promises' +import path from 'node:path' + +type PatternInput = string | readonly string[] +const { globSync: fsGlobSync } = fs + +export interface NativeGlobbyOptions { + cwd?: string + absolute?: boolean + onlyFiles?: boolean + ignore?: readonly string[] +} + +interface NormalizedOptions { + cwd?: string + absolute: boolean + onlyFiles: boolean + ignore?: readonly string[] +} + +interface Candidate { + rawPath: string + absolutePath: string +} + +const normalizeSlashes = (value: string) => value.replace(/\\/g, '/') + +const toAbsolutePath = (rawPath: string, cwd?: string): string => { + if (path.isAbsolute(rawPath)) { + return rawPath + } + if (cwd) { + return path.join(cwd, rawPath) + } + return path.resolve(rawPath) +} + +const normalizeOptions = (options: NativeGlobbyOptions = {}): NormalizedOptions => ({ + cwd: options.cwd ? path.resolve(options.cwd) : undefined, + absolute: options.absolute ?? false, + onlyFiles: options.onlyFiles ?? true, + ignore: options.ignore && options.ignore.length > 0 ? options.ignore : undefined, +}) + +const hasGlobMagic = (pattern: string) => /[*?[\]{}()!]/.test(pattern) + +const expandPatternAsync = async (pattern: string, options: NormalizedOptions) => { + if (hasGlobMagic(pattern)) { + return [pattern] + } + + try { + const absolute = toAbsolutePath(pattern, options.cwd) + const stats = await statAsync(absolute) + if (stats.isDirectory()) { + const expanded = normalizeSlashes(path.join(pattern, '**/*')) + return [expanded] + } + } catch { + // ignore missing paths; fall back to original pattern + } + + return [pattern] +} + +const expandPatternSync = (pattern: string, options: NormalizedOptions) => { + if (hasGlobMagic(pattern)) { + return [pattern] + } + + try { + const absolute = toAbsolutePath(pattern, options.cwd) + const stats = fs.statSync(absolute) + if (stats.isDirectory()) { + const expanded = normalizeSlashes(path.join(pattern, '**/*')) + return [expanded] + } + } catch { + // ignore missing paths; fall back to original pattern + } + + return [pattern] +} + +const splitPatterns = (patterns: PatternInput) => { + const list = Array.isArray(patterns) ? patterns : [patterns] + const positive: string[] = [] + const negative: string[] = [] + + for (const pattern of list) { + if (pattern.startsWith('!')) { + const negated = pattern.slice(1) + if (negated) { + negative.push(negated) + } + } else { + positive.push(pattern) + } + } + + return { positive, negative } +} + +const toGlobOptions = (options: NormalizedOptions): GlobOptionsWithoutFileTypes => { + const globOptions: GlobOptionsWithoutFileTypes = { withFileTypes: false } + if (options.cwd) { + globOptions.cwd = options.cwd + } + if (options.ignore) { + // Node's glob implementation uses `exclude` for ignore patterns + globOptions.exclude = options.ignore + } + return globOptions +} + +const filterFilesAsync = async (candidates: Candidate[], requireFiles: boolean) => { + if (!requireFiles) { + return candidates + } + + const filtered = await Promise.all( + candidates.map(async (candidate) => { + try { + const stats = await statAsync(candidate.absolutePath) + return stats.isFile() ? candidate : null + } catch { + return null + } + }), + ) + + return filtered.filter(Boolean) as Candidate[] +} + +const filterFilesSync = (candidates: Candidate[], requireFiles: boolean) => { + if (!requireFiles) { + return candidates + } + + const filtered: Candidate[] = [] + for (const candidate of candidates) { + try { + const stats = fs.statSync(candidate.absolutePath) + if (stats.isFile()) { + filtered.push(candidate) + } + } catch { + // Ignore files that cannot be stat'ed + } + } + return filtered +} + +const formatResult = (candidate: Candidate, options: NormalizedOptions) => { + const output = options.absolute ? candidate.absolutePath : candidate.rawPath + return normalizeSlashes(output) +} + +const collectMatchesAsync = async (pattern: string, options: NormalizedOptions) => { + const matches: Candidate[] = [] + for await (const match of fsGlob(pattern, toGlobOptions(options))) { + matches.push({ + rawPath: match as string, + absolutePath: toAbsolutePath(match as string, options.cwd), + }) + } + const filtered = await filterFilesAsync(matches, options.onlyFiles) + return filtered.map((candidate) => formatResult(candidate, options)) +} + +const collectMatchesSync = (pattern: string, options: NormalizedOptions) => { + const matches = (fsGlobSync(pattern, toGlobOptions(options)) as string[]).map((match) => ({ + rawPath: match, + absolutePath: toAbsolutePath(match, options.cwd), + })) + const filtered = filterFilesSync(matches, options.onlyFiles) + return filtered.map((candidate) => formatResult(candidate, options)) +} + +type GlobbyLike = { + (patterns: PatternInput, options?: NativeGlobbyOptions): Promise + sync(patterns: PatternInput, options?: NativeGlobbyOptions): string[] +} + +export const nativeGlobby: GlobbyLike = Object.assign( + async (patterns: PatternInput, options?: NativeGlobbyOptions) => { + const normalized = normalizeOptions(options) + const { positive, negative } = splitPatterns(patterns) + const expandedPositives = ( + await Promise.all(positive.map((pattern) => expandPatternAsync(pattern, normalized))) + ).flat() + const expandedNegatives = ( + await Promise.all(negative.map((pattern) => expandPatternAsync(pattern, normalized))) + ).flat() + const results = new Set() + + for (const pattern of expandedPositives) { + const matches = await collectMatchesAsync(pattern, normalized) + for (const match of matches) { + results.add(match) + } + } + + for (const pattern of expandedNegatives) { + const matches = await collectMatchesAsync(pattern, normalized) + for (const match of matches) { + results.delete(match) + } + } + + return Array.from(results) + }, + { + sync(patterns: PatternInput, options?: NativeGlobbyOptions) { + const normalized = normalizeOptions(options) + const { positive, negative } = splitPatterns(patterns) + const expandedPositives = positive.flatMap((pattern) => + expandPatternSync(pattern, normalized), + ) + const expandedNegatives = negative.flatMap((pattern) => + expandPatternSync(pattern, normalized), + ) + const results = new Set() + + for (const pattern of expandedPositives) { + const matches = collectMatchesSync(pattern, normalized) + for (const match of matches) { + results.add(match) + } + } + + for (const pattern of expandedNegatives) { + const matches = collectMatchesSync(pattern, normalized) + for (const match of matches) { + results.delete(match) + } + } + + return Array.from(results) + }, + }, +) diff --git a/src/alphalib/mcache.ts b/src/alphalib/mcache.ts new file mode 100644 index 0000000..0bd0c45 --- /dev/null +++ b/src/alphalib/mcache.ts @@ -0,0 +1,184 @@ +import type { SevLogger } from '@transloadit/sev-logger' +import type { Schema } from 'zod' + +export interface McacheOpts { + ttlMs?: number + zodSchema?: Schema + logger?: SevLogger + /** + * Maximum number of entries in the cache. When exceeded, oldest entries are removed. + * Defaults to 10,000 entries. + */ + maxSize?: number + /** + * Custom key generator function. If not provided, uses JSON.stringify. + */ + keyFn?: (...args: unknown[]) => string +} + +interface CacheEntry { + value: T + timestamp: number +} + +/** + * Memory cache abstraction to help cache function results in-process. + * + * Example: + * + * const cache = new Mcache({ ttlMs: 1000 * 60 * 10 }) + * + * async function fetchInstances(region: string): Promise { + * return cache.get(region, async () => { + * // Do work, e.g. fetch instances from AWS + * return await this._fetchInstances(region) + * }) + * } + */ +export class Mcache { + #cache: Map> + #opts: Required, 'logger' | 'zodSchema' | 'keyFn'>> & + Pick, 'logger' | 'zodSchema' | 'keyFn'> + + constructor(opts: McacheOpts = {}) { + this.#cache = new Map() + this.#opts = { + ttlMs: opts.ttlMs ?? Number.POSITIVE_INFINITY, + maxSize: opts.maxSize ?? 10_000, + zodSchema: opts.zodSchema, + logger: opts.logger, + keyFn: opts.keyFn, + } + } + + /** + * Get a value from cache, or compute it using the provided function. + * The cache key is generated from the args using JSON.stringify by default, + * or using the custom keyFn if provided. + */ + async get(producer: () => Promise | T, ...args: unknown[]): Promise { + const key = this.#opts.keyFn ? this.#opts.keyFn(...args) : JSON.stringify(args) + const cached = this.#cache.get(key) + + if (cached) { + const age = Date.now() - cached.timestamp + if (age <= this.#opts.ttlMs || this.#opts.ttlMs === Number.POSITIVE_INFINITY) { + this.#opts.logger?.debug(`Cache hit for key ${key} (age: ${age}ms)`) + return cached.value + } + + this.#opts.logger?.debug( + `Cache expired for key ${key} (age: ${age}ms > ${this.#opts.ttlMs}ms)`, + ) + this.#cache.delete(key) + } + + this.#opts.logger?.debug(`Cache miss for key ${key}, computing value`) + const value = await producer() + + // Validate if schema provided + if (this.#opts.zodSchema) { + this.#opts.zodSchema.parse(value) + } + + this.#set(key, value) + return value + } + + /** + * Set a value in the cache directly. + */ + set(value: T, ...args: unknown[]): void { + const key = this.#opts.keyFn ? this.#opts.keyFn(...args) : JSON.stringify(args) + + // Validate if schema provided + if (this.#opts.zodSchema) { + this.#opts.zodSchema.parse(value) + } + + this.#set(key, value) + } + + /** + * Check if a key exists in cache and is not expired. + */ + has(...args: unknown[]): boolean { + const key = this.#opts.keyFn ? this.#opts.keyFn(...args) : JSON.stringify(args) + const cached = this.#cache.get(key) + + if (!cached) { + return false + } + + const age = Date.now() - cached.timestamp + if (age > this.#opts.ttlMs && this.#opts.ttlMs !== Number.POSITIVE_INFINITY) { + this.#cache.delete(key) + return false + } + + return true + } + + /** + * Clear all entries from the cache. + */ + clear(): void { + this.#cache.clear() + } + + /** + * Delete a specific entry from the cache. + */ + delete(...args: unknown[]): boolean { + const key = this.#opts.keyFn ? this.#opts.keyFn(...args) : JSON.stringify(args) + return this.#cache.delete(key) + } + + /** + * Get the current size of the cache. + */ + get size(): number { + return this.#cache.size + } + + /** + * Clean up expired entries and enforce size limit. + */ + cleanup(): void { + const now = Date.now() + + // Remove expired entries + if (this.#opts.ttlMs !== Number.POSITIVE_INFINITY) { + for (const [key, entry] of this.#cache.entries()) { + if (now - entry.timestamp > this.#opts.ttlMs) { + this.#cache.delete(key) + } + } + } + + // Enforce size limit by removing oldest entries + if (this.#cache.size > this.#opts.maxSize) { + const entries = Array.from(this.#cache.entries()) + entries.sort((a, b) => a[1].timestamp - b[1].timestamp) + const toRemove = entries.slice(0, this.#cache.size - this.#opts.maxSize) + for (const [key] of toRemove) { + this.#cache.delete(key) + } + this.#opts.logger?.debug( + `Cache size limit reached, removed ${toRemove.length} oldest entries`, + ) + } + } + + #set(key: string, value: T): void { + this.#cache.set(key, { + value, + timestamp: Date.now(), + }) + + // Trigger cleanup if we're over size limit + if (this.#cache.size > this.#opts.maxSize) { + this.cleanup() + } + } +} diff --git a/src/alphalib/types/robots/_instructions-primitives.ts b/src/alphalib/types/robots/_instructions-primitives.ts index 9231eb8..166738e 100644 --- a/src/alphalib/types/robots/_instructions-primitives.ts +++ b/src/alphalib/types/robots/_instructions-primitives.ts @@ -118,6 +118,7 @@ export const robotMetaSchema = z.object({ trackOutputFileSize: z.boolean().optional(), isInternal: z.boolean(), numDaemons: z.number().optional(), + stage: z.enum(['alpha', 'beta', 'ga', 'deprecated', 'removed']), importRanges: z.array(z.string()).optional(), extraChargeForImageResize: z.number().optional(), @@ -473,6 +474,20 @@ example, will happily ignore input images. With the \`force_accept\` parameter set to \`true\`, you can force Robots to accept all files thrown at them. This will typically lead to errors and should only be used for debugging or combatting edge cases. +`), + + ignore_errors: z + .union([z.boolean(), z.array(z.enum(['meta', 'execute']))]) + .transform((value) => (value === true ? ['meta', 'execute'] : value === false ? [] : value)) + .default([]) + .describe(` +Ignore errors during specific phases of processing. + +Setting this to \`["meta"]\` will cause the Robot to ignore errors during metadata extraction. + +Setting this to \`["execute"]\` will cause the Robot to ignore errors during the main execution phase. + +Setting this to \`true\` is equivalent to \`["meta", "execute"]\` and will ignore errors in both phases. `), }) .strict() @@ -1190,8 +1205,10 @@ export const robotImport = z 'Custom name for the imported file(s). By default file names are derived from the source.', ), ignore_errors: z - .union([z.boolean(), z.array(z.enum(['meta', 'import']))]) - .transform((value) => (value === true ? ['meta', 'import'] : value === false ? [] : value)) + .union([z.boolean(), z.array(z.enum(['meta', 'import', 'execute']))]) + .transform((value) => + value === true ? ['meta', 'import', 'execute'] : value === false ? [] : value, + ) .default([]), }) .strict() diff --git a/src/alphalib/types/robots/assembly-savejson.ts b/src/alphalib/types/robots/assembly-savejson.ts index 59c9038..9942824 100644 --- a/src/alphalib/types/robots/assembly-savejson.ts +++ b/src/alphalib/types/robots/assembly-savejson.ts @@ -10,6 +10,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, trackOutputFileSize: false, isInternal: true, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/audio-artwork.ts b/src/alphalib/types/robots/audio-artwork.ts index f5579e7..e57096f 100644 --- a/src/alphalib/types/robots/audio-artwork.ts +++ b/src/alphalib/types/robots/audio-artwork.ts @@ -45,6 +45,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAudioArtworkInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/audio-concat.ts b/src/alphalib/types/robots/audio-concat.ts index 7512573..2d22337 100644 --- a/src/alphalib/types/robots/audio-concat.ts +++ b/src/alphalib/types/robots/audio-concat.ts @@ -66,6 +66,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAudioConcatInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/audio-encode.ts b/src/alphalib/types/robots/audio-encode.ts index a037daa..2476cee 100644 --- a/src/alphalib/types/robots/audio-encode.ts +++ b/src/alphalib/types/robots/audio-encode.ts @@ -48,6 +48,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: false, trackOutputFileSize: true, isInternal: false, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/audio-loop.ts b/src/alphalib/types/robots/audio-loop.ts index c429a88..d0f4b87 100644 --- a/src/alphalib/types/robots/audio-loop.ts +++ b/src/alphalib/types/robots/audio-loop.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAudioLoopInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/audio-merge.ts b/src/alphalib/types/robots/audio-merge.ts index 6be7fd8..e105954 100644 --- a/src/alphalib/types/robots/audio-merge.ts +++ b/src/alphalib/types/robots/audio-merge.ts @@ -67,6 +67,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAudioMergeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/audio-waveform.ts b/src/alphalib/types/robots/audio-waveform.ts index f5de78f..2fe5e37 100644 --- a/src/alphalib/types/robots/audio-waveform.ts +++ b/src/alphalib/types/robots/audio-waveform.ts @@ -56,6 +56,7 @@ Here is an example waveform image: trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAudioWaveformInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/azure-import.ts b/src/alphalib/types/robots/azure-import.ts index 197a615..806277d 100644 --- a/src/alphalib/types/robots/azure-import.ts +++ b/src/alphalib/types/robots/azure-import.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotAzureImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/azure-store.ts b/src/alphalib/types/robots/azure-store.ts index 25788c0..dcb1e67 100644 --- a/src/alphalib/types/robots/azure-store.ts +++ b/src/alphalib/types/robots/azure-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotAzureStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/backblaze-import.ts b/src/alphalib/types/robots/backblaze-import.ts index 6225053..1062f46 100644 --- a/src/alphalib/types/robots/backblaze-import.ts +++ b/src/alphalib/types/robots/backblaze-import.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotBackblazeImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/backblaze-store.ts b/src/alphalib/types/robots/backblaze-store.ts index c1a3a9a..84bbd13 100644 --- a/src/alphalib/types/robots/backblaze-store.ts +++ b/src/alphalib/types/robots/backblaze-store.ts @@ -44,6 +44,7 @@ Your Backblaze buckets need to have the \`listBuckets\` (to obtain a bucket ID f trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotBackblazeStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/cloudfiles-import.ts b/src/alphalib/types/robots/cloudfiles-import.ts index e5d9efa..3f38051 100644 --- a/src/alphalib/types/robots/cloudfiles-import.ts +++ b/src/alphalib/types/robots/cloudfiles-import.ts @@ -48,6 +48,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotCloudfilesImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/cloudfiles-store.ts b/src/alphalib/types/robots/cloudfiles-store.ts index 384ee17..eec34b6 100644 --- a/src/alphalib/types/robots/cloudfiles-store.ts +++ b/src/alphalib/types/robots/cloudfiles-store.ts @@ -53,6 +53,7 @@ The storage container URL for this file is always available via \`file.meta.stor trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotCloudfilesStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/cloudflare-import.ts b/src/alphalib/types/robots/cloudflare-import.ts index 73626b9..3ac9036 100644 --- a/src/alphalib/types/robots/cloudflare-import.ts +++ b/src/alphalib/types/robots/cloudflare-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotCloudflareImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/cloudflare-store.ts b/src/alphalib/types/robots/cloudflare-store.ts index 8268830..905ba30 100644 --- a/src/alphalib/types/robots/cloudflare-store.ts +++ b/src/alphalib/types/robots/cloudflare-store.ts @@ -47,6 +47,7 @@ The URL to the result file will be returned in the Assembly Status JSONRobot also detects and handles any of the following before evalu For security reasons, archives that contain symlinks to outside the archived dir, will error out the Assembly. Decompressing password-protected archives (encrypted archives) is currently not fully supported but will not cause an Assembly to fail. `), ignore_errors: z - .union([z.boolean(), z.array(z.enum(['meta']))]) - .transform((ignoreErrors): 'meta'[] => - ignoreErrors === true ? ['meta'] : ignoreErrors === false ? [] : ignoreErrors, + .union([z.boolean(), z.array(z.enum(['meta', 'execute']))]) + .transform((ignoreErrors): ('meta' | 'execute')[] => + ignoreErrors === true ? ['meta', 'execute'] : ignoreErrors === false ? [] : ignoreErrors, ) .default([]) .describe(` diff --git a/src/alphalib/types/robots/file-filter.ts b/src/alphalib/types/robots/file-filter.ts index 2256cc4..0bf6f8c 100644 --- a/src/alphalib/types/robots/file-filter.ts +++ b/src/alphalib/types/robots/file-filter.ts @@ -46,6 +46,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileFilterInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-hash.ts b/src/alphalib/types/robots/file-hash.ts index fbef86f..50058e6 100644 --- a/src/alphalib/types/robots/file-hash.ts +++ b/src/alphalib/types/robots/file-hash.ts @@ -36,6 +36,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileHashInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-preview.ts b/src/alphalib/types/robots/file-preview.ts index f960752..a430722 100644 --- a/src/alphalib/types/robots/file-preview.ts +++ b/src/alphalib/types/robots/file-preview.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { importRanges: ['0-19999999', '-1000000'], isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'beta', } export const robotFilePreviewInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-read.ts b/src/alphalib/types/robots/file-read.ts index 71aada5..4fabd6c 100644 --- a/src/alphalib/types/robots/file-read.ts +++ b/src/alphalib/types/robots/file-read.ts @@ -27,6 +27,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileReadInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-serve.ts b/src/alphalib/types/robots/file-serve.ts index 322ece4..7c4e2a6 100644 --- a/src/alphalib/types/robots/file-serve.ts +++ b/src/alphalib/types/robots/file-serve.ts @@ -27,6 +27,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, trackOutputFileSize: false, isInternal: false, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/file-verify.ts b/src/alphalib/types/robots/file-verify.ts index aa6d64e..15b5590 100644 --- a/src/alphalib/types/robots/file-verify.ts +++ b/src/alphalib/types/robots/file-verify.ts @@ -41,6 +41,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileVerifyInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-virusscan.ts b/src/alphalib/types/robots/file-virusscan.ts index 72fded7..11e7d88 100644 --- a/src/alphalib/types/robots/file-virusscan.ts +++ b/src/alphalib/types/robots/file-virusscan.ts @@ -46,6 +46,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileVirusscanInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/file-watermark.ts b/src/alphalib/types/robots/file-watermark.ts index 01bd337..70e03dd 100644 --- a/src/alphalib/types/robots/file-watermark.ts +++ b/src/alphalib/types/robots/file-watermark.ts @@ -12,6 +12,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFileWatermarkInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/ftp-import.ts b/src/alphalib/types/robots/ftp-import.ts index 56b515e..5791c33 100644 --- a/src/alphalib/types/robots/ftp-import.ts +++ b/src/alphalib/types/robots/ftp-import.ts @@ -45,6 +45,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotFtpImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/ftp-store.ts b/src/alphalib/types/robots/ftp-store.ts index 5bcf26e..85c3377 100644 --- a/src/alphalib/types/robots/ftp-store.ts +++ b/src/alphalib/types/robots/ftp-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotFtpStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/google-import.ts b/src/alphalib/types/robots/google-import.ts index 5661ce1..b031fbd 100644 --- a/src/alphalib/types/robots/google-import.ts +++ b/src/alphalib/types/robots/google-import.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotGoogleImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/google-store.ts b/src/alphalib/types/robots/google-store.ts index 8a323bb..9101626 100644 --- a/src/alphalib/types/robots/google-store.ts +++ b/src/alphalib/types/robots/google-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotGoogleStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/html-convert.ts b/src/alphalib/types/robots/html-convert.ts index accf4ef..2960a07 100644 --- a/src/alphalib/types/robots/html-convert.ts +++ b/src/alphalib/types/robots/html-convert.ts @@ -44,6 +44,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotHtmlConvertInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/http-import.ts b/src/alphalib/types/robots/http-import.ts index 498d6bf..1dec331 100644 --- a/src/alphalib/types/robots/http-import.ts +++ b/src/alphalib/types/robots/http-import.ts @@ -41,6 +41,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotHttpImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-bgremove.ts b/src/alphalib/types/robots/image-bgremove.ts index 0c5276f..522fd1a 100644 --- a/src/alphalib/types/robots/image-bgremove.ts +++ b/src/alphalib/types/robots/image-bgremove.ts @@ -37,6 +37,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageBgremoveInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-describe.ts b/src/alphalib/types/robots/image-describe.ts index 3f62b3f..d6a618c 100644 --- a/src/alphalib/types/robots/image-describe.ts +++ b/src/alphalib/types/robots/image-describe.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageDescribeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-facedetect.ts b/src/alphalib/types/robots/image-facedetect.ts index ad99ab8..fad9a02 100644 --- a/src/alphalib/types/robots/image-facedetect.ts +++ b/src/alphalib/types/robots/image-facedetect.ts @@ -47,6 +47,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageFacedetectInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-generate.ts b/src/alphalib/types/robots/image-generate.ts index 1a81d3c..7aea1b3 100644 --- a/src/alphalib/types/robots/image-generate.ts +++ b/src/alphalib/types/robots/image-generate.ts @@ -27,6 +27,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageGenerateInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-merge.ts b/src/alphalib/types/robots/image-merge.ts index 2b9748f..535d05b 100644 --- a/src/alphalib/types/robots/image-merge.ts +++ b/src/alphalib/types/robots/image-merge.ts @@ -46,6 +46,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageMergeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-ocr.ts b/src/alphalib/types/robots/image-ocr.ts index 78eb984..e4d4a86 100644 --- a/src/alphalib/types/robots/image-ocr.ts +++ b/src/alphalib/types/robots/image-ocr.ts @@ -49,6 +49,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageOcrInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-optimize.ts b/src/alphalib/types/robots/image-optimize.ts index fe8c1cb..f4d027c 100644 --- a/src/alphalib/types/robots/image-optimize.ts +++ b/src/alphalib/types/robots/image-optimize.ts @@ -41,6 +41,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotImageOptimizeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/image-resize.ts b/src/alphalib/types/robots/image-resize.ts index 0945b5e..ff632d2 100644 --- a/src/alphalib/types/robots/image-resize.ts +++ b/src/alphalib/types/robots/image-resize.ts @@ -53,6 +53,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const oneTextSchema = z.object({ @@ -479,6 +480,32 @@ For the \`"min_fit"\` resize strategy, the watermark is scaled so that the short For the \`"stretch"\` resize strategy, the watermark is stretched (meaning, it is resized without keeping its aspect ratio in mind) so that both sides take up 25% of the corresponding image side. Since our image is 800×800 pixels, for a watermark size of 25% the watermark would be resized to 200×200 pixels. Its height would appear stretched, because keeping the aspect ratio in mind it would be resized to 200×150 pixels instead. For the \`"area"\` resize strategy, the watermark is resized (keeping its aspect ratio in check) so that it covers \`"xx%"\` of the image's surface area. The value from \`watermark_size\` is used for the percentage area size. +`), + watermark_opacity: z + .number() + .min(0) + .max(1) + .default(1.0) + .describe(` +The opacity of the watermark, where \`0.0\` is fully transparent and \`1.0\` is fully opaque. + +For example, a value of \`0.5\` means the watermark will be 50% transparent, allowing the underlying image to show through. This is useful for subtle branding or when you want the watermark to be less obtrusive. +`), + watermark_repeat_x: z + .boolean() + .default(false) + .describe(` +When set to \`true\`, the watermark will be repeated horizontally across the entire width of the image. + +This is useful for creating tiled watermark patterns that cover the full image and make it more difficult to crop out the watermark. +`), + watermark_repeat_y: z + .boolean() + .default(false) + .describe(` +When set to \`true\`, the watermark will be repeated vertically across the entire height of the image. + +This is useful for creating tiled watermark patterns that cover the full image. Can be combined with \`watermark_repeat_x\` to tile in both directions. `), text: z .union([ diff --git a/src/alphalib/types/robots/meta-read.ts b/src/alphalib/types/robots/meta-read.ts index 3de1dcd..544c578 100644 --- a/src/alphalib/types/robots/meta-read.ts +++ b/src/alphalib/types/robots/meta-read.ts @@ -10,6 +10,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, trackOutputFileSize: false, isInternal: true, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/meta-write.ts b/src/alphalib/types/robots/meta-write.ts index 09871ad..eca0cfc 100644 --- a/src/alphalib/types/robots/meta-write.ts +++ b/src/alphalib/types/robots/meta-write.ts @@ -42,6 +42,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotMetaWriteInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/minio-import.ts b/src/alphalib/types/robots/minio-import.ts index 58d0fd5..617f699 100644 --- a/src/alphalib/types/robots/minio-import.ts +++ b/src/alphalib/types/robots/minio-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotMinioImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/minio-store.ts b/src/alphalib/types/robots/minio-store.ts index 5e05a71..6003f60 100644 --- a/src/alphalib/types/robots/minio-store.ts +++ b/src/alphalib/types/robots/minio-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotMinioStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/progress-simulate.ts b/src/alphalib/types/robots/progress-simulate.ts index 70f5430..350f2bc 100644 --- a/src/alphalib/types/robots/progress-simulate.ts +++ b/src/alphalib/types/robots/progress-simulate.ts @@ -11,6 +11,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: false, trackOutputFileSize: true, isInternal: true, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/s3-import.ts b/src/alphalib/types/robots/s3-import.ts index 4d78e4a..5d43582 100644 --- a/src/alphalib/types/robots/s3-import.ts +++ b/src/alphalib/types/robots/s3-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotS3ImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/s3-store.ts b/src/alphalib/types/robots/s3-store.ts index 5228a57..69946f3 100644 --- a/src/alphalib/types/robots/s3-store.ts +++ b/src/alphalib/types/robots/s3-store.ts @@ -38,6 +38,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, trackOutputFileSize: false, isInternal: false, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/script-run.ts b/src/alphalib/types/robots/script-run.ts index 96e9a83..1cabe77 100644 --- a/src/alphalib/types/robots/script-run.ts +++ b/src/alphalib/types/robots/script-run.ts @@ -27,6 +27,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotScriptRunInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/sftp-import.ts b/src/alphalib/types/robots/sftp-import.ts index 9fbfaae..8ea81bb 100644 --- a/src/alphalib/types/robots/sftp-import.ts +++ b/src/alphalib/types/robots/sftp-import.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotSftpImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/sftp-store.ts b/src/alphalib/types/robots/sftp-store.ts index d6614a3..11c4f53 100644 --- a/src/alphalib/types/robots/sftp-store.ts +++ b/src/alphalib/types/robots/sftp-store.ts @@ -38,6 +38,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotSftpStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/speech-transcribe.ts b/src/alphalib/types/robots/speech-transcribe.ts index 27c95db..2922cc5 100644 --- a/src/alphalib/types/robots/speech-transcribe.ts +++ b/src/alphalib/types/robots/speech-transcribe.ts @@ -54,6 +54,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotSpeechTranscribeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/supabase-import.ts b/src/alphalib/types/robots/supabase-import.ts index 4488630..3081d9b 100644 --- a/src/alphalib/types/robots/supabase-import.ts +++ b/src/alphalib/types/robots/supabase-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotSupabaseImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/supabase-store.ts b/src/alphalib/types/robots/supabase-store.ts index e47d345..53a60ba 100644 --- a/src/alphalib/types/robots/supabase-store.ts +++ b/src/alphalib/types/robots/supabase-store.ts @@ -38,6 +38,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: true, trackOutputFileSize: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', isInternal: false, } diff --git a/src/alphalib/types/robots/swift-import.ts b/src/alphalib/types/robots/swift-import.ts index aea698c..505f712 100644 --- a/src/alphalib/types/robots/swift-import.ts +++ b/src/alphalib/types/robots/swift-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotSwiftImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/swift-store.ts b/src/alphalib/types/robots/swift-store.ts index befc908..de032bd 100644 --- a/src/alphalib/types/robots/swift-store.ts +++ b/src/alphalib/types/robots/swift-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotSwiftStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/text-speak.ts b/src/alphalib/types/robots/text-speak.ts index 8398668..bf7a771 100644 --- a/src/alphalib/types/robots/text-speak.ts +++ b/src/alphalib/types/robots/text-speak.ts @@ -74,6 +74,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotTextSpeakInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/text-translate.ts b/src/alphalib/types/robots/text-translate.ts index 820da0f..a4ea2b5 100644 --- a/src/alphalib/types/robots/text-translate.ts +++ b/src/alphalib/types/robots/text-translate.ts @@ -60,6 +60,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } const translatableLanguages = z diff --git a/src/alphalib/types/robots/tigris-import.ts b/src/alphalib/types/robots/tigris-import.ts index 50176f3..5004c3c 100644 --- a/src/alphalib/types/robots/tigris-import.ts +++ b/src/alphalib/types/robots/tigris-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotTigrisImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/tigris-store.ts b/src/alphalib/types/robots/tigris-store.ts index f6dbd14..28f0a0f 100644 --- a/src/alphalib/types/robots/tigris-store.ts +++ b/src/alphalib/types/robots/tigris-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotTigrisStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/tlcdn-deliver.ts b/src/alphalib/types/robots/tlcdn-deliver.ts index fe4b683..b327f51 100644 --- a/src/alphalib/types/robots/tlcdn-deliver.ts +++ b/src/alphalib/types/robots/tlcdn-deliver.ts @@ -28,6 +28,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: false, trackOutputFileSize: false, isInternal: true, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/tus-store.ts b/src/alphalib/types/robots/tus-store.ts index 36108fc..8681b73 100644 --- a/src/alphalib/types/robots/tus-store.ts +++ b/src/alphalib/types/robots/tus-store.ts @@ -37,6 +37,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotTusStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/upload-handle.ts b/src/alphalib/types/robots/upload-handle.ts index d278c6c..b416701 100644 --- a/src/alphalib/types/robots/upload-handle.ts +++ b/src/alphalib/types/robots/upload-handle.ts @@ -43,6 +43,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotUploadHandleInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-adaptive.ts b/src/alphalib/types/robots/video-adaptive.ts index 75bde4b..1afdbd6 100644 --- a/src/alphalib/types/robots/video-adaptive.ts +++ b/src/alphalib/types/robots/video-adaptive.ts @@ -70,6 +70,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVideoAdaptiveInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-concat.ts b/src/alphalib/types/robots/video-concat.ts index f919c52..492ce2d 100644 --- a/src/alphalib/types/robots/video-concat.ts +++ b/src/alphalib/types/robots/video-concat.ts @@ -61,6 +61,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVideoConcatInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-encode.ts b/src/alphalib/types/robots/video-encode.ts index 2e3be2b..e34e4f0 100644 --- a/src/alphalib/types/robots/video-encode.ts +++ b/src/alphalib/types/robots/video-encode.ts @@ -43,6 +43,7 @@ export const meta: RobotMetaInput = { isAllowedForUrlTransform: false, trackOutputFileSize: true, isInternal: false, + stage: 'ga', removeJobResultFilesFromDiskRightAfterStoringOnS3: false, } diff --git a/src/alphalib/types/robots/video-merge.ts b/src/alphalib/types/robots/video-merge.ts index fa1c162..2858703 100644 --- a/src/alphalib/types/robots/video-merge.ts +++ b/src/alphalib/types/robots/video-merge.ts @@ -36,6 +36,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVideoMergeInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-ondemand.ts b/src/alphalib/types/robots/video-ondemand.ts index f684c36..8f4356b 100644 --- a/src/alphalib/types/robots/video-ondemand.ts +++ b/src/alphalib/types/robots/video-ondemand.ts @@ -68,6 +68,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'beta', } export const robotVideoOndemandInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-subtitle.ts b/src/alphalib/types/robots/video-subtitle.ts index 1e32a86..760c5ee 100644 --- a/src/alphalib/types/robots/video-subtitle.ts +++ b/src/alphalib/types/robots/video-subtitle.ts @@ -61,6 +61,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVideoSubtitleInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/video-thumbs.ts b/src/alphalib/types/robots/video-thumbs.ts index 31fb497..77bc03b 100644 --- a/src/alphalib/types/robots/video-thumbs.ts +++ b/src/alphalib/types/robots/video-thumbs.ts @@ -48,6 +48,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: true, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVideoThumbsInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/vimeo-import.ts b/src/alphalib/types/robots/vimeo-import.ts index 3f13984..9a160ae 100644 --- a/src/alphalib/types/robots/vimeo-import.ts +++ b/src/alphalib/types/robots/vimeo-import.ts @@ -48,6 +48,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotVimeoImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/vimeo-store.ts b/src/alphalib/types/robots/vimeo-store.ts index ad6fc3f..9d3c89c 100644 --- a/src/alphalib/types/robots/vimeo-store.ts +++ b/src/alphalib/types/robots/vimeo-store.ts @@ -40,6 +40,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotVimeoStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/wasabi-import.ts b/src/alphalib/types/robots/wasabi-import.ts index 87a9eb8..5cf2a8a 100644 --- a/src/alphalib/types/robots/wasabi-import.ts +++ b/src/alphalib/types/robots/wasabi-import.ts @@ -51,6 +51,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: true, + stage: 'ga', } export const robotWasabiImportInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/wasabi-store.ts b/src/alphalib/types/robots/wasabi-store.ts index 8f45ad2..e714cee 100644 --- a/src/alphalib/types/robots/wasabi-store.ts +++ b/src/alphalib/types/robots/wasabi-store.ts @@ -39,6 +39,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotWasabiStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/robots/youtube-store.ts b/src/alphalib/types/robots/youtube-store.ts index 7d0b708..83f0e04 100644 --- a/src/alphalib/types/robots/youtube-store.ts +++ b/src/alphalib/types/robots/youtube-store.ts @@ -42,6 +42,7 @@ export const meta: RobotMetaInput = { trackOutputFileSize: false, isInternal: false, removeJobResultFilesFromDiskRightAfterStoringOnS3: false, + stage: 'ga', } export const robotYoutubeStoreInstructionsSchema = robotBase diff --git a/src/alphalib/types/template.ts b/src/alphalib/types/template.ts index 0c339b0..d237b80 100644 --- a/src/alphalib/types/template.ts +++ b/src/alphalib/types/template.ts @@ -240,6 +240,22 @@ export const assemblyInstructionsWithHiddenSchema = assemblyInstructionsSchema.e mediainfo_stack: z.string().optional(), ffmpeg_stack: z.string().optional(), usage_tags: z.string().optional(), + response_headers: z + .object({ + cors: z + .object({ + 'Access-Control-Allow-Methods': z.string(), + 'Access-Control-Allow-Origin': z.string(), + 'Access-Control-Allow-Headers': z.string(), + 'Access-Control-Expose-Headers': z.string(), + 'Access-Control-Allow-Credentials': z.boolean(), + 'Access-Control-Max-Age': z.number(), + 'Access-Control-Allow-Private-Network': z.boolean(), + 'Access-Control-Allow-Public-Network': z.boolean(), + }) + .optional(), + }) + .optional(), randomize_watermarks: z.boolean().optional(), await: z .union([ diff --git a/yarn.lock b/yarn.lock index 94c98b9..f42faea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1929,6 +1929,13 @@ __metadata: languageName: node linkType: hard +"@transloadit/sev-logger@npm:^0.0.15": + version: 0.0.15 + resolution: "@transloadit/sev-logger@npm:0.0.15" + checksum: 10c0/1aa26ab5d6c8dab425ea85832f2094d59285963bc368b64990f23420ddc3a5bedea8ca70f91abb068d447479f4fca88cb1a9b2cd49ccc4093294daa7cf8e2ae1 + languageName: node + linkType: hard + "@types/chai@npm:^5.2.2": version: 5.2.2 resolution: "@types/chai@npm:5.2.2" @@ -5233,6 +5240,7 @@ __metadata: "@aws-sdk/client-s3": "npm:^3.891.0" "@aws-sdk/s3-request-presigner": "npm:^3.891.0" "@biomejs/biome": "npm:^2.2.4" + "@transloadit/sev-logger": "npm:^0.0.15" "@types/debug": "npm:^4.1.12" "@types/temp": "npm:^0.9.4" "@vitest/coverage-v8": "npm:^3.2.4"