Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .cursor/rules/coding-style.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ description:
globs:
alwaysApply: true
---

Coding style:

- Favor `async run() {` over `run = async () => {` inside ES6 classes
Expand All @@ -15,6 +14,6 @@ Coding style:
- Do not wrap each function body and function call in `try`/`catch` blocks. It pollutes the code. Assume we will always have an e.g. `main().catch((err) => { console.error(err); process.exit(1) })` to catch us. I repeat: Avoid over-use of try-catch such as `try { // foo } catch (err) { console.error('error while foo'); throw err }`, assume we catch errors on a higher level and do not need the extra explananation.
- Before creating new files and new code, see if we can leverage existing work, maybe slighty adapt that without breaking BC, to keep things DRY.
- Favor early exits, so quickly `continue`, `return false` (or `throw` if needed), over nesting everything in positive conditions, creating christmas trees.
- Use Biome with 100 char line width, single quotes for JS/TS, semi: false
- Use Prettier with 100 char line width, single quotes for JS/TS, semi: false
- Use descriptive names: PascalCase for components/types, camelCase for variables/methods/schemas
- Alphabetize imports, group by source type (built-in/external/internal)
309 changes: 233 additions & 76 deletions src/alphalib/types/robots/_instructions-primitives.ts

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions src/alphalib/types/robots/audio-artwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,16 @@ If you need the image in a different format, pipe the result of this <dfn>Robot<

The \`method\` parameter determines whether to extract or insert.
`),
method: z.enum(['extract', 'insert']).default('extract').describe(`
method: z
.enum(['extract', 'insert'])
.default('extract')
.describe(`
What should be done with the audio file. A value of \`"extract"\` means audio artwork will be extracted. A value of \`"insert"\` means the provided image will be inserted as audio artwork.
`),
change_format_if_necessary: z.boolean().default(false).describe(`
change_format_if_necessary: z
.boolean()
.default(false)
.describe(`
Whether the original file should be transcoded into a new format if there is an issue with the original file.
`),
})
Expand Down
10 changes: 8 additions & 2 deletions src/alphalib/types/robots/audio-concat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,18 @@ Bit rate of the resulting audio file, in bits per second. If not specified will
sample_rate: sampleRateSchema.optional().describe(`
Sample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.
`),
audio_fade_seconds: z.number().default(1).describe(`
audio_fade_seconds: z
.number()
.default(1)
.describe(`
When used this adds an audio fade in and out effect between each section of your concatenated audio file. The float value is used, so if you want an audio delay effect of 500 milliseconds between each video section, you would select 0.5. Integer values can also be represented.

This parameter does not add an audio fade effect at the beginning or end of your result audio file. If you want to do so, create an additional [🤖/audio/encode](/docs/robots/audio-encode/) <dfn>Step</dfn> and use our \`ffmpeg\` parameter as shown in this [demo](/demos/audio-encoding/ffmpeg-fade-in-and-out/).
`),
crossfade: z.boolean().default(false).describe(`
crossfade: z
.boolean()
.default(false)
.describe(`
When set to \`true\`, this parameter enables crossfading between concatenated audio files using FFmpeg's \`acrossfade\` filter. This creates a smooth transition where the end of one audio file overlaps and blends with the beginning of the next file.

The duration of the crossfade is controlled by the \`audio_fade_seconds\` parameter (defaults to 1 second if \`audio_fade_seconds\` is 0).
Expand Down
5 changes: 4 additions & 1 deletion src/alphalib/types/robots/audio-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ Bit rate of the resulting audio file, in bits per second. If not specified will
sample_rate: sampleRateSchema.optional().describe(`
Sample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.
`),
duration: z.number().default(60).describe(`
duration: z
.number()
.default(60)
.describe(`
Target duration for the whole process in seconds. The <dfn>Robot</dfn> will loop the input audio file for as long as this target duration is not reached yet.
`),
})
Expand Down
15 changes: 12 additions & 3 deletions src/alphalib/types/robots/audio-merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,22 @@ Bit rate of the resulting audio file, in bits per second. If not specified will
sample_rate: sampleRateSchema.optional().describe(`
Sample rate of the resulting audio file, in Hertz. If not specified will default to the sample rate of the input audio file.
`),
duration: z.enum(['first', 'longest', 'shortest']).default('longest').describe(`
duration: z
.enum(['first', 'longest', 'shortest'])
.default('longest')
.describe(`
Duration of the output file compared to the duration of all merged audio files. Can be \`"first"\` (duration of the first input file), \`"shortest"\` (duration of the shortest audio file) or \`"longest"\` for the duration of the longest input file.
`),
loop: z.boolean().default(false).describe(`
loop: z
.boolean()
.default(false)
.describe(`
Specifies if any input files that do not match the target duration should be looped to match it. Useful for audio merging where your overlay file is typically much shorter than the main audio file.
`),
volume: z.enum(['average', 'sum']).default('average').describe(`
volume: z
.enum(['average', 'sum'])
.default('average')
.describe(`
Valid values are \`"average"\` and \`"sum"\` here. \`"average"\` means each input is scaled 1/n (n is the number of inputs) or \`"sum"\` which means each individual audio stays on the same volume, but since we merge tracks 'on top' of each other, this could result in very loud output.
`),
})
Expand Down
29 changes: 24 additions & 5 deletions src/alphalib/types/robots/audio-waveform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,38 @@ We recommend that you use an [🤖/audio/encode](/docs/robots/audio-encode/) <df

