@jokerized/decksmith 0.1.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.
Files changed (78) hide show
  1. package/README.md +794 -0
  2. package/dist/cli.js +8906 -0
  3. package/dist/deck-runtime.js +55 -0
  4. package/dist/index.js +8590 -0
  5. package/dist/mcp.js +7809 -0
  6. package/dist/server/errors.js +73 -0
  7. package/dist/server/http.js +504 -0
  8. package/dist/server/main.js +91 -0
  9. package/dist/server/options.js +198 -0
  10. package/dist/server/pipeline.js +356 -0
  11. package/dist/server/queue.js +195 -0
  12. package/dist/server/ui.js +1614 -0
  13. package/dist/server/upload.js +232 -0
  14. package/dist/types/cli.d.ts +1 -0
  15. package/dist/types/deck/runtime.d.ts +59 -0
  16. package/dist/types/deck/subtitles.d.ts +101 -0
  17. package/dist/types/emit/archetypes/annotated-figure.d.ts +103 -0
  18. package/dist/types/emit/archetypes/bar-compare.d.ts +30 -0
  19. package/dist/types/emit/archetypes/callout.d.ts +7 -0
  20. package/dist/types/emit/archetypes/claim-figure.d.ts +9 -0
  21. package/dist/types/emit/archetypes/data-table.d.ts +21 -0
  22. package/dist/types/emit/archetypes/equation-walk.d.ts +2 -0
  23. package/dist/types/emit/archetypes/grid.d.ts +16 -0
  24. package/dist/types/emit/archetypes/index.d.ts +19 -0
  25. package/dist/types/emit/archetypes/line-chart.d.ts +22 -0
  26. package/dist/types/emit/archetypes/pipeline.d.ts +81 -0
  27. package/dist/types/emit/archetypes/split-compare.d.ts +2 -0
  28. package/dist/types/emit/archetypes/stack.d.ts +93 -0
  29. package/dist/types/emit/archetypes/title.d.ts +188 -0
  30. package/dist/types/emit/camera.d.ts +397 -0
  31. package/dist/types/emit/composition.d.ts +191 -0
  32. package/dist/types/emit/island.d.ts +19 -0
  33. package/dist/types/emit/kit.d.ts +256 -0
  34. package/dist/types/emit/svg.d.ts +177 -0
  35. package/dist/types/emit/theme.d.ts +65 -0
  36. package/dist/types/emit/themes/index.d.ts +40 -0
  37. package/dist/types/emit/themes/ink.d.ts +12 -0
  38. package/dist/types/emit/themes/mono.d.ts +20 -0
  39. package/dist/types/emit/themes/paper.d.ts +18 -0
  40. package/dist/types/index.d.ts +200 -0
  41. package/dist/types/mcp/main.d.ts +2 -0
  42. package/dist/types/mcp/prereqs.d.ts +22 -0
  43. package/dist/types/mcp/tools.d.ts +212 -0
  44. package/dist/types/narrate/narrate.d.ts +87 -0
  45. package/dist/types/narrate/tts.d.ts +134 -0
  46. package/dist/types/narrate/voices.d.ts +29 -0
  47. package/dist/types/pack/media.d.ts +61 -0
  48. package/dist/types/pack/pack.d.ts +16 -0
  49. package/dist/types/plan/codex.d.ts +24 -0
  50. package/dist/types/plan/duration.d.ts +394 -0
  51. package/dist/types/plan/prompt.d.ts +47 -0
  52. package/dist/types/plan/refs.d.ts +22 -0
  53. package/dist/types/plan/select.d.ts +116 -0
  54. package/dist/types/prefs.d.ts +43 -0
  55. package/dist/types/render/captions.d.ts +108 -0
  56. package/dist/types/render/ffmpeg.d.ts +129 -0
  57. package/dist/types/render/render.d.ts +123 -0
  58. package/dist/types/render/timing.d.ts +290 -0
  59. package/dist/types/server/errors.d.ts +11 -0
  60. package/dist/types/server/http.d.ts +57 -0
  61. package/dist/types/server/main.d.ts +1 -0
  62. package/dist/types/server/options.d.ts +90 -0
  63. package/dist/types/server/pipeline.d.ts +21 -0
  64. package/dist/types/server/queue.d.ts +105 -0
  65. package/dist/types/server/ui.d.ts +9 -0
  66. package/dist/types/server/upload.d.ts +107 -0
  67. package/dist/types/source/assets.d.ts +11 -0
  68. package/dist/types/source/fonts.d.ts +15 -0
  69. package/dist/types/source/markdown.d.ts +8 -0
  70. package/dist/types/types.d.ts +1992 -0
  71. package/dist/types/verify/budget.d.ts +41 -0
  72. package/dist/types/verify/check.d.ts +78 -0
  73. package/dist/types/verify/drift.d.ts +158 -0
  74. package/dist/types/verify/fidelity.d.ts +247 -0
  75. package/dist/types/verify/index.d.ts +207 -0
  76. package/dist/types/verify/overprint.d.ts +133 -0
  77. package/dist/types/verify/typefloor.d.ts +50 -0
  78. package/package.json +84 -0
