diff --git a/build_ts/index.ts b/build_ts/index.ts index 311bef4..8a72839 100644 --- a/build_ts/index.ts +++ b/build_ts/index.ts @@ -2,13 +2,13 @@ export interface Workflow { slug: WorkflowSlug; name: string; command: string; - tags?: [string]; + tags?: string[]; description?: string; - arguments?: [Argument]; + arguments?: Argument[]; source_url?: string; author?: string; author_url?: string; - shells?: [Shell]; + shells?: Shell[]; relative_git_url: string; } diff --git a/build_ts/package.json b/build_ts/package.json index c6e5790..6cf11c5 100644 --- a/build_ts/package.json +++ b/build_ts/package.json @@ -6,6 +6,7 @@ "types": "dist/index.d.ts", "scripts": { "build": "tsc && webpack", + "check-types": "tsc -p tsconfig.typetest.json", "prepare": "npm run build" }, "author": "Warp Team (eng@warp.dev)", diff --git a/build_ts/tsconfig.json b/build_ts/tsconfig.json index 4682020..b50d848 100644 --- a/build_ts/tsconfig.json +++ b/build_ts/tsconfig.json @@ -9,5 +9,6 @@ "strict": true, "esModuleInterop": true, "moduleResolution": "node" - } + }, + "exclude": ["node_modules", "dist", "type-tests"] } diff --git a/build_ts/tsconfig.typetest.json b/build_ts/tsconfig.typetest.json new file mode 100644 index 0000000..8270b93 --- /dev/null +++ b/build_ts/tsconfig.typetest.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "declaration": false, + "sourceMap": false + }, + "include": ["index.ts", "type-tests/**/*.ts"] +} diff --git a/build_ts/type-tests/workflow-types.test-d.ts b/build_ts/type-tests/workflow-types.test-d.ts new file mode 100644 index 0000000..12aa056 --- /dev/null +++ b/build_ts/type-tests/workflow-types.test-d.ts @@ -0,0 +1,48 @@ +// Type-level regression test for the exported `Workflow` interface. +// +// These declarations do not run; they exist so that `tsc` fails to compile if +// the multi-value fields (`tags`, `arguments`, `shells`) are ever narrowed back +// to single-element tuple types. Every literal below mirrors an example that is +// already documented in FORMAT.md / README.md or shipped under specs/. +// +// Compile with: npm run check-types + +import { Argument, Shell, Workflow } from "../index"; + +// Mirrors FORMAT.md's own for-loop example, which documents a command with the +// three arguments `variable`, `sequence`, and `command`, alongside a two-tag +// list and two valid shells. Under the old `[string]` / `[Argument]` / `[Shell]` +// tuple types this fails to type-check even though it is the documented format. +const multiValued: Workflow = { + slug: "for-loop", + name: "For loop", + command: "for {{variable}} in {{sequence}}; do\n {{command}}\ndone", + tags: ["shell", "loops"], + description: "Iterate over a sequence", + arguments: [ + { name: "variable" }, + { name: "sequence" }, + { name: "command" }, + ], + shells: [Shell.Bash, Shell.Zsh], + relative_git_url: "/specs/shell/for_loop.yaml", +}; + +// Mirrors the README's example workflow, which uses a single tag/argument and +// an empty `shells: []` (valid in all shells). A single-element tuple type would +// reject `shells: []` because it requires exactly one element. +const singleValued: Workflow = { + slug: "brew-rmtree", + name: "Uninstall a Homebrew package and all of its dependencies", + command: "brew tap beeftornado/rmtree\nbrew rmtree {{package_name}}", + tags: ["homebrew"], + arguments: [{ name: "package_name" }], + shells: [], + relative_git_url: "/specs/homebrew/brew_rmtree.yaml", +}; + +// Reference the declarations so `noUnusedLocals`-style checks stay quiet and the +// `Argument` import is exercised. +const _arg: Argument = multiValued.arguments![0]; +void _arg; +void singleValued;