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
2 changes: 2 additions & 0 deletions cli/azd/.vscode/cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ words:
- grpcbroker
- msiexec
- nosec
- npx
- oneof
- idxs
# Looks like the protogen has a spelling error for panics
Expand All @@ -54,6 +55,7 @@ words:
- structpb
- syncmap
- syscall
- tsx
- Retryable
- runcontext
- surveyterm
Expand Down
2 changes: 2 additions & 0 deletions cli/azd/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,8 @@ func registerCommonDependencies(container *ioc.NestedContainer) {
language.HookKindBash: bash.NewExecutor,
language.HookKindPowerShell: powershell.NewExecutor,
language.HookKindPython: language.NewPythonExecutor,
language.HookKindJavaScript: language.NewJavaScriptExecutor,
language.HookKindTypeScript: language.NewTypeScriptExecutor,
}

for kind, constructor := range hookExecutorMap {
Expand Down
106 changes: 100 additions & 6 deletions cli/azd/docs/language-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ unified lifecycle regardless of its executor: **Prepare → Execute → Cleanup*
| Bash | `sh` | `.sh` | ✅ Stable |
| PowerShell | `pwsh` | `.ps1` | ✅ Stable |
| Python | `python` | `.py` | ✅ Phase 1 |
| JavaScript | `js` | `.js` | 🔜 Planned |
| TypeScript | `ts` | `.ts` | 🔜 Planned |
| JavaScript | `js` | `.js` | ✅ Phase 2 |
| TypeScript | `ts` | `.ts` | ✅ Phase 3 |
| .NET (C#) | `dotnet` | `.cs` | 🔜 Planned |

## Configuration
Expand Down Expand Up @@ -123,6 +123,95 @@ hooks:
DB_CONNECTION_STRING: DATABASE_URL
```

### JavaScript hook — auto-detected from .js extension

The simplest way to use a JavaScript hook. The executor is inferred from the `.js`
extension. Dependencies are installed automatically if a `package.json` is found
in the script's directory (or a parent directory up to the project root).

```yaml
hooks:
postprovision:
run: ./hooks/seed-database.js
```

### JavaScript hook with package.json

When a `package.json` exists near the script, `npm install` runs automatically
before execution.

```yaml
hooks:
postprovision:
run: ./hooks/seed-database.js
# package.json in ./hooks/ → npm install runs automatically
```

### JavaScript hook — explicit kind

```yaml
hooks:
postprovision:
run: ./hooks/setup
kind: js
```

### JavaScript hook with working directory override

```yaml
hooks:
postprovision:
run: ./tools/scripts/seed.js
dir: ./tools # package.json is in ./tools, not ./tools/scripts
```

### JavaScript hook with platform overrides

```yaml
hooks:
postprovision:
windows:
run: ./hooks/setup.ps1
shell: pwsh
posix:
run: ./hooks/setup.js
kind: js
```

### TypeScript hook — auto-detected from .ts extension

TypeScript hooks use `npx tsx` for zero-config execution. `tsx` handles
TypeScript natively without requiring a separate compilation step, and
supports both ESM and CommonJS modules automatically.

```yaml
hooks:
postprovision:
run: ./hooks/seed-database.ts
```

### TypeScript hook with package.json

When a `package.json` is found, dependencies are installed before execution.
If `tsx` is listed as a dependency, the local version is used; otherwise
`npx` downloads it on demand.

```yaml
hooks:
postprovision:
run: ./hooks/seed-database.ts
# package.json with tsx dependency → uses local tsx
```

### TypeScript hook — explicit kind

```yaml
hooks:
postprovision:
run: ./hooks/setup
kind: ts
```

### Bash hook (existing behavior, unchanged)

Bash hooks continue to work exactly as before. The `kind` field is
Expand Down Expand Up @@ -164,7 +253,12 @@ Every hook follows the unified **Prepare → Execute → Cleanup** lifecycle:

- **Inline scripts** are only supported for Bash and PowerShell hooks.
All other executor types must reference a file path.
- **Phase 1** supports only Python as a non-shell executor. JavaScript,
TypeScript, and .NET support is planned for future phases.
- **Virtual environments** are created in the project directory alongside the
dependency file, following the naming convention `{dirName}_env`.
- **Phase 1** supports Python as a non-shell executor.
**Phase 2** adds JavaScript and **Phase 3** adds TypeScript.
.NET support is planned for a future phase.
- **Virtual environments** (Python) are created in the project directory alongside
the dependency file, following the naming convention `{dirName}_env`.
- **TypeScript** hooks require Node.js 18+ and use `npx tsx` for execution.
If `tsx` is not installed locally, `npx` will download it automatically.
- **Package manager** for JS/TS hooks currently uses npm for dependency
installation. Support for pnpm and yarn may be added in a future release.
2 changes: 1 addition & 1 deletion cli/azd/pkg/ext/hooks_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (h *HooksRunner) execHook(
hookConfig.Kind,
hookConfig.Name,
),
Suggestion: "Supported hook kinds: sh, pwsh, python.",
Suggestion: "Supported hook kinds: sh, pwsh, python, js, ts.",
Links: []errorhandler.ErrorLink{
{
Title: "Hook documentation",
Expand Down
Loading
Loading