@shotstack/cli 0.1.0 → 0.2.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 +20 -1
- package/SKILL.md +40 -20
- package/dist/shotstack.js +21 -21
- package/package.json +2 -2
- package/references/timeline.md +5 -9
- package/references/troubleshooting.md +5 -5
package/README.md
CHANGED
|
@@ -50,11 +50,13 @@ SHOTSTACK_ENV=stage shotstack render template.json
|
|
|
50
50
|
|
|
51
51
|
### `shotstack render <file>`
|
|
52
52
|
|
|
53
|
-
Submits a Shotstack Edit JSON to the render API. Returns a render ID.
|
|
53
|
+
Submits a Shotstack Edit JSON to the render API. Returns a render ID. With `--watch`, polls until the render reaches a terminal state and prints the output URL — equivalent to `render` followed by `status --watch` but in one command.
|
|
54
54
|
|
|
55
55
|
```sh
|
|
56
56
|
shotstack render my-template.json
|
|
57
57
|
shotstack render my-template.json --output json
|
|
58
|
+
shotstack render my-template.json --watch # submit + poll until done
|
|
59
|
+
shotstack render my-template.json --watch --output json
|
|
58
60
|
```
|
|
59
61
|
|
|
60
62
|
### `shotstack status <id>`
|
|
@@ -67,6 +69,23 @@ shotstack status 01ja7-x8m2k-... --watch
|
|
|
67
69
|
shotstack status 01ja7-x8m2k-... --output json
|
|
68
70
|
```
|
|
69
71
|
|
|
72
|
+
### `shotstack preview <file>`
|
|
73
|
+
|
|
74
|
+
Opens a `shotstack.studio` URL that loads the Edit JSON directly into the browser-based editor. No API call, no key, no charge — pure client-side encoding via the URL hash. Use it to hand a generated edit off to a human for review or quick tweaks before rendering.
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
shotstack preview my-template.json
|
|
78
|
+
# → opens browser silently
|
|
79
|
+
|
|
80
|
+
shotstack preview my-template.json --copy # also copies URL to clipboard
|
|
81
|
+
shotstack preview my-template.json --no-open # print URL, don't open browser
|
|
82
|
+
shotstack preview my-template.json --output json # emit {"url":"..."} on stdout
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
When a browser can be launched, the command is silent — the URL only opens in the browser. On a headless server (no `$DISPLAY`, no `xdg-open`), the URL is printed to stdout instead so you can copy it elsewhere.
|
|
86
|
+
|
|
87
|
+
Templates whose encoded URL exceeds ~6KB print a stderr warning. Browser URL limits vary; if you regularly exceed it, host the JSON publicly and link to it via `https://shotstack.studio/#src=<https-url>`.
|
|
88
|
+
|
|
70
89
|
### `shotstack feedback`
|
|
71
90
|
|
|
72
91
|
Opens a pre-filled GitHub issue with a sanitised dossier of your last 5 CLI invocations (render IDs, errors, exit codes). API keys and signed URLs are stripped at write time. You review and submit in your browser; nothing is transmitted automatically. Inspect the log at `~/.shotstack/log.jsonl`.
|
package/SKILL.md
CHANGED
|
@@ -4,26 +4,25 @@ description: |
|
|
|
4
4
|
Render video and poll render status via the Shotstack API.
|
|
5
5
|
Use when generating clips, building automated video pipelines, or orchestrating
|
|
6
6
|
cloud video renders from a script, agent, or CI workflow.
|
|
7
|
-
NOT for: real-time streaming, live broadcasting
|
|
7
|
+
NOT for: real-time streaming, or live broadcasting.
|
|
8
8
|
license: Apache-2.0
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Shotstack CLI
|
|
12
12
|
|
|
13
|
-
Two commands for the Shotstack video rendering API. `render` submits
|
|
13
|
+
Two commands for the Shotstack video rendering API. `render` submits an Edit JSON and returns a render ID; `status` polls a render until done.
|
|
14
14
|
|
|
15
15
|
## Authentication
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
export SHOTSTACK_API_KEY
|
|
18
|
+
export SHOTSTACK_API_KEY=...
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
Get a key at <https://
|
|
21
|
+
Get a key at <https://app.shotstack.io>. Without a key, every command exits with code 1.
|
|
22
22
|
|
|
23
23
|
## Environments
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
--env dev → https://api.shotstack.io/edit/dev
|
|
27
26
|
--env stage → https://api.shotstack.io/edit/stage (test credits, free)
|
|
28
27
|
--env v1 → https://api.shotstack.io/edit/v1 (production, default)
|
|
29
28
|
```
|
|
@@ -33,32 +32,52 @@ Use `--env stage` for experimentation. Stage is free; v1 charges real credits. O
|
|
|
33
32
|
## Quickstart
|
|
34
33
|
|
|
35
34
|
```sh
|
|
36
|
-
# Submit
|
|
37
|
-
shotstack render template.json --
|
|
35
|
+
# Submit + poll in one command (most agent flows want this).
|
|
36
|
+
shotstack render template.json --watch
|
|
37
|
+
# → done https://shotstack-api-v1-output.s3.amazonaws.com/.../01ja7-x8m2k-39rzv-cmvxve.mp4
|
|
38
|
+
|
|
39
|
+
# Submit only (returns ID).
|
|
40
|
+
shotstack render template.json --output json
|
|
38
41
|
# → {"id":"01ja7-x8m2k-39rzv-cmvxve"}
|
|
39
42
|
|
|
40
|
-
# Poll
|
|
41
|
-
shotstack status 01ja7-x8m2k-39rzv-cmvxve --watch
|
|
42
|
-
# → done https://shotstack-api-
|
|
43
|
+
# Poll an existing render to terminal state.
|
|
44
|
+
shotstack status 01ja7-x8m2k-39rzv-cmvxve --watch
|
|
45
|
+
# → done https://shotstack-api-v1-output.s3.amazonaws.com/.../01ja7-x8m2k-39rzv-cmvxve.mp4
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
##
|
|
48
|
+
## Hand-off to a human before rendering
|
|
49
|
+
|
|
50
|
+
When a human is in the loop and may want to tweak the result, prefer **`shotstack preview <file>`** over `shotstack render`. By default it opens the browser to `https://shotstack.studio/#json=<base64url>` and prints the URL — the timeline loads directly into the browser-based editor. No API call, no key, no charge. The human can play, edit, and decide whether to render — saving credits when the AI's first attempt isn't quite right.
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
shotstack preview template.json # opens browser + prints URL
|
|
54
|
+
shotstack preview template.json --no-open # headless: just print the URL
|
|
55
|
+
shotstack preview template.json --output json # piping: {"url":"..."}, no browser
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
On headless systems (no `xdg-open`, no `$DISPLAY`) the browser launch silently no-ops; the URL is still printed. Safe to run anywhere.
|
|
59
|
+
|
|
60
|
+
Use `render` only when you're confident the JSON is final, or there's no human to review.
|
|
61
|
+
|
|
62
|
+
## Four CLI rules
|
|
63
|
+
|
|
64
|
+
1. **Pipe → `--output json`.** Default output is human-readable. When parsing programmatically or piping to another command, always pass `--output json`.
|
|
46
65
|
|
|
47
|
-
|
|
66
|
+
2. **Use `--watch`, not a polling loop.** `shotstack render <file> --watch` submits and polls in one shot; `shotstack status <id> --watch` polls an existing render. Both exit when terminal: `done` (exit 0) or `failed` (exit 1). Don't write `while true; do ...; sleep 3; done`.
|
|
48
67
|
|
|
49
|
-
|
|
68
|
+
3. **Fetch the current schema and docs before generating Edit JSON.** The Shotstack API evolves; LLM training data is often stale. Pull <https://shotstack.io/docs/api/api.edit.json> and <https://shotstack.io/docs/guide/llms-full.txt> for the current schema and guides before composing an Edit from scratch.
|
|
50
69
|
|
|
51
|
-
|
|
70
|
+
4. **Hand off to a human via `preview` when uncertain.** Don't burn render credits iterating. Generate JSON → `shotstack preview` → human reviews/tweaks → render only when right.
|
|
52
71
|
|
|
53
|
-
## Authoring
|
|
72
|
+
## Authoring Edit JSON
|
|
54
73
|
|
|
55
|
-
These are the conventions agents most often get wrong. Read this section before generating any
|
|
74
|
+
These are the conventions agents most often get wrong. Read this section before generating any Edit JSON.
|
|
56
75
|
|
|
57
76
|
### Before composing JSON: check the schema
|
|
58
77
|
|
|
59
78
|
Don't invent property names or enum values. The Shotstack schema is published — fetch one of these before composing JSON from scratch:
|
|
60
79
|
|
|
61
|
-
- <https://shotstack.io/docs/api/api.
|
|
80
|
+
- <https://shotstack.io/docs/api/api.edit.json> — single-file OpenAPI Schema. Machine-validatable; load it once and validate locally instead of round-tripping the API.
|
|
62
81
|
- <https://shotstack.io/docs/api/> — interactive HTML reference. Fastest for human scanning.
|
|
63
82
|
- <https://shotstack.io/docs/guide/llms-full.txt> — single-file LLM-friendly version of the full guide + reference.
|
|
64
83
|
- <https://github.com/shotstack/oas-api-definition/tree/main/schemas> — raw OpenAPI YAML, source of truth.
|
|
@@ -167,7 +186,7 @@ The render API supports many asset types. Use only the **current** ones; the dep
|
|
|
167
186
|
|
|
168
187
|
### AI-generated assets
|
|
169
188
|
|
|
170
|
-
`image-to-video` and `text-to-image` are billed per generation **even when invoked through the sandbox stage endpoint** (which is otherwise free). They are async — the render submits the AI job and waits. Renders containing AI assets take longer.
|
|
189
|
+
`image-to-video`, `text-to-speech`, and `text-to-image` are billed per generation **even when invoked through the sandbox stage endpoint** (which is otherwise free). They are async — the render submits the AI job and waits. Renders containing AI assets take longer.
|
|
171
190
|
|
|
172
191
|
## Fonts
|
|
173
192
|
|
|
@@ -220,10 +239,11 @@ The `font.family` value is the **font file basename** (without `.ttf`/`.otf`).
|
|
|
220
239
|
Authoritative sources, in order of preference:
|
|
221
240
|
|
|
222
241
|
- `shotstack --help` and `shotstack <command> --help` — current CLI flag listing
|
|
223
|
-
- <https://shotstack.io/docs/api/api.
|
|
242
|
+
- <https://shotstack.io/docs/api/api.edit.json> — OpenAPI Schema for the render API (machine-validatable)
|
|
224
243
|
- <https://shotstack.io/docs/guide/llms-full.txt> — full API docs in LLM-friendly single file
|
|
225
244
|
- <https://github.com/shotstack/oas-api-definition/tree/main/schemas> — raw OpenAPI YAML, source of truth for property names and enums
|
|
226
|
-
- <https://shotstack.io/docs/
|
|
245
|
+
- <https://shotstack.io/docs/guide/> — interactive HTML docs and guides
|
|
246
|
+
- <https://shotstack.io/docs/api/> — interactive HTML API reference
|
|
227
247
|
- <https://github.com/shotstack/shotstack-cli> — CLI source
|
|
228
248
|
|
|
229
249
|
This skill ships sub-references for the gnarly bits:
|
package/dist/shotstack.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createRequire as
|
|
3
|
-
`).replace(/^/gm," ".repeat(2))}let
|
|
4
|
-
`)}padWidth(E
|
|
2
|
+
import{createRequire as sf}from"node:module";var Df=Object.create;var{getPrototypeOf:Ff,defineProperty:d,getOwnPropertyNames:kf}=Object;var uf=Object.prototype.hasOwnProperty;function Af(f){return this[f]}var Vf,xf,bf=(f,E,R)=>{var S=f!=null&&typeof f==="object";if(S){var w=E?Vf??=new WeakMap:xf??=new WeakMap,$=w.get(f);if($)return $}R=f!=null?Df(Ff(f)):{};let T=E||!f||!f.__esModule?d(R,"default",{value:f,enumerable:!0}):R;for(let _ of kf(f))if(!uf.call(T,_))d(T,_,{get:Af.bind(f,_),enumerable:!0});if(S)w.set(f,T);return T};var M=(f,E)=>()=>(E||f((E={exports:{}}).exports,E),E.exports);var N=sf(import.meta.url);var Q=M((Cf)=>{class x extends Error{constructor(f,E,R){super(R);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=E,this.exitCode=f,this.nestedError=void 0}}class o extends x{constructor(f){super(1,"commander.invalidArgument",f);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}Cf.CommanderError=x;Cf.InvalidArgumentError=o});var K=M((nf)=>{var{InvalidArgumentError:vf}=Q();class e{constructor(f,E){switch(this.description=E||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,f[0]){case"<":this.required=!0,this._name=f.slice(1,-1);break;case"[":this.required=!1,this._name=f.slice(1,-1);break;default:this.required=!0,this._name=f;break}if(this._name.length>3&&this._name.slice(-3)==="...")this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_concatValue(f,E){if(E===this.defaultValue||!Array.isArray(E))return[f];return E.concat(f)}default(f,E){return this.defaultValue=f,this.defaultValueDescription=E,this}argParser(f){return this.parseArg=f,this}choices(f){return this.argChoices=f.slice(),this.parseArg=(E,R)=>{if(!this.argChoices.includes(E))throw new vf(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(E,R);return E},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function cf(f){let E=f.name()+(f.variadic===!0?"...":"");return f.required?"<"+E+">":"["+E+"]"}nf.Argument=e;nf.humanReadableArgName=cf});var b=M((df)=>{var{humanReadableArgName:lf}=K();class p{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(f){let E=f.commands.filter((S)=>!S._hidden),R=f._getHelpCommand();if(R&&!R._hidden)E.push(R);if(this.sortSubcommands)E.sort((S,w)=>{return S.name().localeCompare(w.name())});return E}compareOptions(f,E){let R=(S)=>{return S.short?S.short.replace(/^-/,""):S.long.replace(/^--/,"")};return R(f).localeCompare(R(E))}visibleOptions(f){let E=f.options.filter((S)=>!S.hidden),R=f._getHelpOption();if(R&&!R.hidden){let S=R.short&&f._findOption(R.short),w=R.long&&f._findOption(R.long);if(!S&&!w)E.push(R);else if(R.long&&!w)E.push(f.createOption(R.long,R.description));else if(R.short&&!S)E.push(f.createOption(R.short,R.description))}if(this.sortOptions)E.sort(this.compareOptions);return E}visibleGlobalOptions(f){if(!this.showGlobalOptions)return[];let E=[];for(let R=f.parent;R;R=R.parent){let S=R.options.filter((w)=>!w.hidden);E.push(...S)}if(this.sortOptions)E.sort(this.compareOptions);return E}visibleArguments(f){if(f._argsDescription)f.registeredArguments.forEach((E)=>{E.description=E.description||f._argsDescription[E.name()]||""});if(f.registeredArguments.find((E)=>E.description))return f.registeredArguments;return[]}subcommandTerm(f){let E=f.registeredArguments.map((R)=>lf(R)).join(" ");return f._name+(f._aliases[0]?"|"+f._aliases[0]:"")+(f.options.length?" [options]":"")+(E?" "+E:"")}optionTerm(f){return f.flags}argumentTerm(f){return f.name()}longestSubcommandTermLength(f,E){return E.visibleCommands(f).reduce((R,S)=>{return Math.max(R,E.subcommandTerm(S).length)},0)}longestOptionTermLength(f,E){return E.visibleOptions(f).reduce((R,S)=>{return Math.max(R,E.optionTerm(S).length)},0)}longestGlobalOptionTermLength(f,E){return E.visibleGlobalOptions(f).reduce((R,S)=>{return Math.max(R,E.optionTerm(S).length)},0)}longestArgumentTermLength(f,E){return E.visibleArguments(f).reduce((R,S)=>{return Math.max(R,E.argumentTerm(S).length)},0)}commandUsage(f){let E=f._name;if(f._aliases[0])E=E+"|"+f._aliases[0];let R="";for(let S=f.parent;S;S=S.parent)R=S.name()+" "+R;return R+E+" "+f.usage()}commandDescription(f){return f.description()}subcommandDescription(f){return f.summary()||f.description()}optionDescription(f){let E=[];if(f.argChoices)E.push(`choices: ${f.argChoices.map((R)=>JSON.stringify(R)).join(", ")}`);if(f.defaultValue!==void 0){if(f.required||f.optional||f.isBoolean()&&typeof f.defaultValue==="boolean")E.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`)}if(f.presetArg!==void 0&&f.optional)E.push(`preset: ${JSON.stringify(f.presetArg)}`);if(f.envVar!==void 0)E.push(`env: ${f.envVar}`);if(E.length>0)return`${f.description} (${E.join(", ")})`;return f.description}argumentDescription(f){let E=[];if(f.argChoices)E.push(`choices: ${f.argChoices.map((R)=>JSON.stringify(R)).join(", ")}`);if(f.defaultValue!==void 0)E.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`);if(E.length>0){let R=`(${E.join(", ")})`;if(f.description)return`${f.description} ${R}`;return R}return f.description}formatHelp(f,E){let R=E.padWidth(f,E),S=E.helpWidth||80,w=2,$=2;function T(U,Y){if(Y){let V=`${U.padEnd(R+2)}${Y}`;return E.wrap(V,S-2,R+2)}return U}function _(U){return U.join(`
|
|
3
|
+
`).replace(/^/gm," ".repeat(2))}let y=[`Usage: ${E.commandUsage(f)}`,""],L=E.commandDescription(f);if(L.length>0)y=y.concat([E.wrap(L,S,0),""]);let r=E.visibleArguments(f).map((U)=>{return T(E.argumentTerm(U),E.argumentDescription(U))});if(r.length>0)y=y.concat(["Arguments:",_(r),""]);let J=E.visibleOptions(f).map((U)=>{return T(E.optionTerm(U),E.optionDescription(U))});if(J.length>0)y=y.concat(["Options:",_(J),""]);if(this.showGlobalOptions){let U=E.visibleGlobalOptions(f).map((Y)=>{return T(E.optionTerm(Y),E.optionDescription(Y))});if(U.length>0)y=y.concat(["Global Options:",_(U),""])}let P=E.visibleCommands(f).map((U)=>{return T(E.subcommandTerm(U),E.subcommandDescription(U))});if(P.length>0)y=y.concat(["Commands:",_(P),""]);return y.join(`
|
|
4
|
+
`)}padWidth(f,E){return Math.max(E.longestOptionTermLength(f,E),E.longestGlobalOptionTermLength(f,E),E.longestSubcommandTermLength(f,E),E.longestArgumentTermLength(f,E))}wrap(f,E,R,S=40){let $=new RegExp(`[\\n][${" \\f\\t\\v - \uFEFF"}]+`);if(f.match($))return f;let T=E-R;if(T<S)return f;let _=f.slice(0,R),y=f.slice(R).replace(`\r
|
|
5
5
|
`,`
|
|
6
|
-
`),
|
|
7
|
-
|.{1,${
|
|
8
|
-
`)return"";return(
|
|
9
|
-
`)}}
|
|
10
|
-
(Did you mean one of ${
|
|
11
|
-
(Did you mean ${
|
|
12
|
-
- specify the name in Command constructor or using .name()`);if(
|
|
13
|
-
Expecting one of '${R.join("', '")}'`);if(this._lifeCycleHooks[
|
|
14
|
-
- already used by option '${
|
|
15
|
-
- if '${
|
|
6
|
+
`),L=" ".repeat(R),J=`\\s${""}`,P=new RegExp(`
|
|
7
|
+
|.{1,${T-1}}([${J}]|$)|[^${J}]+?([${J}]|$)`,"g"),U=y.match(P)||[];return _+U.map((Y,V)=>{if(Y===`
|
|
8
|
+
`)return"";return(V>0?L:"")+Y.trimEnd()}).join(`
|
|
9
|
+
`)}}df.Help=p});var s=M((fE)=>{var{InvalidArgumentError:ef}=Q();class a{constructor(f,E){this.flags=f,this.description=E||"",this.required=f.includes("<"),this.optional=f.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(f),this.mandatory=!1;let R=af(f);if(this.short=R.shortFlag,this.long=R.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(f,E){return this.defaultValue=f,this.defaultValueDescription=E,this}preset(f){return this.presetArg=f,this}conflicts(f){return this.conflictsWith=this.conflictsWith.concat(f),this}implies(f){let E=f;if(typeof f==="string")E={[f]:!0};return this.implied=Object.assign(this.implied||{},E),this}env(f){return this.envVar=f,this}argParser(f){return this.parseArg=f,this}makeOptionMandatory(f=!0){return this.mandatory=!!f,this}hideHelp(f=!0){return this.hidden=!!f,this}_concatValue(f,E){if(E===this.defaultValue||!Array.isArray(E))return[f];return E.concat(f)}choices(f){return this.argChoices=f.slice(),this.parseArg=(E,R)=>{if(!this.argChoices.includes(E))throw new ef(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(E,R);return E},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){return pf(this.name().replace(/^no-/,""))}is(f){return this.short===f||this.long===f}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class ff{constructor(f){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,f.forEach((E)=>{if(E.negate)this.negativeOptions.set(E.attributeName(),E);else this.positiveOptions.set(E.attributeName(),E)}),this.negativeOptions.forEach((E,R)=>{if(this.positiveOptions.has(R))this.dualOptions.add(R)})}valueFromOption(f,E){let R=E.attributeName();if(!this.dualOptions.has(R))return!0;let S=this.negativeOptions.get(R).presetArg,w=S!==void 0?S:!1;return E.negate===(w===f)}}function pf(f){return f.split("-").reduce((E,R)=>{return E+R[0].toUpperCase()+R.slice(1)})}function af(f){let E,R,S=f.split(/[ |,]+/);if(S.length>1&&!/^[[<]/.test(S[1]))E=S.shift();if(R=S.shift(),!E&&/^-[^-]$/.test(R))E=R,R=void 0;return{shortFlag:E,longFlag:R}}fE.Option=a;fE.DualOptions=ff});var Ef=M(($E)=>{function SE(f,E){if(Math.abs(f.length-E.length)>3)return Math.max(f.length,E.length);let R=[];for(let S=0;S<=f.length;S++)R[S]=[S];for(let S=0;S<=E.length;S++)R[0][S]=S;for(let S=1;S<=E.length;S++)for(let w=1;w<=f.length;w++){let $=1;if(f[w-1]===E[S-1])$=0;else $=1;if(R[w][S]=Math.min(R[w-1][S]+1,R[w][S-1]+1,R[w-1][S-1]+$),w>1&&S>1&&f[w-1]===E[S-2]&&f[w-2]===E[S-1])R[w][S]=Math.min(R[w][S],R[w-2][S-2]+1)}return R[f.length][E.length]}function wE(f,E){if(!E||E.length===0)return"";E=Array.from(new Set(E));let R=f.startsWith("--");if(R)f=f.slice(2),E=E.map((T)=>T.slice(2));let S=[],w=3,$=0.4;if(E.forEach((T)=>{if(T.length<=1)return;let _=SE(f,T),y=Math.max(f.length,T.length);if((y-_)/y>$){if(_<w)w=_,S=[T];else if(_===w)S.push(T)}}),S.sort((T,_)=>T.localeCompare(_)),R)S=S.map((T)=>`--${T}`);if(S.length>1)return`
|
|
10
|
+
(Did you mean one of ${S.join(", ")}?)`;if(S.length===1)return`
|
|
11
|
+
(Did you mean ${S[0]}?)`;return""}$E.suggestSimilar=wE});var $f=M((UE)=>{var _E=N("node:events").EventEmitter,C=N("node:child_process"),q=N("node:path"),h=N("node:fs"),I=N("node:process"),{Argument:yE,humanReadableArgName:LE}=K(),{CommanderError:O}=Q(),{Help:rE}=b(),{Option:Rf,DualOptions:IE}=s(),{suggestSimilar:Sf}=Ef();class v extends _E{constructor(f){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=f||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:(E)=>I.stdout.write(E),writeErr:(E)=>I.stderr.write(E),getOutHelpWidth:()=>I.stdout.isTTY?I.stdout.columns:void 0,getErrHelpWidth:()=>I.stderr.isTTY?I.stderr.columns:void 0,outputError:(E,R)=>R(E)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(f){return this._outputConfiguration=f._outputConfiguration,this._helpOption=f._helpOption,this._helpCommand=f._helpCommand,this._helpConfiguration=f._helpConfiguration,this._exitCallback=f._exitCallback,this._storeOptionsAsProperties=f._storeOptionsAsProperties,this._combineFlagAndOptionalValue=f._combineFlagAndOptionalValue,this._allowExcessArguments=f._allowExcessArguments,this._enablePositionalOptions=f._enablePositionalOptions,this._showHelpAfterError=f._showHelpAfterError,this._showSuggestionAfterError=f._showSuggestionAfterError,this}_getCommandAndAncestors(){let f=[];for(let E=this;E;E=E.parent)f.push(E);return f}command(f,E,R){let S=E,w=R;if(typeof S==="object"&&S!==null)w=S,S=null;w=w||{};let[,$,T]=f.match(/([^ ]+) *(.*)/),_=this.createCommand($);if(S)_.description(S),_._executableHandler=!0;if(w.isDefault)this._defaultCommandName=_._name;if(_._hidden=!!(w.noHelp||w.hidden),_._executableFile=w.executableFile||null,T)_.arguments(T);if(this._registerCommand(_),_.parent=this,_.copyInheritedSettings(this),S)return this;return _}createCommand(f){return new v(f)}createHelp(){return Object.assign(new rE,this.configureHelp())}configureHelp(f){if(f===void 0)return this._helpConfiguration;return this._helpConfiguration=f,this}configureOutput(f){if(f===void 0)return this._outputConfiguration;return Object.assign(this._outputConfiguration,f),this}showHelpAfterError(f=!0){if(typeof f!=="string")f=!!f;return this._showHelpAfterError=f,this}showSuggestionAfterError(f=!0){return this._showSuggestionAfterError=!!f,this}addCommand(f,E){if(!f._name)throw Error(`Command passed to .addCommand() must have a name
|
|
12
|
+
- specify the name in Command constructor or using .name()`);if(E=E||{},E.isDefault)this._defaultCommandName=f._name;if(E.noHelp||E.hidden)f._hidden=!0;return this._registerCommand(f),f.parent=this,f._checkForBrokenPassThrough(),this}createArgument(f,E){return new yE(f,E)}argument(f,E,R,S){let w=this.createArgument(f,E);if(typeof R==="function")w.default(S).argParser(R);else w.default(R);return this.addArgument(w),this}arguments(f){return f.trim().split(/ +/).forEach((E)=>{this.argument(E)}),this}addArgument(f){let E=this.registeredArguments.slice(-1)[0];if(E&&E.variadic)throw Error(`only the last argument can be variadic '${E.name()}'`);if(f.required&&f.defaultValue!==void 0&&f.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${f.name()}'`);return this.registeredArguments.push(f),this}helpCommand(f,E){if(typeof f==="boolean")return this._addImplicitHelpCommand=f,this;f=f??"help [command]";let[,R,S]=f.match(/([^ ]+) *(.*)/),w=E??"display help for command",$=this.createCommand(R);if($.helpOption(!1),S)$.arguments(S);if(w)$.description(w);return this._addImplicitHelpCommand=!0,this._helpCommand=$,this}addHelpCommand(f,E){if(typeof f!=="object")return this.helpCommand(f,E),this;return this._addImplicitHelpCommand=!0,this._helpCommand=f,this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook(f,E){let R=["preSubcommand","preAction","postAction"];if(!R.includes(f))throw Error(`Unexpected value for event passed to hook : '${f}'.
|
|
13
|
+
Expecting one of '${R.join("', '")}'`);if(this._lifeCycleHooks[f])this._lifeCycleHooks[f].push(E);else this._lifeCycleHooks[f]=[E];return this}exitOverride(f){if(f)this._exitCallback=f;else this._exitCallback=(E)=>{if(E.code!=="commander.executeSubCommandAsync")throw E};return this}_exit(f,E,R){if(this._exitCallback)this._exitCallback(new O(f,E,R));I.exit(f)}action(f){let E=(R)=>{let S=this.registeredArguments.length,w=R.slice(0,S);if(this._storeOptionsAsProperties)w[S]=this;else w[S]=this.opts();return w.push(this),f.apply(this,w)};return this._actionHandler=E,this}createOption(f,E){return new Rf(f,E)}_callParseArg(f,E,R,S){try{return f.parseArg(E,R)}catch(w){if(w.code==="commander.invalidArgument"){let $=`${S} ${w.message}`;this.error($,{exitCode:w.exitCode,code:w.code})}throw w}}_registerOption(f){let E=f.short&&this._findOption(f.short)||f.long&&this._findOption(f.long);if(E){let R=f.long&&this._findOption(f.long)?f.long:f.short;throw Error(`Cannot add option '${f.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${R}'
|
|
14
|
+
- already used by option '${E.flags}'`)}this.options.push(f)}_registerCommand(f){let E=(S)=>{return[S.name()].concat(S.aliases())},R=E(f).find((S)=>this._findCommand(S));if(R){let S=E(this._findCommand(R)).join("|"),w=E(f).join("|");throw Error(`cannot add command '${w}' as already have command '${S}'`)}this.commands.push(f)}addOption(f){this._registerOption(f);let E=f.name(),R=f.attributeName();if(f.negate){let w=f.long.replace(/^--no-/,"--");if(!this._findOption(w))this.setOptionValueWithSource(R,f.defaultValue===void 0?!0:f.defaultValue,"default")}else if(f.defaultValue!==void 0)this.setOptionValueWithSource(R,f.defaultValue,"default");let S=(w,$,T)=>{if(w==null&&f.presetArg!==void 0)w=f.presetArg;let _=this.getOptionValue(R);if(w!==null&&f.parseArg)w=this._callParseArg(f,w,_,$);else if(w!==null&&f.variadic)w=f._concatValue(w,_);if(w==null)if(f.negate)w=!1;else if(f.isBoolean()||f.optional)w=!0;else w="";this.setOptionValueWithSource(R,w,T)};if(this.on("option:"+E,(w)=>{let $=`error: option '${f.flags}' argument '${w}' is invalid.`;S(w,$,"cli")}),f.envVar)this.on("optionEnv:"+E,(w)=>{let $=`error: option '${f.flags}' value '${w}' from env '${f.envVar}' is invalid.`;S(w,$,"env")});return this}_optionEx(f,E,R,S,w){if(typeof E==="object"&&E instanceof Rf)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let $=this.createOption(E,R);if($.makeOptionMandatory(!!f.mandatory),typeof S==="function")$.default(w).argParser(S);else if(S instanceof RegExp){let T=S;S=(_,y)=>{let L=T.exec(_);return L?L[0]:y},$.default(w).argParser(S)}else $.default(S);return this.addOption($)}option(f,E,R,S){return this._optionEx({},f,E,R,S)}requiredOption(f,E,R,S){return this._optionEx({mandatory:!0},f,E,R,S)}combineFlagAndOptionalValue(f=!0){return this._combineFlagAndOptionalValue=!!f,this}allowUnknownOption(f=!0){return this._allowUnknownOption=!!f,this}allowExcessArguments(f=!0){return this._allowExcessArguments=!!f,this}enablePositionalOptions(f=!0){return this._enablePositionalOptions=!!f,this}passThroughOptions(f=!0){return this._passThroughOptions=!!f,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(f=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!f,this}getOptionValue(f){if(this._storeOptionsAsProperties)return this[f];return this._optionValues[f]}setOptionValue(f,E){return this.setOptionValueWithSource(f,E,void 0)}setOptionValueWithSource(f,E,R){if(this._storeOptionsAsProperties)this[f]=E;else this._optionValues[f]=E;return this._optionValueSources[f]=R,this}getOptionValueSource(f){return this._optionValueSources[f]}getOptionValueSourceWithGlobals(f){let E;return this._getCommandAndAncestors().forEach((R)=>{if(R.getOptionValueSource(f)!==void 0)E=R.getOptionValueSource(f)}),E}_prepareUserArgs(f,E){if(f!==void 0&&!Array.isArray(f))throw Error("first parameter to parse must be array or undefined");if(E=E||{},f===void 0&&E.from===void 0){if(I.versions?.electron)E.from="electron";let S=I.execArgv??[];if(S.includes("-e")||S.includes("--eval")||S.includes("-p")||S.includes("--print"))E.from="eval"}if(f===void 0)f=I.argv;this.rawArgs=f.slice();let R;switch(E.from){case void 0:case"node":this._scriptPath=f[1],R=f.slice(2);break;case"electron":if(I.defaultApp)this._scriptPath=f[1],R=f.slice(2);else R=f.slice(1);break;case"user":R=f.slice(0);break;case"eval":R=f.slice(1);break;default:throw Error(`unexpected parse option { from: '${E.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",R}parse(f,E){let R=this._prepareUserArgs(f,E);return this._parseCommand([],R),this}async parseAsync(f,E){let R=this._prepareUserArgs(f,E);return await this._parseCommand([],R),this}_executeSubCommand(f,E){E=E.slice();let R=!1,S=[".js",".ts",".tsx",".mjs",".cjs"];function w(L,r){let J=q.resolve(L,r);if(h.existsSync(J))return J;if(S.includes(q.extname(r)))return;let P=S.find((U)=>h.existsSync(`${J}${U}`));if(P)return`${J}${P}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let $=f._executableFile||`${this._name}-${f._name}`,T=this._executableDir||"";if(this._scriptPath){let L;try{L=h.realpathSync(this._scriptPath)}catch(r){L=this._scriptPath}T=q.resolve(q.dirname(L),T)}if(T){let L=w(T,$);if(!L&&!f._executableFile&&this._scriptPath){let r=q.basename(this._scriptPath,q.extname(this._scriptPath));if(r!==this._name)L=w(T,`${r}-${f._name}`)}$=L||$}R=S.includes(q.extname($));let _;if(I.platform!=="win32")if(R)E.unshift($),E=wf(I.execArgv).concat(E),_=C.spawn(I.argv[0],E,{stdio:"inherit"});else _=C.spawn($,E,{stdio:"inherit"});else E.unshift($),E=wf(I.execArgv).concat(E),_=C.spawn(I.execPath,E,{stdio:"inherit"});if(!_.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((r)=>{I.on(r,()=>{if(_.killed===!1&&_.exitCode===null)_.kill(r)})});let y=this._exitCallback;_.on("close",(L)=>{if(L=L??1,!y)I.exit(L);else y(new O(L,"commander.executeSubCommandAsync","(close)"))}),_.on("error",(L)=>{if(L.code==="ENOENT"){let r=T?`searched for local subcommand relative to directory '${T}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",J=`'${$}' does not exist
|
|
15
|
+
- if '${f._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
16
16
|
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
17
|
-
- ${
|
|
17
|
+
- ${r}`;throw Error(J)}else if(L.code==="EACCES")throw Error(`'${$}' not executable`);if(!y)I.exit(1);else{let r=new O(1,"commander.executeSubCommandAsync","(error)");r.nestedError=L,y(r)}}),this.runningCommand=_}_dispatchSubcommand(f,E,R){let S=this._findCommand(f);if(!S)this.help({error:!0});let w;return w=this._chainOrCallSubCommandHook(w,S,"preSubcommand"),w=this._chainOrCall(w,()=>{if(S._executableHandler)this._executeSubCommand(S,E.concat(R));else return S._parseCommand(E,R)}),w}_dispatchHelpCommand(f){if(!f)this.help();let E=this._findCommand(f);if(E&&!E._executableHandler)E.help();return this._dispatchSubcommand(f,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach((f,E)=>{if(f.required&&this.args[E]==null)this.missingArgument(f.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let f=(R,S,w)=>{let $=S;if(S!==null&&R.parseArg){let T=`error: command-argument value '${S}' is invalid for argument '${R.name()}'.`;$=this._callParseArg(R,S,w,T)}return $};this._checkNumberOfArguments();let E=[];this.registeredArguments.forEach((R,S)=>{let w=R.defaultValue;if(R.variadic){if(S<this.args.length){if(w=this.args.slice(S),R.parseArg)w=w.reduce(($,T)=>{return f(R,T,$)},R.defaultValue)}else if(w===void 0)w=[]}else if(S<this.args.length){if(w=this.args[S],R.parseArg)w=f(R,w,R.defaultValue)}E[S]=w}),this.processedArgs=E}_chainOrCall(f,E){if(f&&f.then&&typeof f.then==="function")return f.then(()=>E());return E()}_chainOrCallHooks(f,E){let R=f,S=[];if(this._getCommandAndAncestors().reverse().filter((w)=>w._lifeCycleHooks[E]!==void 0).forEach((w)=>{w._lifeCycleHooks[E].forEach(($)=>{S.push({hookedCommand:w,callback:$})})}),E==="postAction")S.reverse();return S.forEach((w)=>{R=this._chainOrCall(R,()=>{return w.callback(w.hookedCommand,this)})}),R}_chainOrCallSubCommandHook(f,E,R){let S=f;if(this._lifeCycleHooks[R]!==void 0)this._lifeCycleHooks[R].forEach((w)=>{S=this._chainOrCall(S,()=>{return w(this,E)})});return S}_parseCommand(f,E){let R=this.parseOptions(E);if(this._parseOptionsEnv(),this._parseOptionsImplied(),f=f.concat(R.operands),E=R.unknown,this.args=f.concat(E),f&&this._findCommand(f[0]))return this._dispatchSubcommand(f[0],f.slice(1),E);if(this._getHelpCommand()&&f[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(f[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(E),this._dispatchSubcommand(this._defaultCommandName,f,E);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(R.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let S=()=>{if(R.unknown.length>0)this.unknownOption(R.unknown[0])},w=`command:${this.name()}`;if(this._actionHandler){S(),this._processArguments();let $;if($=this._chainOrCallHooks($,"preAction"),$=this._chainOrCall($,()=>this._actionHandler(this.processedArgs)),this.parent)$=this._chainOrCall($,()=>{this.parent.emit(w,f,E)});return $=this._chainOrCallHooks($,"postAction"),$}if(this.parent&&this.parent.listenerCount(w))S(),this._processArguments(),this.parent.emit(w,f,E);else if(f.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",f,E);if(this.listenerCount("command:*"))this.emit("command:*",f,E);else if(this.commands.length)this.unknownCommand();else S(),this._processArguments()}else if(this.commands.length)S(),this.help({error:!0});else S(),this._processArguments()}_findCommand(f){if(!f)return;return this.commands.find((E)=>E._name===f||E._aliases.includes(f))}_findOption(f){return this.options.find((E)=>E.is(f))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach((f)=>{f.options.forEach((E)=>{if(E.mandatory&&f.getOptionValue(E.attributeName())===void 0)f.missingMandatoryOptionValue(E)})})}_checkForConflictingLocalOptions(){let f=this.options.filter((R)=>{let S=R.attributeName();if(this.getOptionValue(S)===void 0)return!1;return this.getOptionValueSource(S)!=="default"});f.filter((R)=>R.conflictsWith.length>0).forEach((R)=>{let S=f.find((w)=>R.conflictsWith.includes(w.attributeName()));if(S)this._conflictingOption(R,S)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach((f)=>{f._checkForConflictingLocalOptions()})}parseOptions(f){let E=[],R=[],S=E,w=f.slice();function $(_){return _.length>1&&_[0]==="-"}let T=null;while(w.length){let _=w.shift();if(_==="--"){if(S===R)S.push(_);S.push(...w);break}if(T&&!$(_)){this.emit(`option:${T.name()}`,_);continue}if(T=null,$(_)){let y=this._findOption(_);if(y){if(y.required){let L=w.shift();if(L===void 0)this.optionMissingArgument(y);this.emit(`option:${y.name()}`,L)}else if(y.optional){let L=null;if(w.length>0&&!$(w[0]))L=w.shift();this.emit(`option:${y.name()}`,L)}else this.emit(`option:${y.name()}`);T=y.variadic?y:null;continue}}if(_.length>2&&_[0]==="-"&&_[1]!=="-"){let y=this._findOption(`-${_[1]}`);if(y){if(y.required||y.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${y.name()}`,_.slice(2));else this.emit(`option:${y.name()}`),w.unshift(`-${_.slice(2)}`);continue}}if(/^--[^=]+=/.test(_)){let y=_.indexOf("="),L=this._findOption(_.slice(0,y));if(L&&(L.required||L.optional)){this.emit(`option:${L.name()}`,_.slice(y+1));continue}}if($(_))S=R;if((this._enablePositionalOptions||this._passThroughOptions)&&E.length===0&&R.length===0){if(this._findCommand(_)){if(E.push(_),w.length>0)R.push(...w);break}else if(this._getHelpCommand()&&_===this._getHelpCommand().name()){if(E.push(_),w.length>0)E.push(...w);break}else if(this._defaultCommandName){if(R.push(_),w.length>0)R.push(...w);break}}if(this._passThroughOptions){if(S.push(_),w.length>0)S.push(...w);break}S.push(_)}return{operands:E,unknown:R}}opts(){if(this._storeOptionsAsProperties){let f={},E=this.options.length;for(let R=0;R<E;R++){let S=this.options[R].attributeName();f[S]=S===this._versionOptionName?this._version:this[S]}return f}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((f,E)=>Object.assign(f,E.opts()),{})}error(f,E){if(this._outputConfiguration.outputError(`${f}
|
|
18
18
|
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError==="string")this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
19
19
|
`);else if(this._showHelpAfterError)this._outputConfiguration.writeErr(`
|
|
20
|
-
`),this.outputHelp({error:!0});let R=
|
|
21
|
-
`),this._exit(0,"commander.version",
|
|
22
|
-
Expecting one of '${R.join("', '")}'`);let
|
|
23
|
-
`)}),this}_outputHelpIfRequested(
|
|
24
|
-
`;if(await
|
|
25
|
-
`).filter((
|
|
26
|
-
`)}var
|
|
20
|
+
`),this.outputHelp({error:!0});let R=E||{},S=R.exitCode||1,w=R.code||"commander.error";this._exit(S,w,f)}_parseOptionsEnv(){this.options.forEach((f)=>{if(f.envVar&&f.envVar in I.env){let E=f.attributeName();if(this.getOptionValue(E)===void 0||["default","config","env"].includes(this.getOptionValueSource(E)))if(f.required||f.optional)this.emit(`optionEnv:${f.name()}`,I.env[f.envVar]);else this.emit(`optionEnv:${f.name()}`)}})}_parseOptionsImplied(){let f=new IE(this.options),E=(R)=>{return this.getOptionValue(R)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(R))};this.options.filter((R)=>R.implied!==void 0&&E(R.attributeName())&&f.valueFromOption(this.getOptionValue(R.attributeName()),R)).forEach((R)=>{Object.keys(R.implied).filter((S)=>!E(S)).forEach((S)=>{this.setOptionValueWithSource(S,R.implied[S],"implied")})})}missingArgument(f){let E=`error: missing required argument '${f}'`;this.error(E,{code:"commander.missingArgument"})}optionMissingArgument(f){let E=`error: option '${f.flags}' argument missing`;this.error(E,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(f){let E=`error: required option '${f.flags}' not specified`;this.error(E,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(f,E){let R=($)=>{let T=$.attributeName(),_=this.getOptionValue(T),y=this.options.find((r)=>r.negate&&T===r.attributeName()),L=this.options.find((r)=>!r.negate&&T===r.attributeName());if(y&&(y.presetArg===void 0&&_===!1||y.presetArg!==void 0&&_===y.presetArg))return y;return L||$},S=($)=>{let T=R($),_=T.attributeName();if(this.getOptionValueSource(_)==="env")return`environment variable '${T.envVar}'`;return`option '${T.flags}'`},w=`error: ${S(f)} cannot be used with ${S(E)}`;this.error(w,{code:"commander.conflictingOption"})}unknownOption(f){if(this._allowUnknownOption)return;let E="";if(f.startsWith("--")&&this._showSuggestionAfterError){let S=[],w=this;do{let $=w.createHelp().visibleOptions(w).filter((T)=>T.long).map((T)=>T.long);S=S.concat($),w=w.parent}while(w&&!w._enablePositionalOptions);E=Sf(f,S)}let R=`error: unknown option '${f}'${E}`;this.error(R,{code:"commander.unknownOption"})}_excessArguments(f){if(this._allowExcessArguments)return;let E=this.registeredArguments.length,R=E===1?"":"s",w=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${E} argument${R} but got ${f.length}.`;this.error(w,{code:"commander.excessArguments"})}unknownCommand(){let f=this.args[0],E="";if(this._showSuggestionAfterError){let S=[];this.createHelp().visibleCommands(this).forEach((w)=>{if(S.push(w.name()),w.alias())S.push(w.alias())}),E=Sf(f,S)}let R=`error: unknown command '${f}'${E}`;this.error(R,{code:"commander.unknownCommand"})}version(f,E,R){if(f===void 0)return this._version;this._version=f,E=E||"-V, --version",R=R||"output the version number";let S=this.createOption(E,R);return this._versionOptionName=S.attributeName(),this._registerOption(S),this.on("option:"+S.name(),()=>{this._outputConfiguration.writeOut(`${f}
|
|
21
|
+
`),this._exit(0,"commander.version",f)}),this}description(f,E){if(f===void 0&&E===void 0)return this._description;if(this._description=f,E)this._argsDescription=E;return this}summary(f){if(f===void 0)return this._summary;return this._summary=f,this}alias(f){if(f===void 0)return this._aliases[0];let E=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)E=this.commands[this.commands.length-1];if(f===E._name)throw Error("Command alias can't be the same as its name");let R=this.parent?._findCommand(f);if(R){let S=[R.name()].concat(R.aliases()).join("|");throw Error(`cannot add alias '${f}' to command '${this.name()}' as already have command '${S}'`)}return E._aliases.push(f),this}aliases(f){if(f===void 0)return this._aliases;return f.forEach((E)=>this.alias(E)),this}usage(f){if(f===void 0){if(this._usage)return this._usage;let E=this.registeredArguments.map((R)=>{return LE(R)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?E:[]).join(" ")}return this._usage=f,this}name(f){if(f===void 0)return this._name;return this._name=f,this}nameFromFilename(f){return this._name=q.basename(f,q.extname(f)),this}executableDir(f){if(f===void 0)return this._executableDir;return this._executableDir=f,this}helpInformation(f){let E=this.createHelp();if(E.helpWidth===void 0)E.helpWidth=f&&f.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth();return E.formatHelp(this,E)}_getHelpContext(f){f=f||{};let E={error:!!f.error},R;if(E.error)R=(S)=>this._outputConfiguration.writeErr(S);else R=(S)=>this._outputConfiguration.writeOut(S);return E.write=f.write||R,E.command=this,E}outputHelp(f){let E;if(typeof f==="function")E=f,f=void 0;let R=this._getHelpContext(f);this._getCommandAndAncestors().reverse().forEach((w)=>w.emit("beforeAllHelp",R)),this.emit("beforeHelp",R);let S=this.helpInformation(R);if(E){if(S=E(S),typeof S!=="string"&&!Buffer.isBuffer(S))throw Error("outputHelp callback must return a string or a Buffer")}if(R.write(S),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",R),this._getCommandAndAncestors().forEach((w)=>w.emit("afterAllHelp",R))}helpOption(f,E){if(typeof f==="boolean"){if(f)this._helpOption=this._helpOption??void 0;else this._helpOption=null;return this}return f=f??"-h, --help",E=E??"display help for command",this._helpOption=this.createOption(f,E),this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption(f){return this._helpOption=f,this}help(f){this.outputHelp(f);let E=I.exitCode||0;if(E===0&&f&&typeof f!=="function"&&f.error)E=1;this._exit(E,"commander.help","(outputHelp)")}addHelpText(f,E){let R=["beforeAll","before","after","afterAll"];if(!R.includes(f))throw Error(`Unexpected value for position to addHelpText.
|
|
22
|
+
Expecting one of '${R.join("', '")}'`);let S=`${f}Help`;return this.on(S,(w)=>{let $;if(typeof E==="function")$=E({error:w.error,command:w.command});else $=E;if($)w.write(`${$}
|
|
23
|
+
`)}),this}_outputHelpIfRequested(f){let E=this._getHelpOption();if(E&&f.find((S)=>E.is(S)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function wf(f){return f.map((E)=>{if(!E.startsWith("--inspect"))return E;let R,S="127.0.0.1",w="9229",$;if(($=E.match(/^(--inspect(-brk)?)$/))!==null)R=$[1];else if(($=E.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(R=$[1],/^\d+$/.test($[3]))w=$[3];else S=$[3];else if(($=E.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)R=$[1],S=$[3],w=$[4];if(R&&w!=="0")return`${R}=${S}:${parseInt(w)+1}`;return E})}UE.Command=v});var Lf=M((qE)=>{var{Argument:Tf}=K(),{Command:c}=$f(),{CommanderError:tE,InvalidArgumentError:_f}=Q(),{Help:PE}=b(),{Option:yf}=s();qE.program=new c;qE.createCommand=(f)=>new c(f);qE.createOption=(f,E)=>new yf(f,E);qE.createArgument=(f,E)=>new Tf(f,E);qE.Command=c;qE.Option=yf;qE.Argument=Tf;qE.Help=PE;qE.CommanderError=tE;qE.InvalidArgumentError=_f;qE.InvalidOptionArgumentError=_f});var rf=bf(Lf(),1),{program:uR,createCommand:AR,createArgument:VR,createOption:xR,CommanderError:bR,InvalidArgumentError:sR,InvalidOptionArgumentError:CR,Command:t,Argument:hR,Option:OR,Help:vR}=rf.default;import{readFile as pE}from"node:fs/promises";import{resolve as aE}from"node:path";var If={name:"@shotstack/cli",version:"0.2.0",description:"Command-line interface for the Shotstack video rendering API.",license:"Apache-2.0",homepage:"https://github.com/shotstack/shotstack-cli",repository:{type:"git",url:"git+https://github.com/shotstack/shotstack-cli.git"},bugs:{url:"https://github.com/shotstack/shotstack-cli/issues"},type:"module",bin:{shotstack:"dist/shotstack.js"},files:["dist/shotstack.js","SKILL.md","references"],scripts:{start:"bun run src/index.ts",build:"bun build src/index.ts --target=node --minify --outfile=dist/shotstack.js --banner='#!/usr/bin/env node' && chmod +x dist/shotstack.js",prepack:"bun run build",typecheck:"tsc --noEmit",test:"bun test"},dependencies:{commander:"^12.1.0"},devDependencies:{"@types/bun":"latest",typescript:"^5.6.0"}};var H=If.version,Uf=`shotstack-cli/${H} (${process.platform}-${process.arch})`;class G extends Error{status;body;constructor(f,E,R){super(R);this.status=f;this.body=E;this.name="ApiError"}get isTransient(){return this.status>=500||this.status===429}}function W(f){let E=f.env.baseUrl.replace(/\/$/,"");async function R(S,w,$){let T=await fetch(`${E}${w}`,{method:S,headers:{"x-api-key":f.apiKey,"x-shotstack-origin":"cli","x-shotstack-environment":f.env.name,"user-agent":Uf,...$!==void 0?{"content-type":"application/json"}:{}},body:$!==void 0?JSON.stringify($):void 0}),_=await T.text(),y=_?WE(_):void 0;if(!T.ok)throw new G(T.status,y??_,`${S} ${w} → ${T.status} ${T.statusText}`);return y}return{post:(S,w)=>R("POST",S,w),get:(S)=>R("GET",S)}}function WE(f){try{return JSON.parse(f)}catch{return f}}class j extends Error{constructor(){super("SHOTSTACK_API_KEY is not set. Get a key at https://shotstack.io.");this.name="MissingApiKeyError"}}function D(){let f=process.env.SHOTSTACK_API_KEY?.trim();if(!f)throw new j;return f}var Jf={dev:"https://api.shotstack.io/edit/dev",stage:"https://api.shotstack.io/edit/stage",v1:"https://api.shotstack.io/edit/v1"},X=Object.keys(Jf);class z extends Error{constructor(f){super(`Invalid environment "${f}". Use one of: ${X.join(", ")}.`);this.name="InvalidEnvError"}}function F(f){let E=process.env.SHOTSTACK_API_BASE_URL?.trim();if(E)return{name:"custom",baseUrl:E};let R=f??process.env.SHOTSTACK_ENV?.trim()??"v1";if(!DE(R))throw new z(R);return{name:R,baseUrl:Jf[R]}}function DE(f){return X.includes(f)}function B(f){if(f==="json")return"json";return"text"}function Z(f,E,R){if(f==="json")console.log(JSON.stringify(E));else console.log(R)}import{mkdir as FE,appendFile as kE,stat as Yf,readFile as uE,writeFile as Mf}from"node:fs/promises";import{join as n,dirname as AE}from"node:path";import{homedir as tf}from"node:os";var VE=1e6,xE=500000,Pf=2000;function k(){if(process.platform==="win32"){let f=process.env.APPDATA??n(tf(),"AppData","Roaming");return n(f,"shotstack","log.jsonl")}return n(tf(),".shotstack","log.jsonl")}function bE(f,E=new Date){let R={ts:E.toISOString(),cmd:f.cmd,args:f.args.map(nE),exit:f.exit,durationMs:f.durationMs};if(f.renderId)R.renderId=f.renderId;if(f.response!==void 0)R.response=gE(i(f.response));if(f.error)R.error=sE(f.error);return R}function sE(f){return{name:f.name,message:typeof f.message==="string"?g(f.message):String(f.message)}}function CE(f){if(f instanceof Error)return{name:f.name,message:f.message};if(f===void 0||f===null)return;return{name:"Unknown",message:String(f)}}async function qf(f,E=k()){let R=bE(f),S=JSON.stringify(R)+`
|
|
24
|
+
`;if(await FE(AE(E),{recursive:!0,mode:448}),!await hE(E))await Mf(E,"",{mode:384});await kE(E,S),await OE(E)}async function hE(f){try{return await Yf(f),!0}catch{return!1}}async function OE(f){let E=await Yf(f).catch(()=>null);if(!E||E.size<=VE)return;let R=await uE(f),S=R.subarray(Math.max(0,R.length-xE)),w=S.indexOf(10),$=w>=0?S.subarray(w+1):S;await Mf(f,$,{mode:384})}var vE=/^https?:\/\//i,cE=/(https?:\/\/[^\s'"<>]+?)\?[^\s'"<>]*?(?:Signature|X-Amz-[A-Za-z0-9-]*)=[^\s'"<>]*/gi;function g(f){return f.replace(cE,"$1?[redacted-signed]")}function nE(f){if(typeof f!=="string")return f;if(f.startsWith("-"))return f;if(vE.test(f))return g(f);if(/[\/\\]/.test(f))return iE(f);return f}function iE(f){let E=f.split(/[\/\\]/);return E[E.length-1]||f}function i(f){if(typeof f==="string")return g(f);if(Array.isArray(f))return f.map(i);if(f&&typeof f==="object"){let E={};for(let[R,S]of Object.entries(f))E[R]=i(S);return E}return f}function gE(f){let E=JSON.stringify(f);if(E===void 0||E.length<=Pf)return f;return E.slice(0,Pf)+"...[truncated]"}async function u(f,E,R){let S=Date.now();try{let w=await R(),$=w.exitCode??0;if(await qf({cmd:f,args:E,exit:$,durationMs:Date.now()-S,renderId:w.renderId,response:w.response}).catch(()=>{}),$!==0)process.exit($)}catch(w){let $=mE(w),T=w instanceof G?w.body:void 0;throw await qf({cmd:f,args:E,exit:$,durationMs:Date.now()-S,response:T,error:CE(w)}).catch(()=>{}),w}}function mE(f){if(f instanceof G)return f.isTransient?2:1;if(f instanceof j||f instanceof z)return 1;if(f instanceof Error&&f.code==="ENOENT")return 1;return 2}function A(f){let E=process.argv.slice(2),R=E.indexOf(f);return R>=0?E.slice(R+1):E}var lE=new Set(["done","failed"]),dE=3000,Gf=new t("status").description("Poll the status of a Shotstack render").argument("<id>","Render ID returned by `shotstack render`").option("--watch","Poll continuously until the render reaches a terminal state").option("--env <name>",`Environment: ${X.join(" | ")}`).option("--output <format>","Output format: text | json","text").action(async(f,E)=>{await u("status",A("status"),async()=>{let R=B(E.output),S=D(),w=F(E.env),$=W({apiKey:S,env:w}),T=await m($,f,R,E.watch===!0),_=T.status==="failed"?1:0;return{renderId:T.id,response:T,exitCode:_}})});async function m(f,E,R,S){while(!0){let $=(await f.get(`/render/${encodeURIComponent(E)}`)).response;if(Z(R,$,oE($)),!S||lE.has($.status))return $;await eE(dE)}}function oE(f){let E=[f.status];if(f.url)E.push(f.url);if(f.error)E.push(`error: ${f.error}`);return E.join(" ")}function eE(f){return new Promise((E)=>setTimeout(E,f))}var jf=new t("render").description("Submit a Shotstack Edit JSON to the render API").argument("<file>","Path to a Shotstack Edit JSON file").option("--env <name>",`Environment: ${X.join(" | ")}`).option("--watch","After submitting, poll until the render reaches a terminal state").option("--output <format>","Output format: text | json","text").action(async(f,E)=>{await u("render",A("render"),async()=>{let R=B(E.output),S=D(),w=F(E.env),$=aE(process.cwd(),f),T=await pE($,"utf8"),_=JSON.parse(T),y=W({apiKey:S,env:w}),L=await y.post("/render",_),r=L.response.id;if(!E.watch)return Z(R,{id:r},r),{renderId:r,response:L.response};let J=await m(y,r,R,!0),P=J.status==="failed"?1:0;return{renderId:r,response:J,exitCode:P}})});import{readFile as fR,writeFile as ER,mkdtemp as RR}from"node:fs/promises";import{tmpdir as SR}from"node:os";import{join as Xf}from"node:path";import{spawn as wR}from"node:child_process";var zf="https://github.com/shotstack/shotstack-cli/issues/new?template=bug.yml",$R=6000,Qf=5,Hf=new t("feedback").description("Open a pre-filled GitHub issue with a flight-recorder dossier from your last 5 invocations").action(async()=>{let f=await TR(Qf),E=_R(f),R=LR(f),S=`&title=${encodeURIComponent(R)}`,w=`${zf}${S}&body=${encodeURIComponent(E)}`;if(w.length<=$R){Nf(w),console.log("Opened browser with pre-filled issue. Review before submitting.");return}let $=await RR(Xf(SR(),"shotstack-feedback-")),T=Xf($,"dossier.md");await ER(T,E),Nf(`${zf}${S}`),console.log(`Dossier too large to inline. Saved to: ${T}`),console.log("Drag the file into the issue body, or paste its contents.")});async function TR(f){let E=k(),R;try{R=await fR(E,"utf8")}catch{return[]}let w=R.split(`
|
|
25
|
+
`).filter((T)=>T.trim().length>0).slice(-f).reverse(),$=[];for(let T of w)try{$.push(JSON.parse(T))}catch{}return $}function _R(f){let E=[];if(E.push("## Environment"),E.push(`- Shotstack CLI: ${H}`),E.push(`- OS: ${process.platform}-${process.arch}`),E.push(""),E.push(`## Last ${Qf} invocations (most recent first)`),E.push(""),f.length===0)E.push("_No recorded invocations._");else for(let R of f){let S=(R.args??[]).join(" "),w=`### ${R.ts} — shotstack ${R.cmd}${S?" "+S:""}`;if(E.push(w),E.push(`- Exit: ${R.exit} Duration: ${R.durationMs}ms`),R.renderId)E.push(`- Render ID: ${R.renderId}`);if(R.response!==void 0){let $=typeof R.response==="string"?R.response:JSON.stringify(R.response);E.push(`- Response: ${$}`)}if(R.error)E.push(`- Error: ${R.error.name}: ${R.error.message}`);E.push("")}return E.push(`[full log at ${k()}]`),E.push(""),E.push("## What I expected vs what happened"),E.push("<!-- Describe the issue, request, or question here. -->"),E.join(`
|
|
26
|
+
`)}var Bf=80,yR="Feedback from shotstack CLI";function LR(f){let E=f.find((w)=>w.error);if(E&&E.error)return l(`${E.cmd}: ${E.error.name} — ${E.error.message}`);let R=f.find((w)=>Zf(w.response)!==null);if(R){let w=Zf(R.response);return l(`Render failed: ${w}`)}let S=f.find((w)=>w.exit!==0);if(S)return l(`${S.cmd} exited ${S.exit}`);return yR}function Zf(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let E=f;if(E.state!=="failed")return null;return typeof E.error==="string"&&E.error.length>0?E.error:"unknown error"}function l(f){return f.length<=Bf?f:f.slice(0,Bf-1)+"…"}function Nf(f){let E=process.platform==="win32",R=process.platform==="darwin"?"open":E?"cmd":"xdg-open",w=wR(R,E?["/c","start","",f]:[f],{stdio:"ignore",detached:!0});w.on("error",()=>{console.error(`Could not open browser. Visit: ${f}`)}),w.unref()}import{readFile as rR}from"node:fs/promises";import{resolve as IR}from"node:path";import{spawn as Kf,execSync as UR}from"node:child_process";var JR="https://shotstack.studio",tR=6000,Wf=new t("preview").description("Open a shotstack.studio URL that loads the Edit JSON in the browser editor").argument("<file>","Path to a Shotstack Edit JSON file").option("--copy","Copy the URL to the clipboard").option("--no-open","Do not try to open the URL in a browser").option("--output <format>","Output format: text | json","text").action(async(f,E)=>{let R=B(E.output),S=IR(process.cwd(),f),w=await rR(S,"utf8"),$=JSON.parse(w);qR($);let T=PR($);if(T.length>tR)console.error(`warning: encoded URL is ${T.length} characters; large templates may exceed browser URL limits.`);if(E.copy)await YR(T);let _=E.open&&XR()&&GR(T);if(R==="json"||!_)Z(R,{url:T},T)});function PR(f){let E=Buffer.from(JSON.stringify(f),"utf8").toString("base64url");return`${JR}/#json=${E}`}function qR(f){if(!f||typeof f!=="object")throw Error("Template must be a JSON object.");if(!("timeline"in f))throw Error("Template missing required field: timeline.");if(!("output"in f))throw Error("Template missing required field: output.")}async function YR(f){let{cmd:E,args:R}=MR();await new Promise((S,w)=>{let $=Kf(E,R,{stdio:["pipe","ignore","ignore"]});$.on("error",w),$.on("exit",(T)=>T===0?S():w(Error(`${E} exited ${T}`))),$.stdin.end(f)})}function MR(){if(process.platform==="darwin")return{cmd:"pbcopy",args:[]};if(process.platform==="win32")return{cmd:"clip",args:[]};return{cmd:"xclip",args:["-selection","clipboard"]}}function GR(f){let{cmd:E,args:R}=jR(f);try{let S=Kf(E,R,{detached:!0,stdio:"ignore"});return S.on("error",()=>{}),S.unref(),!0}catch{return!1}}function jR(f){if(process.platform==="win32")return{cmd:"cmd",args:["/c","start","",f]};if(process.platform==="darwin")return{cmd:"open",args:[f]};return{cmd:"xdg-open",args:[f]}}function XR(){if(process.platform==="darwin"||process.platform==="win32")return!0;if(!process.env.DISPLAY&&!process.env.WAYLAND_DISPLAY)return!1;try{return UR("command -v xdg-open",{stdio:"ignore"}),!0}catch{return!1}}var zR=new t().name("shotstack").description("Command-line interface for the Shotstack video rendering API").version(H).addCommand(jf).addCommand(Gf).addCommand(Wf).addCommand(Hf);try{await zR.parseAsync(process.argv)}catch(f){process.exit(BR(f))}function BR(f){if(f instanceof j||f instanceof z)return console.error(f.message),1;if(f instanceof G){if(console.error(f.message),f.body)console.error(typeof f.body==="string"?f.body:JSON.stringify(f.body));return f.isTransient?2:1}if(f instanceof Error){if("code"in f&&f.code==="ENOENT")return console.error(f.message),1;return console.error(f.message),2}return console.error(String(f)),2}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shotstack/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Command-line interface for the Shotstack video rendering API.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/shotstack/shotstack-cli",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"type": "module",
|
|
15
15
|
"bin": {
|
|
16
|
-
"shotstack": "
|
|
16
|
+
"shotstack": "dist/shotstack.js"
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist/shotstack.js",
|
package/references/timeline.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Timeline conventions
|
|
2
2
|
|
|
3
|
-
Detailed guide to track layering, the soundtrack vs audio distinction, and `timeline.fonts[]`. Read this when building any non-trivial
|
|
3
|
+
Detailed guide to track layering, the soundtrack vs audio distinction, and `timeline.fonts[]`. Read this when building any non-trivial Edit JSON.
|
|
4
4
|
|
|
5
5
|
## Contents
|
|
6
6
|
|
|
@@ -74,13 +74,7 @@ If you put the video first and the captions last, the video covers the captions
|
|
|
74
74
|
|
|
75
75
|
## Soundtrack vs audio asset
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
| Use `timeline.soundtrack` when | Use `audio` asset when |
|
|
80
|
-
|---|---|
|
|
81
|
-
| One background music track for the entire timeline | Sound effects at specific times |
|
|
82
|
-
| Loop or fade the music | Voiceover synced to specific clips |
|
|
83
|
-
| You don't need to control timing | Multiple audio sources at different times |
|
|
77
|
+
Prefer `Audio` assets — they support custom timing, keyframes, and effects, and can do everything `timeline.soundtrack` can. Use `timeline.soundtrack` only when you want a single background track spanning the whole edit.
|
|
84
78
|
|
|
85
79
|
```json
|
|
86
80
|
{
|
|
@@ -94,7 +88,9 @@ There are two ways to add audio. Pick the right one.
|
|
|
94
88
|
}
|
|
95
89
|
```
|
|
96
90
|
|
|
97
|
-
|
|
91
|
+
`soundtrack.effect` accepts `fadeIn`, `fadeOut`, or `fadeInFadeOut`.
|
|
92
|
+
|
|
93
|
+
An `audio` clip with `length: "end"` is functionally identical to `timeline.soundtrack`.
|
|
98
94
|
|
|
99
95
|
## `timeline.fonts[]` for custom fonts
|
|
100
96
|
|
|
@@ -13,7 +13,7 @@ Common errors and the fix for each. If your error isn't here, run `shotstack fee
|
|
|
13
13
|
- "Invalid asset URL"
|
|
14
14
|
- "Render failed" with no other detail
|
|
15
15
|
- Render takes much longer than expected
|
|
16
|
-
-
|
|
16
|
+
- Credits exhausted on stage environment
|
|
17
17
|
|
|
18
18
|
## "Unknown property: alignment" (and similar)
|
|
19
19
|
|
|
@@ -28,7 +28,7 @@ You used a property name from CSS or HTML instinct — `alignment`, `font.name`,
|
|
|
28
28
|
| `duration` | `length` |
|
|
29
29
|
| `transitions: [...]` (array) | `transition: { in, out }` (object) |
|
|
30
30
|
|
|
31
|
-
Always check <https://shotstack.io/docs/api/api.
|
|
31
|
+
Always check <https://shotstack.io/docs/api/api.edit.json> (OpenAPI Schema) or <https://shotstack.io/docs/guide/llms-full.txt> before composing Edit JSON. Don't guess from CSS conventions.
|
|
32
32
|
|
|
33
33
|
## "Invalid option: expected one of top|middle|bottom"
|
|
34
34
|
|
|
@@ -91,11 +91,11 @@ Renders containing AI-generation assets (`text-to-image`, `image-to-video`) take
|
|
|
91
91
|
|
|
92
92
|
**Fix:** if you're iterating quickly, render with `output.resolution: "preview"` first (512×288 @ 15fps) to validate the timeline shape before spending credits on full-resolution output.
|
|
93
93
|
|
|
94
|
-
##
|
|
94
|
+
## Credits exhausted on stage environment
|
|
95
95
|
|
|
96
|
-
The `stage` environment uses
|
|
96
|
+
The `stage` environment uses no credits, but you do require a positive credit balance to make use of the sandbox.
|
|
97
97
|
|
|
98
|
-
**Fix:**
|
|
98
|
+
**Fix:** add more credits to your account. Check current credit balance at <https://app.shotstack.io>.
|
|
99
99
|
|
|
100
100
|
## Filing a useful bug report
|
|
101
101
|
|