webhook 1.0.1 copy "webhook: ^1.0.1" to clipboard
webhook: ^1.0.1 copied to clipboard

A tiny, dependency-free webhook server for Dart that routes requests by exact path + HTTP method, and lets you run shell scripts safely with cooldown and concurrency controls.

example/webhook_example.dart

import 'dart:io';
import 'package:webhook/webhook.dart';

/// Entry point for the webhook server example.
///
/// Usage:
///   dart run bin/main.dart `<`FORCE_PASSWORD`>`
///
/// Notes:
/// - If FORCE_PASSWORD is not provided, the `?force=...` query parameter will not work.
/// - This example exposes a single webhook endpoint:
///     /build-docs  (GET, POST)
///   which runs a two-step script pipeline and returns JSON output for both steps.
Future<void> main(List<String> args) async {
  // Force password is passed as the first CLI argument.
  // When set, requests can bypass cooldown via `?force=<FORCE_PASSWORD>`.
  final forcePassword = args.isNotEmpty ? args[0] : null;

  if (forcePassword == null || forcePassword.isEmpty) {
    stderr.writeln(
      '[WARN] FORCE_PASSWORD is not provided, so the `force` query parameter is disabled.\n'
      'Usage: dart run bin/main.dart <FORCE_PASSWORD>',
    );
  } else {
    stdout.writeln(
      '[INFO] FORCE_PASSWORD is set (from command-line arguments).',
    );
  }

  // Create and configure the webhook server.
  final server = WebhookServer(options: WebhookServerOptions(port: 3333));

  // Register a webhook endpoint for building documentation.
  server.addHook(
    Webhook(
      path: '/build-docs',
      methods: {'GET', 'POST'},
      options: HookOptions(
        cooldown: const Duration(hours: 1),

        // Use the current directory as the working directory.
        // This is the default behavior, but keeping it explicit improves clarity.
        workDir: Directory.current.path,

        // Enables `?force=<password>` to bypass cooldown when the password matches.
        forcePassword: forcePassword,

        // Reject concurrent requests while the hook is executing.
        rejectIfRunning: true,
      ),
      handler: (ctx) async {
        // Optionally read JSON body for routing/parameters (GET returns null).
        final body = await ctx.tryReadJsonBody();
        final target = body?['target']?.toString() ?? 'default';

        // Step 1:
        // Prefer running a script file if it exists; otherwise fall back to an inline script.
        final r1 = await ctx.runScript(
          ScriptSpec(
            shell: 'bash',
            scriptPath: 'scripts/build_docs.sh',
            scriptString:
                'echo "Script path not found, falling back to inline script: build $target"',
            // shellArgs: ['-lc'], // Optional: override shell arguments if desired.
          ),
        );

        // Step 2:
        // Run a second script step (e.g., upload artifacts, refresh cache, etc.).
        final r2 = await ctx.runScript(
          ScriptSpec(
            shell: 'bash',
            scriptString: 'echo "Second step for $target"',
          ),
        );

        // Aggregate result and respond with structured JSON.
        final ok = r1.exitCode == 0 && r2.exitCode == 0;
        await ctx.json(ok ? 200 : 500, {
          'ok': ok,
          'step1': r1.toJson(),
          'step2': r2.toJson(),
        });
      },
    ),
  );

  // Start serving requests.
  await server.start();
}
0
likes
160
points
116
downloads

Publisher

verified publisherabandoft.com

Weekly Downloads

A tiny, dependency-free webhook server for Dart that routes requests by exact path + HTTP method, and lets you run shell scripts safely with cooldown and concurrency controls.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

More

Packages that depend on webhook