@cosmicdrift/kumiko-renderer-puppeteer-client 0.391.0 → 0.392.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 +30 -32
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
# renderer-puppeteer-client
|
|
2
2
|
|
|
3
|
-
Plugin
|
|
3
|
+
Plugin for `renderer-foundation`. Renders `kind=["document-pdf", "image-snapshot"]` requests via an HTTP call to `puppeteer-service` (separate app in `apps/puppeteer-service` in this repository).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Architektur
|
|
5
|
+
## Architecture
|
|
8
6
|
|
|
9
7
|
```
|
|
10
|
-
Caller (
|
|
8
|
+
Caller (e.g. Solon NKA-PDF-Generator)
|
|
11
9
|
│
|
|
12
10
|
│ const renderer = foundation.createRendererForTenant({ tenantId, kind: "document-pdf" })
|
|
13
11
|
│ await renderer.render({ kind: "document-pdf", payload: { content: "<html>…" } }, ctx)
|
|
14
12
|
▼
|
|
15
|
-
renderer-puppeteer-client (
|
|
13
|
+
renderer-puppeteer-client (THIS package)
|
|
16
14
|
│
|
|
17
15
|
│ POST {PUPPETEER_SERVICE_URL}/render
|
|
18
16
|
│ Authorization: Bearer {PUPPETEER_AUTH_TOKEN}
|
|
19
17
|
│ Retry: 5xx + network-error (exponential backoff)
|
|
20
18
|
▼
|
|
21
|
-
puppeteer-service (separate
|
|
19
|
+
puppeteer-service (separate app, K8s deployment)
|
|
22
20
|
│
|
|
23
|
-
│ Launches Puppeteer
|
|
21
|
+
│ Launches Puppeteer browser, renders HTML
|
|
24
22
|
▼
|
|
25
23
|
{kind: "document-pdf", pdfBytes, ...}
|
|
26
24
|
```
|
|
@@ -34,7 +32,7 @@ import { createRendererFoundationFeature } from "@cosmicdrift/kumiko-bundled-fea
|
|
|
34
32
|
const features = [
|
|
35
33
|
createRendererFoundationFeature(),
|
|
36
34
|
createRendererPuppeteerClientFeature(),
|
|
37
|
-
//
|
|
35
|
+
// additional renderer plugins (renderer-mail-html, …)
|
|
38
36
|
];
|
|
39
37
|
|
|
40
38
|
// In createKumikoApp's extraContext:
|
|
@@ -43,31 +41,31 @@ extraContext: ({ db, registry }) => ({
|
|
|
43
41
|
});
|
|
44
42
|
```
|
|
45
43
|
|
|
46
|
-
##
|
|
44
|
+
## Configuration (env vars)
|
|
47
45
|
|
|
48
|
-
App-wide,
|
|
46
|
+
App-wide, set via K8s Secret + ConfigMap:
|
|
49
47
|
|
|
50
|
-
| Var | Default |
|
|
48
|
+
| Var | Default | Description |
|
|
51
49
|
|---|---|---|
|
|
52
|
-
| `PUPPETEER_SERVICE_URL` | `http://puppeteer-service:3000` |
|
|
53
|
-
| `PUPPETEER_AUTH_TOKEN` | **required** | Shared
|
|
54
|
-
| `PUPPETEER_CLIENT_TIMEOUT_MS` | `60000` | Per-
|
|
55
|
-
| `PUPPETEER_CLIENT_MAX_RETRIES` | `3` |
|
|
50
|
+
| `PUPPETEER_SERVICE_URL` | `http://puppeteer-service:3000` | Internal cluster URL of the service |
|
|
51
|
+
| `PUPPETEER_AUTH_TOKEN` | **required** | Shared secret (>=16 chars, matching the service) |
|
|
52
|
+
| `PUPPETEER_CLIENT_TIMEOUT_MS` | `60000` | Per-request timeout (client side) |
|
|
53
|
+
| `PUPPETEER_CLIENT_MAX_RETRIES` | `3` | Number of retries for 5xx/network errors |
|
|
56
54
|
|
|
57
|
-
**
|
|
55
|
+
**Per tenant?** Currently **no**. All tenants use the same service. Per-tenant overrides via a config bundle will be added when there is a real need, for example a dedicated Puppeteer pool for enterprise tenants.
|
|
58
56
|
|
|
59
|
-
## Retry
|
|
57
|
+
## Retry strategy
|
|
60
58
|
|
|
61
|
-
| Response |
|
|
59
|
+
| Response | Action |
|
|
62
60
|
|---|---|
|
|
63
|
-
| `2xx` | Success
|
|
64
|
-
| `4xx` (
|
|
65
|
-
| `5xx` (
|
|
66
|
-
| Network-error (ECONNREFUSED, timeout) | Retry
|
|
61
|
+
| `2xx` | Success, return bytes |
|
|
62
|
+
| `4xx` (validation, auth, 413) | **NO retry**. Return `RendererError("invalid_payload")` immediately |
|
|
63
|
+
| `5xx` (render error, service crash) | Retry with exponential backoff (200ms × 2^attempt) + ±50% jitter |
|
|
64
|
+
| Network-error (ECONNREFUSED, timeout) | Retry as for 5xx |
|
|
67
65
|
|
|
68
|
-
|
|
66
|
+
After `PUPPETEER_CLIENT_MAX_RETRIES` is exhausted: `RendererError("other")` with the original error message.
|
|
69
67
|
|
|
70
|
-
## Caller
|
|
68
|
+
## Caller pattern
|
|
71
69
|
|
|
72
70
|
```typescript
|
|
73
71
|
import { requireRendererFoundation } from "@cosmicdrift/kumiko-bundled-features/renderer-foundation";
|
|
@@ -86,17 +84,17 @@ async function generatePdf(ctx, tenantId, htmlContent) {
|
|
|
86
84
|
);
|
|
87
85
|
|
|
88
86
|
if (result.kind !== "document-pdf") throw new Error("unexpected kind");
|
|
89
|
-
return result.pdfBytes; // → S3
|
|
87
|
+
return result.pdfBytes; // → S3 upload or directly to the caller
|
|
90
88
|
}
|
|
91
89
|
```
|
|
92
90
|
|
|
93
91
|
## Tests
|
|
94
92
|
|
|
95
|
-
- **15
|
|
96
|
-
- **
|
|
93
|
+
- **15 unit tests** (config + HTTP client + render + contract). No actual network call, fetch mocked via `vi.stubGlobal`.
|
|
94
|
+
- **No integration test with a real service**. The service stack requires puppeteer-service to be running at a URL, which is an E2E setup (step 7). Here, only unit coverage of the HTTP layer.
|
|
97
95
|
|
|
98
|
-
## Out
|
|
96
|
+
## Out of scope
|
|
99
97
|
|
|
100
|
-
- HTML
|
|
101
|
-
- File
|
|
102
|
-
- Tenant-
|
|
98
|
+
- HTML sanitization: the caller provides trusted HTML (from template-resolver with tenant scoping)
|
|
99
|
+
- File storage: the response always contains inline bytes, and the caller persists them to S3 if necessary
|
|
100
|
+
- Tenant-specific URLs: currently app-wide, possibly via a config bundle later
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-renderer-puppeteer-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.392.0",
|
|
4
4
|
"description": "Renderer-Foundation plugin: HTTP client for puppeteer-service (PDF + image snapshot via remote browser).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
23
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
24
|
-
"@cosmicdrift/kumiko-renderer-mail-html": "0.
|
|
25
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
22
|
+
"@cosmicdrift/kumiko-bundled-features": "0.392.0",
|
|
23
|
+
"@cosmicdrift/kumiko-framework": "0.392.0",
|
|
24
|
+
"@cosmicdrift/kumiko-renderer-mail-html": "0.392.0",
|
|
25
|
+
"@cosmicdrift/kumiko-types": "0.392.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@cosmicdrift/kumiko-testing": "0.
|
|
28
|
+
"@cosmicdrift/kumiko-testing": "0.392.0"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|