@@ -0,0 +1,107 @@
1
+ /**
2
+ * What arrives on the socket, treated as hostile.
3
+ *
4
+ * Three jobs, in order: get the bytes off the wire without letting the sender
5
+ * choose how much memory we spend, turn them into a file and a set of fields,
6
+ * and — if the file is a zip — get its contents onto disk without letting an
7
+ * entry name decide where "onto disk" is.
8
+ *
9
+ * Everything here is pure except `readBody`, which is why the zip half can be
10
+ * tested against an actually malicious archive with no server running.
11
+ */
12
+ import type { IncomingMessage } from "node:http";
13
+ /** 20 MB. A paper with its figures is a megabyte or two; ten times that is slack. */
14
+ export declare const MAX_UPLOAD_BYTES: number;
15
+ /**
16
+ * Caps on the archive AFTER decompression, which is the number that matters:
17
+ * deflate tops out near 1032:1, so the upload cap alone would allow a 20 MB zip
18
+ * to become 20 GB. See `readZip` for why the declared sizes are trustworthy
19
+ * enough to cap on.
20
+ */
21
+ export interface ZipLimits {
22
+ maxEntries: number;
23
+ maxTotalBytes: number;
24
+ maxEntryBytes: number;
25
+ }
26
+ export declare const ZIP_LIMITS: ZipLimits;
27
+ /** Extensions we will accept as the document itself. */
28
+ export declare const MARKDOWN_EXTS: string[];
29
+ /**
30
+ * An upload problem the sender can fix, as opposed to a bug. Carries the hint
31
+ * separately so the API can render "what went wrong" and "what to do" apart.
32
+ */
33
+ export declare class UploadError extends Error {
34
+ readonly hint: string;
35
+ readonly status: number;
36
+ constructor(message: string, hint: string, status?: number);
37
+ }
38
+ export declare function readBody(req: IncomingMessage, limit?: number): Promise<Buffer>;
39
+ export interface Upload {
40
+ /** The uploaded file's name as the browser reported it. Never used as a path. */
41
+ filename: string;
42
+ bytes: Uint8Array;
43
+ /** Every non-file field, last one wins. */
44
+ fields: Record<string, string>;
45
+ }
46
+ /**
47
+ * multipart/form-data, with no dependency.
48
+ *
49
+ * `new Response(body, { headers }).formData()` is undici's parser, which ships
50
+ * in Node — measured against a hand-built body with a filename containing a
51
+ * space, a UTF-8 payload and two scalar fields, and it returns a real `File`
52
+ * with the right bytes. It throws a bare TypeError on a malformed body, which
53
+ * is not a sentence anyone can act on, so it is translated here.
54
+ */
55
+ export declare function parseMultipart(body: Buffer, contentType: string): Promise<Upload>;
56
+ /** A zip starts "PK". Asked before unzipping so a PDF reads as a PDF. */
57
+ export declare function looksLikeZip(bytes: Uint8Array): boolean;
58
+ /**
59
+ * ZIP SLIP. An entry name is attacker-controlled text, not a path, and the only
60
+ * safe way to treat it is to rebuild the path from segments we have each
61
+ * inspected. Returns the relative path to write, or `null` when the name cannot
62
+ * be made safe.
63
+ *
64
+ * Rejected, each because it has been used to escape a directory somewhere:
65
+ * absolute paths; a Windows drive letter or UNC prefix; any `..` segment,
66
+ * including one hidden behind backslashes, which unzip implementations on
67
+ * Windows treat as a separator and POSIX ones do not; and NUL, which truncates
68
+ * the path in any C library the bytes later pass through.
69
+ *
70
+ * Note what is NOT a hole: a zip can carry a symlink, and a symlink pointing at
71
+ * /etc is the other classic escape — but fflate reports entries as bytes and we
72
+ * write them with `writeFile`, so a symlink entry lands as an ordinary file
73
+ * containing its target's text. There is no code path here that calls `symlink`.
74
+ */
75
+ export declare function safeEntryPath(name: string): string | null;
76
+ /** Belt and braces: the joined path must still be inside the root. */
77
+ export declare function insideRoot(root: string, joined: string): boolean;
78
+ export interface ZipContents {
79
+ /** Safe relative path (posix separators) → bytes. */
80
+ files: Record<string, Uint8Array>;
81
+ warnings: string[];
82
+ }
83
+ /**
84
+ * Unzip within the limits, or refuse.
85
+ *
86
+ * Two passes over the central directory. The first decompresses nothing — a
87
+ * filter returning false skips the inflate — and is where names and sizes are
88
+ * judged; the second extracts only what the first approved. Splitting them
89
+ * means a hostile entry is refused before any of the archive has been expanded,
90
+ * and it keeps the decision out of a callback that runs inside library code.
91
+ *
92
+ * MEASURED, because the cap depends on it: fflate allocates exactly the
93
+ * declared uncompressed size and truncates the inflate to it. An archive whose
94
+ * header lies — patched to claim 10 bytes for a 5 MB member — yields 10 bytes
95
+ * of memory and 10 bytes of garbage, not 5 MB. So capping on the declared sizes
96
+ * is a real memory bound and not a promise the attacker gets to keep. The
97
+ * post-hoc total below is there for the day that stops being true.
98
+ */
99
+ export declare function readZip(bytes: Uint8Array, limits?: ZipLimits): ZipContents;
100
+ /**
101
+ * Which file in the archive is the document.
102
+ *
103
+ * Shallowest wins, then a name that says so, then alphabetical — a paper's zip
104
+ * is usually one markdown at the top and a folder of figures, and when it is
105
+ * not, "the one nearest the root" is the guess a person would make.
106
+ */
107
+ export declare function pickMarkdown(files: Record<string, Uint8Array>): string;
@@ -0,0 +1,11 @@
1
+ import { type Source } from "../types.js";
2
+ /** Fetch every figure into `dir`, rewrite `src` to the local name, measure it. */
3
+ export declare function fetchFigures(source: Source, dir: string): Promise<Source>;
4
+ /**
5
+ * Intrinsic size from the file header. Just enough PNG/JPEG/GIF to answer the
6
+ * one question layout asks — four field reads do not justify a dependency.
7
+ */
8
+ export declare function imageSize(b: Buffer): {
9
+ width: number;
10
+ height: number;
11
+ };
@@ -0,0 +1,15 @@
1
+ export interface FontBundle {
2
+ /** Belongs at the head of the theme's font stack. */
3
+ family: string;
4
+ /** `@font-face` CSS with every `url()` rewritten to a bare name in `dir`. */
5
+ css: string;
6
+ /** The woff2 basenames written into `dir`, beside `fonts.css`. */
7
+ files: string[];
8
+ }
9
+ /** The family a language needs shipped, or null when the renderer supplies one. */
10
+ export declare function familyFor(lang: string): string | null;
11
+ /**
12
+ * Write `dir/fonts.css` plus its woff2 for `lang`, covering `glyphs`. Returns
13
+ * null for languages the renderer already resolves, which needs no bundle.
14
+ */
15
+ export declare function bundleFont(lang: string, glyphs: string, dir: string): Promise<FontBundle | null>;
@@ -0,0 +1,8 @@
1
+ import { type Source } from "../types.js";
2
+ export interface ParseOptions {
3
+ /** Stable document id. Defaults to a content hash, so re-parsing is idempotent. */
4
+ id?: string;
5
+ /** BCP-47 override. Defaults to a script sniff, which is what picks the font. */
6
+ lang?: string;
7
+ }
8
+ export declare function parseMarkdown(md: string, opts?: ParseOptions): Source;