@flanksource/facet-cli 0.0.0 → 0.0.1

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.
@@ -0,0 +1,456 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Facet Render API
4
+ description: API for rendering React templates to HTML and PDF.
5
+ version: 0.1.23
6
+ license:
7
+ name: Apache 2.0
8
+ url: https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ servers:
11
+ - url: http://localhost:3010
12
+ description: Local development server
13
+
14
+ security: []
15
+
16
+ paths:
17
+ /healthz:
18
+ get:
19
+ operationId: healthz
20
+ summary: Health check
21
+ description: Returns server health and worker pool status.
22
+ responses:
23
+ "200":
24
+ description: Server is healthy.
25
+ content:
26
+ application/json:
27
+ schema:
28
+ type: object
29
+ properties:
30
+ status:
31
+ type: string
32
+ example: ok
33
+ workers:
34
+ type: object
35
+ description: Worker pool statistics.
36
+
37
+ /templates:
38
+ get:
39
+ operationId: listTemplates
40
+ summary: List available templates
41
+ description: Returns templates discovered in the configured templates directory.
42
+ security:
43
+ - apiKey: []
44
+ - bearerAuth: []
45
+ responses:
46
+ "200":
47
+ description: List of templates.
48
+ content:
49
+ application/json:
50
+ schema:
51
+ type: array
52
+ items:
53
+ $ref: "#/components/schemas/TemplateInfo"
54
+ "401":
55
+ $ref: "#/components/responses/Unauthorized"
56
+
57
+ /render:
58
+ post:
59
+ operationId: render
60
+ summary: Render a template
61
+ description: |
62
+ Renders a template to HTML or PDF synchronously. The response body is
63
+ the rendered output (HTML or PDF binary), or a JSON object with S3 URLs
64
+ when `output: "s3"` is used.
65
+
66
+ Supports three input modes:
67
+ - **JSON** with inline code or template name
68
+ - **Multipart** with an uploaded archive
69
+ - **Gzip** body with a tar.gz archive
70
+ security:
71
+ - apiKey: []
72
+ - bearerAuth: []
73
+ requestBody:
74
+ required: true
75
+ content:
76
+ application/json:
77
+ schema:
78
+ $ref: "#/components/schemas/RenderRequest"
79
+ multipart/form-data:
80
+ schema:
81
+ $ref: "#/components/schemas/MultipartRenderRequest"
82
+ application/gzip:
83
+ schema:
84
+ type: string
85
+ format: binary
86
+ parameters:
87
+ - name: format
88
+ in: query
89
+ schema:
90
+ type: string
91
+ enum: [html, pdf]
92
+ description: Output format (gzip mode only).
93
+ - name: output
94
+ in: query
95
+ schema:
96
+ type: string
97
+ enum: [direct, s3]
98
+ description: Output destination (gzip mode only).
99
+ - name: entryFile
100
+ in: query
101
+ schema:
102
+ type: string
103
+ description: Entry file within archive (gzip mode only).
104
+ - name: X-Facet-Data
105
+ in: header
106
+ schema:
107
+ type: string
108
+ description: Base64-encoded JSON data (gzip mode only).
109
+ responses:
110
+ "200":
111
+ description: |
112
+ Rendered output. For HTML format, returns raw HTML. For PDF format,
113
+ returns JSON with a `url` field pointing to `/results/{id}` where the
114
+ cached PDF can be fetched. When `output: "s3"`, returns S3 upload details.
115
+ content:
116
+ text/html:
117
+ schema:
118
+ type: string
119
+ application/json:
120
+ schema:
121
+ oneOf:
122
+ - $ref: "#/components/schemas/PDFRenderResult"
123
+ - $ref: "#/components/schemas/S3UploadResult"
124
+ "400":
125
+ $ref: "#/components/responses/BadRequest"
126
+ "401":
127
+ $ref: "#/components/responses/Unauthorized"
128
+ "404":
129
+ $ref: "#/components/responses/NotFound"
130
+ "504":
131
+ $ref: "#/components/responses/Timeout"
132
+
133
+ /render/stream:
134
+ post:
135
+ operationId: renderStream
136
+ summary: Render with streaming progress
137
+ description: |
138
+ Same as `/render` but returns a Server-Sent Events stream with progress
139
+ updates followed by the final result. Used by the playground.
140
+
141
+ **Event types:**
142
+ - `data: {...}` — progress event with `stage`, `message`, `elapsed`, `duration`
143
+ - `event: result` — final output with `contentType`, `data`, and `url`. For PDFs, `data` is empty and `url` points to `/results/{id}`. For HTML, `data` contains the rendered HTML.
144
+ - `event: error` — render error with `message`
145
+ security:
146
+ - apiKey: []
147
+ - bearerAuth: []
148
+ requestBody:
149
+ required: true
150
+ content:
151
+ application/json:
152
+ schema:
153
+ $ref: "#/components/schemas/RenderRequest"
154
+ responses:
155
+ "200":
156
+ description: SSE stream of progress events and final result.
157
+ content:
158
+ text/event-stream:
159
+ schema:
160
+ type: string
161
+ "400":
162
+ $ref: "#/components/responses/BadRequest"
163
+ "401":
164
+ $ref: "#/components/responses/Unauthorized"
165
+
166
+ /results/{id}:
167
+ get:
168
+ operationId: getResult
169
+ summary: Get cached render result
170
+ description: |
171
+ Serves a previously rendered result from the disk cache. The `id` is a
172
+ 16-character hex cache key returned in the `url` field of streaming
173
+ render results.
174
+ security:
175
+ - apiKey: []
176
+ - bearerAuth: []
177
+ parameters:
178
+ - name: id
179
+ in: path
180
+ required: true
181
+ schema:
182
+ type: string
183
+ pattern: "^[a-f0-9]{16}$"
184
+ description: Cache key (16 hex characters).
185
+ responses:
186
+ "200":
187
+ description: Cached render output.
188
+ headers:
189
+ Cache-Control:
190
+ schema:
191
+ type: string
192
+ example: private, max-age=600
193
+ content:
194
+ text/html:
195
+ schema:
196
+ type: string
197
+ application/pdf:
198
+ schema:
199
+ type: string
200
+ format: binary
201
+ "401":
202
+ $ref: "#/components/responses/Unauthorized"
203
+ "404":
204
+ $ref: "#/components/responses/NotFound"
205
+
206
+ /types:
207
+ get:
208
+ operationId: getTypes
209
+ summary: TypeScript type definitions
210
+ description: Returns the `@flanksource/facet` TypeScript declarations for use in the Monaco editor playground.
211
+ responses:
212
+ "200":
213
+ description: TypeScript declaration file content.
214
+ content:
215
+ text/plain:
216
+ schema:
217
+ type: string
218
+
219
+ components:
220
+ securitySchemes:
221
+ apiKey:
222
+ type: apiKey
223
+ in: header
224
+ name: X-API-Key
225
+ bearerAuth:
226
+ type: http
227
+ scheme: bearer
228
+
229
+ schemas:
230
+ RenderRequest:
231
+ type: object
232
+ description: JSON render request. Provide either `code` (inline) or `template` (named/remote).
233
+ properties:
234
+ code:
235
+ type: string
236
+ description: Inline TSX template code.
237
+ template:
238
+ type: string
239
+ description: Template name (local) or remote ref (e.g. `github.com/org/repo/path`).
240
+ data:
241
+ type: object
242
+ additionalProperties: true
243
+ description: Data passed to the template as props.
244
+ default: {}
245
+ format:
246
+ type: string
247
+ enum: [html, pdf]
248
+ default: pdf
249
+ output:
250
+ type: string
251
+ enum: [direct, s3]
252
+ default: direct
253
+ s3Key:
254
+ type: string
255
+ description: "Custom S3 key (when output is s3)."
256
+ filename:
257
+ type: string
258
+ description: Custom filename for Content-Disposition header.
259
+ dependencies:
260
+ type: object
261
+ additionalProperties:
262
+ type: string
263
+ description: "npm dependencies to install, e.g. react-icons: ^5.4.0."
264
+ headerCode:
265
+ type: string
266
+ description: Inline TSX for a header component.
267
+ footerCode:
268
+ type: string
269
+ description: Inline TSX for a footer component.
270
+ pdfOptions:
271
+ $ref: "#/components/schemas/PDFOptions"
272
+ encryption:
273
+ $ref: "#/components/schemas/PDFEncryptionOptions"
274
+ signature:
275
+ $ref: "#/components/schemas/PDFSignatureOptions"
276
+
277
+ PDFOptions:
278
+ type: object
279
+ properties:
280
+ defaultPageSize:
281
+ type: string
282
+ description: Page size name.
283
+ enum: [a4, a3, letter, legal, fhd, qhd, wqhd, 4k, 5k, 16k]
284
+ landscape:
285
+ type: boolean
286
+ default: false
287
+ debug:
288
+ type: boolean
289
+ description: Add debug overlay lines for header/footer zones.
290
+ default: false
291
+ margins:
292
+ type: object
293
+ properties:
294
+ top:
295
+ type: number
296
+ description: Top margin in mm.
297
+ bottom:
298
+ type: number
299
+ description: Bottom margin in mm.
300
+ left:
301
+ type: number
302
+ description: Left margin in mm.
303
+ right:
304
+ type: number
305
+ description: Right margin in mm.
306
+
307
+ PDFEncryptionOptions:
308
+ type: object
309
+ required: [ownerPassword]
310
+ properties:
311
+ userPassword:
312
+ type: string
313
+ description: Password required to open the PDF.
314
+ ownerPassword:
315
+ type: string
316
+ description: Owner password that controls permissions.
317
+ permissions:
318
+ type: object
319
+ properties:
320
+ print:
321
+ type: boolean
322
+ default: true
323
+ modify:
324
+ type: boolean
325
+ default: false
326
+ copy:
327
+ type: boolean
328
+ default: false
329
+ annotate:
330
+ type: boolean
331
+ default: false
332
+
333
+ PDFSignatureOptions:
334
+ type: object
335
+ properties:
336
+ certPath:
337
+ type: string
338
+ description: Path to PKCS#12 (.p12/.pfx) certificate file.
339
+ certPassword:
340
+ type: string
341
+ description: Certificate password.
342
+ selfSigned:
343
+ type: boolean
344
+ description: Auto-generate a self-signed certificate for signing.
345
+ default: false
346
+ reason:
347
+ type: string
348
+ description: Signature reason text.
349
+ name:
350
+ type: string
351
+ description: Signer name.
352
+ location:
353
+ type: string
354
+ description: Signing location.
355
+ timestampUrl:
356
+ type: string
357
+ description: RFC 3161 Timestamp Authority URL.
358
+
359
+ MultipartRenderRequest:
360
+ type: object
361
+ required: [archive]
362
+ properties:
363
+ archive:
364
+ type: string
365
+ format: binary
366
+ description: Archive file (tar.gz or zip) containing the template.
367
+ data:
368
+ type: string
369
+ description: JSON string of template data.
370
+ options:
371
+ type: string
372
+ description: JSON string with `format`, `output`, `entryFile`, `pdfOptions`, etc.
373
+
374
+ TemplateInfo:
375
+ type: object
376
+ properties:
377
+ name:
378
+ type: string
379
+ entryFile:
380
+ type: string
381
+ description:
382
+ type: string
383
+ hasSchema:
384
+ type: boolean
385
+
386
+ PDFRenderResult:
387
+ type: object
388
+ required: [url]
389
+ properties:
390
+ url:
391
+ type: string
392
+ description: URL path to fetch the cached PDF (e.g. `/results/{id}`).
393
+ example: /results/a1b2c3d4e5f67890
394
+
395
+ S3UploadResult:
396
+ type: object
397
+ properties:
398
+ url:
399
+ type: string
400
+ description: Public S3 URL.
401
+ presignedUrl:
402
+ type: string
403
+ description: Pre-signed URL with expiry.
404
+ key:
405
+ type: string
406
+ description: S3 object key.
407
+
408
+ ErrorResponse:
409
+ type: object
410
+ properties:
411
+ error:
412
+ type: object
413
+ required: [code, message]
414
+ properties:
415
+ code:
416
+ type: string
417
+ enum:
418
+ - TEMPLATE_NOT_FOUND
419
+ - VALIDATION_ERROR
420
+ - RENDER_TIMEOUT
421
+ - RENDER_FAILED
422
+ - S3_UPLOAD_FAILED
423
+ - QUEUE_FULL
424
+ - AUTH_REQUIRED
425
+ - INVALID_REQUEST
426
+ - ARCHIVE_ERROR
427
+ message:
428
+ type: string
429
+ details:
430
+ description: Additional error context.
431
+
432
+ responses:
433
+ BadRequest:
434
+ description: Invalid request.
435
+ content:
436
+ application/json:
437
+ schema:
438
+ $ref: "#/components/schemas/ErrorResponse"
439
+ Unauthorized:
440
+ description: Missing or invalid API key.
441
+ content:
442
+ application/json:
443
+ schema:
444
+ $ref: "#/components/schemas/ErrorResponse"
445
+ NotFound:
446
+ description: Template or resource not found.
447
+ content:
448
+ application/json:
449
+ schema:
450
+ $ref: "#/components/schemas/ErrorResponse"
451
+ Timeout:
452
+ description: Render timed out.
453
+ content:
454
+ application/json:
455
+ schema:
456
+ $ref: "#/components/schemas/ErrorResponse"
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "@flanksource/facet",
3
+ "version": "0.1.48",
4
+ "description": "Build beautiful datasheets and PDFs from React templates",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/flanksource/facet.git"
9
+ },
10
+ "main": "./dist/components/index.js",
11
+ "types": "./dist/components/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/components/index.d.ts",
15
+ "import": "./dist/components/index.js"
16
+ },
17
+ "./styles.css": "./dist/styles.css",
18
+ "./*": {
19
+ "types": "./dist/components/*.d.ts",
20
+ "import": "./dist/components/*.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "files": [
25
+ "dist/",
26
+ "cli/dist/",
27
+ "openapi.yaml",
28
+ "README.md"
29
+ ],
30
+ "packageManager": "pnpm@9.15.9",
31
+ "scripts": {
32
+ "build": "pnpm run build:components && pnpm run build:css && pnpm run build:cli",
33
+ "build:components": "vite build --config vite.lib.config.ts",
34
+ "build:css": "tailwindcss -i src/styles.css -o dist/styles.css",
35
+ "build:cli": "cd cli && pnpm run build",
36
+ "storybook": "storybook dev -p 6006",
37
+ "build-storybook": "storybook build",
38
+ "prepublishOnly": "pnpm run build:components && pnpm run build:css && cd cli && pnpm run build:lib",
39
+ "chromatic": "pnpm exec chromatic"
40
+ },
41
+ "peerDependencies": {
42
+ "react": ">=18",
43
+ "react-dom": ">=18"
44
+ },
45
+ "dependencies": {
46
+ "@flanksource/icons": "^1.0.53",
47
+ "@iconify/react": "^5.1.0",
48
+ "@xyflow/react": "^12.0.0",
49
+ "clsx": "^2.1.1",
50
+ "d3-array": "^3.2.4",
51
+ "d3-format": "^3.1.0",
52
+ "d3-interpolate": "^3.0.1",
53
+ "d3-scale": "^4.0.2",
54
+ "d3-shape": "^3.2.0",
55
+ "d3-time": "^3.1.0",
56
+ "d3-time-format": "^4.1.0",
57
+ "dagre": "^0.8.5",
58
+ "dayjs": "^1.11.13",
59
+ "pdf-lib": "^1.17.1",
60
+ "react-icons": "^5.4.0",
61
+ "react-xarrows": "^2.0.2",
62
+ "shiki": "^1.0.0",
63
+ "source-map-support": "^0.5.21"
64
+ },
65
+ "devDependencies": {
66
+ "@mdx-js/rollup": "^3.0.0",
67
+ "@storybook/addon-docs": "^8.6.14",
68
+ "@storybook/addon-essentials": "^8.6.14",
69
+ "@storybook/react": "^8.6.14",
70
+ "@storybook/react-vite": "^8.6.14",
71
+ "@tailwindcss/postcss": "^4.1.17",
72
+ "@tailwindcss/typography": "^0.5.19",
73
+ "@tailwindcss/vite": "^4.1.17",
74
+ "@testing-library/jest-dom": "^6.9.1",
75
+ "@testing-library/react": "^16.3.2",
76
+ "@types/d3-scale": "^4.0.9",
77
+ "@types/d3-shape": "^3.1.8",
78
+ "@types/dagre": "^0.7.52",
79
+ "@types/node": "^20.0.0",
80
+ "@types/react": "^18.2.0",
81
+ "@types/react-dom": "^18.2.0",
82
+ "@vitejs/plugin-react": "^4.2.0",
83
+ "autoprefixer": "^10.4.16",
84
+ "baseline-browser-mapping": "^2.10.0",
85
+ "chalk": "^5.6.2",
86
+ "chromatic": "^16.0.0",
87
+ "juice": "^11.0.3",
88
+ "ora": "^8.2.0",
89
+ "puppeteer": "^24.26.1",
90
+ "react": "^18.2.0",
91
+ "react-dom": "^18.2.0",
92
+ "remark-gfm": "^4.0.0",
93
+ "storybook": "^8.6.14",
94
+ "tailwindcss": "^3.4.3",
95
+ "tsx": "^4.20.6",
96
+ "typescript": "^5.3.0",
97
+ "vite": "^5.0.0",
98
+ "vite-plugin-dts": "^4.5.0",
99
+ "vitest": "^4.1.1"
100
+ },
101
+ "engines": {
102
+ "node": ">=20.19"
103
+ }
104
+ }