@viaalink/caddy-api-client 0.0.0-stage → 0.10.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Viaalink
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,672 @@
1
- # Temporary Holding Version
1
+ # @viaalink/caddy-api-client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ TypeScript client for Caddy Admin API with MITMproxy integration.
4
+ Maintained by [Viaalink](https://github.com/viaalink).
5
+
6
+ Package pages:
7
+
8
+ - npm: https://www.npmjs.com/package/@viaalink/caddy-api-client
9
+ - Yarn Classic: https://classic.yarnpkg.com/en/package/@viaalink/caddy-api-client
10
+
11
+ ## Features
12
+
13
+ - ✅ **Type-safe Caddy API client** - Full TypeScript support with Zod validation
14
+ - ✅ **Route builders** - Composable functions for building Caddy routes
15
+ - ✅ **Domain management** - TLS automation with Let's Encrypt
16
+ - ✅ **Load balancing** - Health checks and multiple upstream support
17
+ - ✅ **MITMweb integration** - Traffic inspection for tunnels
18
+ - ✅ **Minimal dependencies** - Only peer dependency: `zod` for runtime validation
19
+
20
+ ## Caddy Version Compatibility
21
+
22
+ | npm Package | Caddy | caddy-security | Notes |
23
+ | ------------ | ------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | 0.9.x–0.10.x | v2.11.4 | v1.1.64 | Current — 0.9.0: security-dense dependency bump, `caddy-dns` DNS provider plugin sources, first public vscode-extension release. 0.10.0: test-coverage-only, no dependency changes |
25
+ | 0.6.x–0.8.0 | v2.11.2 | v1.1.59 | First `caddy-dns` plugin (0.8.0) |
26
+ | 0.4.x–0.5.x | v2.10.2 | v1.1.31 | First plugin framework release |
27
+ | 0.3.x | v2.10.2 | — | Self-contained type generation |
28
+ | 0.1.x–0.2.x | — | — | Used external caddy-json-types |
29
+
30
+ See [DEPENDENCIES.md](./DEPENDENCIES.md) for full version details including commit hashes.
31
+
32
+ ## Live Demo
33
+
34
+ Experience the library in action with our interactive demo showing dynamic MITMproxy traffic inspection via Caddy Admin API.
35
+
36
+ The demo showcases:
37
+
38
+ - **Split-screen view**: Interactive search UI + MITMproxy Web UI
39
+ - **Zero-downtime route switching**: Toggle monitoring without restarts
40
+ - **Library-powered routing**: All route configuration via `caddy-api-client`
41
+
42
+ Run locally: `docker compose -f demo/docker-compose.yml up -d` → http://localhost:9080/dashboard
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ npm install @viaalink/caddy-api-client zod
48
+ # or
49
+ yarn add @viaalink/caddy-api-client zod
50
+ # or
51
+ bun add @viaalink/caddy-api-client zod
52
+ ```
53
+
54
+ ## Quick Start
55
+
56
+ ```typescript
57
+ import { CaddyClient, buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
58
+
59
+ // Create client
60
+ const client = new CaddyClient({
61
+ adminUrl: "http://127.0.0.1:2019",
62
+ });
63
+
64
+ // Build routes with type-safe builders
65
+ const routes = buildServiceRoutes({
66
+ host: "api.localhost",
67
+ dial: "127.0.0.1:3000",
68
+ securityHeaders: {
69
+ enableHsts: true,
70
+ frameOptions: "DENY",
71
+ },
72
+ });
73
+
74
+ // Add routes to Caddy
75
+ await client.addRoutes("https_server", routes);
76
+ ```
77
+
78
+ > **⚠️ Important:** Always use our type-safe builder functions instead of constructing raw Caddy JSON objects. Our builders provide:
79
+ >
80
+ > - ✅ Full TypeScript type checking and IDE autocomplete
81
+ > - ✅ Runtime Zod schema validation
82
+ > - ✅ Protection against common configuration errors
83
+ > - ✅ Clear documentation and examples
84
+ >
85
+ > **Raw Caddy JSON is error-prone and breaks easily.** Our builders are tested, validated, and prevent mistakes.
86
+
87
+ ## Usage
88
+
89
+ ### Basic Route Management
90
+
91
+ ```typescript
92
+ import { CaddyClient, buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
93
+
94
+ const client = new CaddyClient();
95
+
96
+ // Build host-based route
97
+ const routes = buildServiceRoutes({
98
+ host: "api.localhost",
99
+ dial: "127.0.0.1:3000",
100
+ serviceId: "my-api",
101
+ });
102
+
103
+ // Add routes
104
+ for (const route of routes) {
105
+ await client.addRoute("https_server", route);
106
+ }
107
+
108
+ // Get all routes
109
+ const allRoutes = await client.getRoutes("https_server");
110
+
111
+ // Remove routes by hostname
112
+ const removed = await client.removeRoutesByHost("old-api.localhost");
113
+ ```
114
+
115
+ ### Path-based Routes
116
+
117
+ ```typescript
118
+ import { buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
119
+
120
+ const routes = buildServiceRoutes({
121
+ path: "/api",
122
+ pathRouteHost: "example.localhost",
123
+ dial: "127.0.0.1:3000",
124
+ stripPrefix: true, // Strip /api before forwarding
125
+ });
126
+ ```
127
+
128
+ ### Load Balancing
129
+
130
+ ```typescript
131
+ import { CaddyClient, buildLoadBalancerRoute } from "@viaalink/caddy-api-client/caddy";
132
+
133
+ const client = new CaddyClient();
134
+
135
+ const lbRoute = buildLoadBalancerRoute({
136
+ host: "api.localhost",
137
+ upstreams: ["127.0.0.1:3000", "127.0.0.1:3001", "127.0.0.1:3002"],
138
+ policy: "round_robin", // or "first", "random", "least_conn"
139
+ healthCheckPath: "/health",
140
+ healthCheckInterval: "10s",
141
+ });
142
+
143
+ await client.addRoute("https_server", lbRoute);
144
+ ```
145
+
146
+ ### Security Headers
147
+
148
+ ```typescript
149
+ import { buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
150
+
151
+ const routes = buildServiceRoutes({
152
+ host: "secure.localhost",
153
+ dial: "127.0.0.1:3000",
154
+ securityHeaders: {
155
+ enableHsts: true,
156
+ hstsMaxAge: 31536000, // 1 year
157
+ frameOptions: "DENY",
158
+ enableCompression: true,
159
+ },
160
+ });
161
+ ```
162
+
163
+ ### Basic Authentication
164
+
165
+ ```typescript
166
+ import { buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
167
+
168
+ const routes = buildServiceRoutes({
169
+ host: "admin.localhost",
170
+ dial: "127.0.0.1:3000",
171
+ basicAuth: {
172
+ enabled: true,
173
+ username: "admin",
174
+ passwordHash: "$2y$10$...", // bcrypt hash
175
+ realm: "Admin Area",
176
+ },
177
+ });
178
+ ```
179
+
180
+ ### MITMproxy Integration
181
+
182
+ Transparently inspect HTTP traffic for debugging production services **without modifying client or backend code, and without service restarts.**
183
+
184
+ #### Quick Start
185
+
186
+ ```bash
187
+ # 1. Start MITMproxy in Docker
188
+ docker run -d \
189
+ -p 8082:8080 \
190
+ -p 8081:8081 \
191
+ --name mitmproxy \
192
+ mitmproxy/mitmproxy:10.4.2 \
193
+ mitmweb \
194
+ --mode reverse:http://your-backend:3000 \
195
+ --web-host 0.0.0.0 \
196
+ --listen-host 0.0.0.0 \
197
+ --no-web-open-browser \
198
+ --set keep_host_header=true
199
+ ```
200
+
201
+ ```typescript
202
+ // 2. Enable traffic inspection (zero downtime)
203
+ import { CaddyClient, buildMitmproxyRoute } from "@viaalink/caddy-api-client/caddy";
204
+
205
+ const client = new CaddyClient({ adminUrl: "http://localhost:2019" });
206
+
207
+ const route = buildMitmproxyRoute({
208
+ host: "api.example.com",
209
+ mitmproxyHost: "localhost",
210
+ mitmproxyPort: 8082,
211
+ });
212
+
213
+ await client.addRoute("https_server", route, "api_debug");
214
+
215
+ // 3. View captured traffic at http://localhost:8081
216
+
217
+ // 4. Disable when done (zero downtime)
218
+ await client.removeRouteById("https_server", "api_debug");
219
+ ```
220
+
221
+ #### Hot-Swapping Between Direct and Proxied Routing
222
+
223
+ Use `buildMitmproxyRoutePair()` to easily toggle traffic inspection on/off:
224
+
225
+ ```typescript
226
+ import { CaddyClient, buildMitmproxyRoutePair } from "@viaalink/caddy-api-client/caddy";
227
+
228
+ const client = new CaddyClient({ adminUrl: "http://localhost:2019" });
229
+
230
+ // Create both direct and proxied routes
231
+ const routes = buildMitmproxyRoutePair({
232
+ host: "api.example.com",
233
+ backendHost: "api-service",
234
+ backendPort: 3000,
235
+ mitmproxyHost: "localhost",
236
+ mitmproxyPort: 8082,
237
+ routeId: "api_route",
238
+ });
239
+
240
+ // Start with direct routing (no inspection)
241
+ await client.addRoute("https_server", routes.direct, routes.direct["@id"]);
242
+
243
+ // Hot-swap to enable inspection (zero downtime)
244
+ await client.removeRouteById("https_server", routes.direct["@id"]);
245
+ await client.addRoute("https_server", routes.proxied, routes.proxied["@id"]);
246
+
247
+ // Hot-swap back to disable inspection
248
+ await client.removeRouteById("https_server", routes.proxied["@id"]);
249
+ await client.addRoute("https_server", routes.direct, routes.direct["@id"]);
250
+ ```
251
+
252
+ #### Load Balancing with MITMproxy
253
+
254
+ Route some traffic through MITMproxy while keeping the rest direct:
255
+
256
+ ```typescript
257
+ import { CaddyClient, buildLoadBalancerRoute } from "@viaalink/caddy-api-client/caddy";
258
+
259
+ const client = new CaddyClient();
260
+ const lbRoute = buildLoadBalancerRoute({
261
+ host: "api.localhost",
262
+ upstreams: [
263
+ "localhost:8082", // MITMproxy (captures traffic)
264
+ "localhost:3000", // Direct to backend
265
+ ],
266
+ policy: "round_robin",
267
+ });
268
+
269
+ await client.addRoute("https_server", lbRoute);
270
+ ```
271
+
272
+ #### Docker Compose Setup
273
+
274
+ ```yaml
275
+ services:
276
+ mitmproxy:
277
+ image: mitmproxy/mitmproxy:10.4.2
278
+ ports:
279
+ - "8082:8080" # Proxy port
280
+ - "8081:8081" # Web UI
281
+ command: >
282
+ mitmweb
283
+ --mode reverse:http://backend:3000
284
+ --web-host 0.0.0.0
285
+ --web-port 8081
286
+ --listen-host 0.0.0.0
287
+ --listen-port 8080
288
+ --no-web-open-browser
289
+ --set keep_host_header=true
290
+ restart: unless-stopped
291
+
292
+ backend:
293
+ image: your-backend-image
294
+ ports:
295
+ - "3000:3000"
296
+ ```
297
+
298
+ **Features:**
299
+
300
+ - ✅ Zero client/backend code changes
301
+ - ✅ Zero service restarts required
302
+ - ✅ Hot-swappable at runtime
303
+ - ✅ Complete request/response inspection
304
+ - ✅ Web UI for viewing captured traffic
305
+ - ✅ Production-safe (tested with concurrent requests)
306
+
307
+ **Troubleshooting:** See the [MITMproxy Troubleshooting Guide](https://github.com/viaalink/asd-caddy-api-client/blob/main/docs/mitmproxy-troubleshooting.md) for common issues and solutions.
308
+
309
+ ### Domain Management
310
+
311
+ ```typescript
312
+ import { addDomainWithAutoTls, deleteDomain } from "@viaalink/caddy-api-client/caddy";
313
+
314
+ // Add domain with automatic TLS (Let's Encrypt)
315
+ const domain = await addDomainWithAutoTls({
316
+ domain: "example.com",
317
+ target: "127.0.0.1",
318
+ targetPort: 3000,
319
+ enableHsts: true,
320
+ redirectMode: "permanent",
321
+ });
322
+
323
+ // Delete domain
324
+ await deleteDomain({ domain: "example.com" });
325
+ ```
326
+
327
+ ## API Reference
328
+
329
+ ### CaddyClient
330
+
331
+ ```typescript
332
+ class CaddyClient {
333
+ constructor(options?: CaddyClientOptions);
334
+
335
+ // Configuration
336
+ getConfig(): Promise<unknown>;
337
+ reload(): Promise<void>;
338
+ stop(): Promise<void>; // Gracefully stop Caddy server
339
+ adapt(config: string, adapter?: string): Promise<unknown>; // Convert Caddyfile to JSON
340
+
341
+ // Routes
342
+ getRoutes(server: string): Promise<CaddyRoute[]>;
343
+ addRoute(server: string, route: CaddyRoute): Promise<boolean>;
344
+ addRoutes(server: string, routes: CaddyRoute[]): Promise<{ added: number; skipped: number }>;
345
+ patchRoutes(server: string, routes: CaddyRoute[]): Promise<void>;
346
+ insertRoute(
347
+ server: string,
348
+ route: CaddyRoute,
349
+ position?: "beginning" | "end" | "after-health-checks"
350
+ ): Promise<void>;
351
+ replaceRouteById(server: string, id: string, newRoute: CaddyRoute): Promise<boolean>;
352
+ removeRouteById(server: string, id: string): Promise<boolean>;
353
+ removeRoutesByHost(hostname: string, server?: string): Promise<number>;
354
+
355
+ // Servers
356
+ getServers(): Promise<unknown>;
357
+ getServerConfig(server: string): Promise<Record<string, unknown>>;
358
+ patchServer(serverConfig: Record<string, unknown>): Promise<void>;
359
+
360
+ // Upstreams (reverse proxy status)
361
+ getUpstreams(): Promise<UpstreamStatus[]>; // Get health/status of upstream servers
362
+
363
+ // Version
364
+ getVersion(): Promise<unknown>;
365
+ }
366
+ ```
367
+
368
+ ### Route Builders
369
+
370
+ ```typescript
371
+ // Service routes (host + path based)
372
+ buildServiceRoutes(options: ServiceRouteOptions): CaddyRoute[];
373
+
374
+ // Individual route types
375
+ buildHealthCheckRoute(options: HealthCheckRouteOptions): CaddyRoute;
376
+ buildHostRoute(options: HostRouteOptions): CaddyRoute;
377
+ buildPathRoute(options: PathRouteOptions): CaddyRoute;
378
+ buildLoadBalancerRoute(options: LoadBalancerRouteOptions): CaddyRoute;
379
+
380
+ // New handler routes (v0.3.0)
381
+ buildFileServerRoute(options: FileServerRouteOptions): CaddyRoute;
382
+ buildTemplatesRoute(options: TemplatesRouteOptions): CaddyRoute;
383
+ buildErrorRoute(options: ErrorRouteOptions): CaddyRoute;
384
+
385
+ // MITMproxy integration
386
+ buildMitmproxyRoute(options: MitmproxyRouteOptions): CaddyRoute;
387
+ buildMitmproxyRoutePair(options: MitmproxyRoutePairOptions): { direct: CaddyRoute; proxied: CaddyRoute };
388
+
389
+ // Handlers
390
+ buildReverseProxyHandler(dial: DialAddress): CaddyRouteHandler;
391
+ buildSecurityHeadersHandler(headers: SecurityHeaders): CaddyRouteHandler;
392
+ buildBasicAuthHandler(auth: BasicAuthOptions): CaddyRouteHandler;
393
+ buildRewriteHandler(prefix: string): CaddyRouteHandler;
394
+ buildCompressionHandler(options?: CompressionOptions): CaddyRouteHandler;
395
+ buildIngressTagHeadersHandler(tag: string): CaddyRouteHandler;
396
+ buildIframeHeadersHandler(allowedOrigin?: string): CaddyRouteHandler;
397
+
398
+ // New handlers (v0.3.0)
399
+ buildRequestBodyHandler(options: RequestBodyHandlerOptions): CaddyRouteHandler;
400
+ buildVarsHandler(options: VarsHandlerOptions): CaddyRouteHandler;
401
+ buildMapHandler(options: MapHandlerOptions): CaddyRouteHandler;
402
+ buildTracingHandler(options?: TracingHandlerOptions): CaddyRouteHandler;
403
+ ```
404
+
405
+ ### MITMweb Functions
406
+
407
+ ```typescript
408
+ // Installation & status
409
+ isMitmproxyInstalled(): Promise<boolean>;
410
+ getMitmproxyVersion(): Promise<string | null>;
411
+ autoInstallMitmproxy(): Promise<boolean>;
412
+
413
+ // Process management
414
+ startMitmweb(options?: MitmwebOptions): Promise<{ pid, webUrl, proxyUrl, pidFile }>;
415
+ stopMitmweb(workingDir?: string): Promise<void>;
416
+ getMitmwebStatus(workingDir?: string): MitmwebStatus;
417
+ ```
418
+
419
+ ### Domain Management
420
+
421
+ ```typescript
422
+ addDomainWithAutoTls(options: AddDomainWithAutoTlsOptions): Promise<DomainConfig>;
423
+ addDomainWithTls(options: AddDomainWithTlsOptions): Promise<DomainConfig>;
424
+ updateDomain(options: UpdateDomainOptions): Promise<DomainConfig>;
425
+ deleteDomain(options: DeleteDomainOptions): Promise<void>;
426
+ getDomainConfig(domain: Domain, adminUrl?: string): Promise<DomainConfig | null>;
427
+ ```
428
+
429
+ ### Advanced Schemas
430
+
431
+ Zod-validated schemas for advanced Caddy configurations:
432
+
433
+ ```typescript
434
+ import {
435
+ // Duration (Go format)
436
+ CaddyDurationSchema, // "10s", "1m30s", or nanoseconds
437
+
438
+ // Health checks
439
+ ActiveHealthChecksSchema, // uri, interval, timeout, expect_status, expect_body
440
+ PassiveHealthChecksSchema, // fail_duration, max_fails, unhealthy_status
441
+ HealthChecksSchema, // Combined active + passive
442
+
443
+ // Load balancing
444
+ LoadBalancingSchema, // selection_policy, retries, try_duration
445
+ UpstreamSchema, // dial, max_requests
446
+
447
+ // Route matching
448
+ ExtendedRouteMatcherSchema, // client_ip, remote_ip, path_regexp, expression, not
449
+
450
+ // Handler
451
+ ReverseProxyHandlerSchema, // Full reverse proxy with health checks + load balancing
452
+ } from "@viaalink/caddy-api-client";
453
+ ```
454
+
455
+ ### Handler Types (v0.3.0)
456
+
457
+ Full TypeScript support for all 20 Caddy HTTP handlers with Zod validation:
458
+
459
+ ```typescript
460
+ import {
461
+ // File serving
462
+ FileServerHandlerSchema, // Static files with browse, precompressed
463
+ TemplatesHandlerSchema, // Server-side template rendering
464
+
465
+ // Request manipulation
466
+ RewriteHandlerSchema, // URI rewriting
467
+ RequestBodyHandlerSchema, // Body size limits
468
+ VarsHandlerSchema, // Set request variables
469
+ MapHandlerSchema, // Variable mapping
470
+
471
+ // Response handling
472
+ StaticResponseHandlerSchema, // Return static content
473
+ HeadersHandlerSchema, // Modify headers
474
+ EncodeHandlerSchema, // Compression (gzip, zstd, br)
475
+ ErrorHandlerSchema, // Trigger error handling
476
+
477
+ // Proxy & routing
478
+ ReverseProxyHandlerSchema, // Proxy to upstreams
479
+ SubrouteHandlerSchema, // Nested routes
480
+ InvokeHandlerSchema, // Call named routes
481
+
482
+ // Interception
483
+ InterceptHandlerSchema, // Response interception
484
+ CopyResponseHandlerSchema, // Copy subrequest response
485
+ CopyResponseHeadersHandlerSchema, // Copy headers
486
+
487
+ // Utilities
488
+ AuthenticationHandlerSchema, // HTTP basic auth
489
+ PushHandlerSchema, // HTTP/2 server push
490
+ TracingHandlerSchema, // Distributed tracing
491
+ LogAppendHandlerSchema, // Custom log fields
492
+ } from "@viaalink/caddy-api-client";
493
+ ```
494
+
495
+ **Route builders for common patterns:**
496
+
497
+ ```typescript
498
+ import {
499
+ buildFileServerRoute, // Serve static files
500
+ buildTemplatesRoute, // Template processing
501
+ buildErrorRoute, // Error responses
502
+ buildRequestBodyHandler, // Body limits
503
+ buildVarsHandler, // Set variables
504
+ buildMapHandler, // Variable mapping
505
+ buildTracingHandler, // Tracing spans
506
+ } from "@viaalink/caddy-api-client/caddy";
507
+
508
+ // Example: Serve static files with browsing
509
+ const fileRoute = buildFileServerRoute({
510
+ path: "/static/*",
511
+ root: "/var/www/static",
512
+ browse: true,
513
+ hidePatterns: [".git", ".env"],
514
+ precompressed: true,
515
+ });
516
+
517
+ // Example: Template rendering
518
+ const templateRoute = buildTemplatesRoute({
519
+ path: "/*.html",
520
+ fileRoot: "/var/www/templates",
521
+ mimeTypes: ["text/html"],
522
+ });
523
+
524
+ // Example: Variable mapping for routing
525
+ const mapHandler = buildMapHandler({
526
+ source: "{http.request.uri.path}",
527
+ destinations: ["{backend}"],
528
+ mappings: [
529
+ { input: "/api/*", outputs: ["api-server"] },
530
+ { input: "/admin/*", outputs: ["admin-server"] },
531
+ ],
532
+ defaults: ["default-server"],
533
+ });
534
+ ```
535
+
536
+ ### Extended Caddy Types
537
+
538
+ For advanced configurations beyond our Zod-validated builders, we re-export comprehensive type definitions from [caddy-json-types](https://github.com/CafuChino/caddy-json-types):
539
+
540
+ ```typescript
541
+ import type {
542
+ IConfig,
543
+ IModulesCaddyhttpRoute,
544
+ IModulesCaddyhttpReverseproxyHandler,
545
+ IModulesCaddytlsConnectionPolicy,
546
+ } from "@viaalink/caddy-api-client/caddy-types";
547
+ ```
548
+
549
+ **Includes 591 types covering:**
550
+
551
+ - Full Caddy JSON configuration structure
552
+ - 50+ DNS providers for ACME challenges
553
+ - Layer 4 (TCP/UDP) proxy configuration
554
+ - PKI/CA management types
555
+ - Storage backends (Redis, S3, DynamoDB, etc.)
556
+ - All HTTP handlers, matchers, and encoders
557
+
558
+ ## Error Handling
559
+
560
+ The library provides custom error classes:
561
+
562
+ ```typescript
563
+ import {
564
+ CaddyApiError,
565
+ ValidationError,
566
+ NetworkError,
567
+ TimeoutError,
568
+ DomainNotFoundError,
569
+ MitmproxyNotInstalledError,
570
+ } from "@viaalink/caddy-api-client";
571
+
572
+ try {
573
+ await client.addRoute("https_server", route);
574
+ } catch (error) {
575
+ if (error instanceof ValidationError) {
576
+ console.error("Invalid route configuration:", error.errors);
577
+ } else if (error instanceof CaddyApiError) {
578
+ console.error(`Caddy API error (${error.statusCode}):`, error.responseBody);
579
+ } else if (error instanceof NetworkError) {
580
+ console.error("Network error:", error.cause);
581
+ } else if (error instanceof TimeoutError) {
582
+ console.error(`Request timed out after ${error.timeoutMs}ms`);
583
+ }
584
+ }
585
+ ```
586
+
587
+ ## Examples
588
+
589
+ ### Tested Examples (Always Current)
590
+
591
+ Our **integration tests** serve as comprehensive, tested examples that are verified in CI:
592
+
593
+ - **[caddy-mitmproxy-flow.integration.test.ts](./src/__tests__/integration/caddy-mitmproxy-flow.integration.test.ts)** - Complete MITMproxy integration patterns
594
+ - **[asd-scenarios.integration.test.ts](./src/__tests__/integration/asd-scenarios.integration.test.ts)** - Production routing scenarios (load balancing, multi-host, path-based)
595
+ - **[critical-modules.integration.test.ts](./src/__tests__/integration/critical-modules.integration.test.ts)** - All route builders, domain management, TLS
596
+
597
+ **Run examples locally:**
598
+
599
+ ```bash
600
+ # Start services
601
+ docker compose -f docker-compose.test.yml up -d
602
+
603
+ # Run all integration tests (86+ examples)
604
+ INTEGRATION_TEST=true bun test src/__tests__/integration/
605
+
606
+ # Run specific example file
607
+ INTEGRATION_TEST=true bun test src/__tests__/integration/caddy-mitmproxy-flow.integration.test.ts
608
+ ```
609
+
610
+ ### Standalone Examples
611
+
612
+ See the [`examples/`](./examples/) directory for standalone examples (require published package):
613
+
614
+ - [`basic-usage.ts`](./examples/basic-usage.ts) - Basic route management
615
+ - [`load-balancer.ts`](./examples/load-balancer.ts) - Load balancing with health checks
616
+ - [`mitmproxy-integration.ts`](./examples/mitmproxy-integration.ts) - Traffic inspection with MITMproxy
617
+
618
+ ## API Documentation
619
+
620
+ 📚 **[View Full API Documentation](https://viaalink.github.io/asd-caddy-api-client/)** ← Auto-generated from source code
621
+
622
+ Full API documentation is generated using TypeDoc and hosted on GitHub Pages. It includes detailed information for all exported functions, classes, and types with examples.
623
+
624
+ **Generate locally:**
625
+
626
+ ```bash
627
+ bun run docs:build # Generate docs
628
+ bun run docs:serve # Generate and open in browser
629
+ ```
630
+
631
+ ## Development
632
+
633
+ ```bash
634
+ # Install dependencies
635
+ bun install
636
+
637
+ # Build
638
+ bun run build
639
+
640
+ # Test
641
+ bun run test
642
+
643
+ # Type check
644
+ bun run typecheck
645
+
646
+ # Lint
647
+ bun run lint
648
+
649
+ # Format
650
+ bun run format
651
+ ```
652
+
653
+ ## Contributing
654
+
655
+ Contributions are welcome! Please [open an issue](https://github.com/viaalink/asd-caddy-api-client/issues) or submit a pull request if you have any improvements or fixes.
656
+
657
+ 1. Fork the repository
658
+ 2. Create a new branch (`git checkout -b my-feature-branch`)
659
+ 3. Make your changes
660
+ 4. Commit your changes (`git commit -am 'Add new feature'`)
661
+ 5. Push to the branch (`git push origin my-feature-branch`)
662
+ 6. Create a new Pull Request
663
+
664
+ ## License
665
+
666
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
667
+
668
+ ## Acknowledgements
669
+
670
+ This project is not affiliated with or endorsed by the Caddy project. It is an independent project created to improve the developer experience when working with Caddy JSON configurations in TypeScript.
671
+
672
+ For more information on Caddy and its configuration options, please visit the [official Caddy documentation](https://caddyserver.com/docs/).