Similarly, if you need the output image in a different format, please pipe the result of this <dfn>Robot</dfn> into [🤖/image/resize](/docs/robots/image-resize/).
`),
format: z.enum(['image', 'json']).default('image').describe(`
format: z
.enum(['image', 'json'])
.default('image')
.describe(`
The format of the result file. Can be \`"image"\` or \`"json"\`. If \`"image"\` is supplied, a PNG image will be created, otherwise a JSON file.
`),
width: z.number().int().min(1).default(256).describe(`
width: z
.number()
.int()
.min(1)
.default(256)
.describe(`
The width of the resulting image if the format \`"image"\` was selected.
`),
height: z.number().int().min(1).default(64).describe(`
height: z
.number()
.int()
.min(1)
.default(64)
.describe(`
The height of the resulting image if the format \`"image"\` was selected.
`),
style: z.union([z.literal(0), z.literal(1)]).default(0).describe(`
style: z
.union([z.literal(0), z.literal(1)])
.default(0)
.describe(`
Either a value of \`0\` or \`1\`, corresponding to using either the legacy waveform tool, or the new tool respectively, with the new tool offering an improved style. Other Robot parameters still function as described, with either tool.
`),
antialiasing: z.union([z.literal(0), z.literal(1), z.boolean()]).default(0).describe(`
antialiasing: z
.union([z.literal(0), z.literal(1), z.boolean()])
.default(0)
.describe(`
Either a value of \`0\` or \`1\`, or \`true\`/\`false\`, corresponding to if you want to enable antialiasing to achieve smoother edges in the waveform graph or not.
`),
background_color: color_with_alpha.default('#00000000').describe(`
Expand Down
45 changes: 36 additions & 9 deletions src/alphalib/types/robots/azure-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,37 +46,64 @@ export const robotAzureStoreInstructionsSchema = robotBase
.merge(azureBase)
.extend({
robot: z.literal('/azure/store'),
path: z.string().default('${unique_prefix}/${file.url_name}').describe(`
path: z
.string()
.default('${unique_prefix}/${file.url_name}')
.describe(`
The path at which the file is to be stored. This may include any available [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables).
`),
content_type: z.string().optional().describe(`
content_type: z
.string()
.optional()
.describe(`
The content type with which to store the file. By default this will be guessed by Azure.
`),
content_encoding: z.string().optional().describe(`
content_encoding: z
.string()
.optional()
.describe(`
The content encoding with which to store the file. By default this will be guessed by Azure.
`),
content_language: z.string().optional().describe(`
content_language: z
.string()
.optional()
.describe(`
The content language with which to store the file. By default this will be guessed by Azure.
`),
content_disposition: z.string().optional().describe(`
content_disposition: z
.string()
.optional()
.describe(`
The content disposition with which to store the file. By default this will be guessed by Azure.
`),
cache_control: z.string().optional().describe(`
cache_control: z
.string()
.optional()
.describe(`
The cache control header with which to store the file.
`),
// TODO: verify if this is correct.
metadata: z.record(z.string()).default({}).describe(`
metadata: z
.record(z.string())
.default({})
.describe(`
A JavaScript object containing a list of metadata to be set for this file on Azure, such as \`{ FileURL: "\${file.url_name}" }\`. This can also include any available [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables).
`),
sas_expires_in: z.number().int().min(0).optional().describe(`
sas_expires_in: z
.number()
.int()
.min(0)
.optional()
.describe(`
Set this to a number to enable shared access signatures for your stored object. This reflects the number of seconds that the signature will be valid for once the object is stored. Enabling this will attach the shared access signature (SAS) to the result URL of your object.
`),
sas_permissions: z
.string()
.regex(/^[rdw]+$/)
.min(0)
.max(3)
.optional().describe(`
.optional()
.describe(`
Set this to a combination of \`r\` (read), \`w\` (write) and \`d\` (delete) for your shared access signatures (SAS) permissions.
`),
})
Expand Down
5 changes: 4 additions & 1 deletion src/alphalib/types/robots/backblaze-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ Setting this to \`true\` will enable importing files from subdirectories and sub

Please use the pagination parameters \`start_file_name\` and \`files_per_page\` wisely here.
`),
start_file_name: z.string().default('').describe(`
start_file_name: z
.string()
.default('')
.describe(`
The name of the last file from the previous paging call. This tells the <dfn>Robot</dfn> to ignore all files up to and including this file.
`),
files_per_page: files_per_page.describe(`
Expand Down
10 changes: 8 additions & 2 deletions src/alphalib/types/robots/backblaze-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,16 @@ export const robotBackblazeStoreInstructionsSchema = robotBase
.merge(backblazeBase)
.extend({
robot: z.literal('/backblaze/store'),
path: z.string().default('${unique_prefix}/${file.url_name}').describe(`
path: z
.string()
.default('${unique_prefix}/${file.url_name}')
.describe(`
The path at which the file is to be stored. This may include any available [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables).
`),
headers: z.record(z.string()).default({}).describe(`
headers: z
.record(z.string())
.default({})
.describe(`
An object containing a list of headers to be set for this file on backblaze, such as \`{ FileURL: "\${file.url_name}" }\`. This can also include any available [Assembly Variables](/docs/topics/assembly-instructions/#assembly-variables).

[Here](https://www.backblaze.com/b2/docs/b2_upload_file.html) you can find a list of available headers.
Expand Down
5 changes: 4 additions & 1 deletion src/alphalib/types/robots/cloudfiles-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ Directories are **not** imported recursively. If you want to import files from s
You can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.
`),
recursive: z.boolean().default(false).describe(`
recursive: z
.boolean()
.default(false)
.describe(`
Setting this to \`true\` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.
Please use the pagination parameters \`page_number\` and \`files_per_page\`wisely here.
Expand Down
5 changes: 4 additions & 1 deletion src/alphalib/types/robots/cloudfiles-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ export const robotCloudfilesStoreInstructionsSchema = robotBase
.merge(cloudfilesBase)
.extend({
robot: z.literal('/cloudfiles/store'),
path: z.string().default('${unique_prefix}/${file.url_name}').describe(`
path: z
.string()
.default('${unique_prefix}/${file.url_name}')
.describe(`
The path at which to store the file. This value can also contain [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables).
`),
})
Expand Down
22 changes: 18 additions & 4 deletions src/alphalib/types/robots/cloudflare-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,32 @@ export const robotCloudflareStoreInstructionsSchema = robotBase
.merge(cloudflareBase)
.extend({
robot: z.literal('/cloudflare/store'),
path: z.string().default('${unique_prefix}/${file.url_name}').describe(`
path: z
.string()
.default('${unique_prefix}/${file.url_name}')
.describe(`
The path at which the file is to be stored. This may include any available [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.
`),
headers: z.record(z.string()).default({ 'Content-Type': '${file.mime}' }).describe(`
headers: z
.record(z.string())
.default({ 'Content-Type': '${file.mime}' })
.describe(`
An object containing a list of headers to be set for this file on cloudflare Spaces, such as \`{ FileURL: "\${file.url_name}" }\`. This can also include any available [Assembly Variables](/docs/topics/assembly-instructions/#assembly-variables).

Object Metadata can be specified using \`x-amz-meta-*\` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).
`),
sign_urls_for: z.number().int().min(0).optional().describe(`
sign_urls_for: z
.number()
.int()
.min(0)
.optional()
.describe(`
This parameter provides signed URLs in the result JSON (in the \`signed_ssl_url\` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.
`),
url_prefix: z.string().optional().describe(`
url_prefix: z
.string()
.optional()
.describe(`
The URL prefix used for accessing files from your Cloudflare R2 bucket. This is typically the custom public URL access host set up in your Cloudflare account.
`),
})
Expand Down
27 changes: 22 additions & 5 deletions src/alphalib/types/robots/digitalocean-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,40 @@ export const robotDigitaloceanStoreInstructionsSchema = robotBase
.merge(digitalOceanBase)
.extend({
robot: z.literal('/digitalocean/store'),
path: z.string().default('${unique_prefix}/${file.url_name}').describe(`
path: z
.string()
.default('${unique_prefix}/${file.url_name}')
.describe(`
The path at which the file is to be stored. This may include any available [Assembly variables](/docs/topics/assembly-instructions/#assembly-variables). The path must not be a directory.
`),
url_prefix: z.string().default('https://{space}.{region}.digitaloceanspaces.com/').describe(`
url_prefix: z
.string()
.default('https://{space}.{region}.digitaloceanspaces.com/')
.describe(`
The URL prefix used for the returned URL, such as \`"https://my.cdn.com/some/path"\`.
`),
acl: z.enum(['private', 'public-read']).default('public-read').describe(`
acl: z
.enum(['private', 'public-read'])
.default('public-read')
.describe(`
The permissions used for this file.
`),
headers: z.record(z.string()).default({ 'Content-Type': '${file.mime}' }).describe(`
headers: z
.record(z.string())
.default({ 'Content-Type': '${file.mime}' })
.describe(`
An object containing a list of headers to be set for this file on DigitalOcean Spaces, such as \`{ FileURL: "\${file.url_name}" }\`. This can also include any available [Assembly Variables](/docs/topics/assembly-instructions/#assembly-variables).

[Here](https://developers.digitalocean.com/documentation/spaces/#object) you can find a list of available headers.

Object Metadata can be specified using \`x-amz-meta-*\` headers. Note that these headers [do not support non-ASCII metadata values](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata).
`),
sign_urls_for: z.number().int().min(0).optional().describe(`
sign_urls_for: z
.number()
.int()
.min(0)
.optional()
.describe(`
This parameter provides signed URLs in the result JSON (in the \`signed_ssl_url\` property). The number that you set this parameter to is the URL expiry time in seconds. If this parameter is not used, no URL signing is done.
`),
})
Expand Down
Loading