slackmark-node 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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -0
  3. package/THIRD_PARTY_NOTICES.md +14 -0
  4. package/dist/create-node-converter.d.ts +72 -0
  5. package/dist/create-node-converter.d.ts.map +1 -0
  6. package/dist/errors.d.ts +60 -0
  7. package/dist/errors.d.ts.map +1 -0
  8. package/dist/image-output.d.ts +9 -0
  9. package/dist/image-output.d.ts.map +1 -0
  10. package/dist/index.d.ts +9 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +1792 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/katex-assets.d.ts +19 -0
  15. package/dist/katex-assets.d.ts.map +1 -0
  16. package/dist/katex-renderer.d.ts +39 -0
  17. package/dist/katex-renderer.d.ts.map +1 -0
  18. package/dist/mermaid-assets.d.ts +9 -0
  19. package/dist/mermaid-assets.d.ts.map +1 -0
  20. package/dist/mermaid-renderer.d.ts +33 -0
  21. package/dist/mermaid-renderer.d.ts.map +1 -0
  22. package/dist/node-options.d.ts +6 -0
  23. package/dist/node-options.d.ts.map +1 -0
  24. package/dist/operation-control.d.ts +18 -0
  25. package/dist/operation-control.d.ts.map +1 -0
  26. package/dist/puppeteer-render-runtime.d.ts +76 -0
  27. package/dist/puppeteer-render-runtime.d.ts.map +1 -0
  28. package/dist/puppeteer.d.ts +7 -0
  29. package/dist/puppeteer.d.ts.map +1 -0
  30. package/dist/puppeteer.js +723 -0
  31. package/dist/puppeteer.js.map +1 -0
  32. package/dist/renderers.d.ts +5 -0
  33. package/dist/renderers.d.ts.map +1 -0
  34. package/dist/renderers.js +551 -0
  35. package/dist/renderers.js.map +1 -0
  36. package/dist/status.d.ts +20 -0
  37. package/dist/status.d.ts.map +1 -0
  38. package/dist/upload-scheduler.d.ts +32 -0
  39. package/dist/upload-scheduler.d.ts.map +1 -0
  40. package/package.json +72 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Siraj
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 ADDED
@@ -0,0 +1,168 @@
1
+ # slackmark-node
2
+
3
+ Render Mermaid diagrams and display math to local PNGs, upload them, and emit native
4
+ Slack `slack_file` image blocks. Requires Node.js 22.12 or newer. Puppeteer downloads a
5
+ compatible browser during installation.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add slackmark slackmark-node
11
+ ```
12
+
13
+ ## Convert
14
+
15
+ ```ts snippet=compile
16
+ import { FetchSlackUploader } from "slackmark/slack";
17
+ import type { Block, UploadReceipt } from "slackmark";
18
+ import { createNodeConverter } from "slackmark-node";
19
+
20
+ declare const slackBotToken: string;
21
+ declare const agentMarkdown: string;
22
+ declare const channel: string;
23
+ declare function postPrepared(
24
+ prepared: PreparedPost,
25
+ timeoutMs: number,
26
+ ): Promise<{ readonly ok: true } | { readonly ok: false; readonly status: number }>;
27
+
28
+ interface PreparedPost {
29
+ readonly channel: string;
30
+ readonly threadTs?: string;
31
+ readonly blocks: ReadonlyArray<Block>;
32
+ readonly text: string;
33
+ readonly receipts: ReadonlyArray<UploadReceipt>;
34
+ }
35
+
36
+ class PostError extends Error {
37
+ readonly prepared: PreparedPost;
38
+ readonly ambiguous: boolean;
39
+
40
+ constructor(prepared: PreparedPost, cause: unknown, ambiguous: boolean) {
41
+ super("Slack post failed", { cause });
42
+ this.prepared = prepared;
43
+ this.ambiguous = ambiguous;
44
+ }
45
+ }
46
+
47
+ const converter = createNodeConverter({
48
+ uploader: new FetchSlackUploader({ token: slackBotToken }),
49
+ });
50
+
51
+ // Reuse this converter for every request; it owns one shared Chromium.
52
+ export async function deliver(): Promise<void> {
53
+ const result = await converter.convert(agentMarkdown, { timeoutMs: 30_000 });
54
+ const prepared: PreparedPost = {
55
+ channel,
56
+ blocks: result.blocks,
57
+ text: result.text,
58
+ receipts: result.receipts,
59
+ };
60
+ try {
61
+ const outcome = await postPrepared(prepared, 10_000);
62
+ if (!outcome.ok) {
63
+ throw new PostError(
64
+ prepared,
65
+ new Error(`Slack rejected with HTTP ${String(outcome.status)}`),
66
+ false,
67
+ );
68
+ }
69
+ } catch (cause) {
70
+ if (cause instanceof PostError) throw cause;
71
+ throw new PostError(prepared, cause, true);
72
+ }
73
+ }
74
+
75
+ // Close once, during awaited process shutdown — never per request. A closed converter
76
+ // rejects every later call. For a one-shot script that converts and exits, close in a
77
+ // `finally` and preserve the primary error with `AggregateError`.
78
+ export async function shutdown(): Promise<void> {
79
+ await converter.close({ behavior: "drain", timeoutMs: 5_000 });
80
+ }
81
+ ```
82
+
83
+ `PostError` retains the exact envelope; reusing it prevents re-upload but does not make
84
+ `chat.postMessage` idempotent. Ambiguous timeout/lost-response failures require
85
+ reconciliation or acceptance of duplicate-message risk; definite Slack rejection can
86
+ retry by app policy. Never reconvert. `prepared -> posted` persistence is only for app
87
+ crash recovery and does not create Slack idempotency. Do not broadly log receipts or
88
+ source-bearing URLs.
89
+
90
+ `timeoutMs` is relative to call start. `signal` and `timeoutMs` are optional on
91
+ `convert`, `convertToMessages`, and `warmup`. Per-call uploaders override the optional
92
+ factory uploader.
93
+
94
+ Convert/warmup have no default timeout. Close defaults to drain/5 seconds; async disposal
95
+ uses cancel/5 seconds. Browser launch and cleanup ceilings are 10 seconds and 2 seconds.
96
+
97
+ `close()` rejects new work immediately. Its default is bounded drain; use
98
+ `close({ behavior: "cancel" })` to request cooperative cancellation. `status()` reports
99
+ state, active/queued work, and retained upload bytes. `activeOperations` includes
100
+ `convert`, `convertToMessages`, and warmup calls until underlying settlement. During
101
+ converter closing, local render/upload `accepting` may remain true for work from already
102
+ accepted operations. Async disposal uses a finite cancel timeout. The first valid close
103
+ promise wins; any accepted close failure, including caller abort, leaves permanent
104
+ `close-failed` state.
105
+
106
+ ## Preserve built-ins while extending
107
+
108
+ ```ts snippet=compile
109
+ import type { UrlImageRenderer } from "slackmark";
110
+ import { createNodeConverter } from "slackmark-node";
111
+
112
+ declare const plantUmlService: {
113
+ render(source: string, options: { readonly signal?: AbortSignal | undefined }): Promise<string>;
114
+ };
115
+
116
+ const plantUml: UrlImageRenderer = {
117
+ id: "plantuml",
118
+ output: "url",
119
+ canRender: ({ lang }) => lang === "plantuml",
120
+ render: async ({ source, altText }, context) => {
121
+ const imageUrl = await plantUmlService.render(source, {
122
+ signal: context.signal,
123
+ });
124
+ return { kind: "url", imageUrl, altText };
125
+ },
126
+ };
127
+
128
+ const converter = createNodeConverter({
129
+ additionalRenderers: [plantUml],
130
+ upload: { concurrency: 2, maxQueueSize: 16 },
131
+ });
132
+ ```
133
+
134
+ Additional renderers run after local Mermaid and KaTeX. Native Slack Mermaid charts run
135
+ before every image renderer. Duplicate IDs are rejected. Use universal
136
+ `slackmark.createConverter()` only to replace the complete renderer list.
137
+
138
+ ## Receipts and errors
139
+
140
+ `degradations` describe content fallback or substitution. `receipts` preserve external
141
+ upload effects independently, including failed attempts hidden by later renderer
142
+ recovery. Receipts can contain sensitive Slack file IDs.
143
+
144
+ Recognise a caught error with `isOperationError` / `isConfigurationError` from `slackmark`
145
+ and `isSlackUploadError` from `slackmark/slack`. Each published entry is bundled
146
+ separately and carries its own copy of the error classes, so `instanceof` across entries
147
+ is a false negative.
148
+
149
+ Caller abort, deadline, and shutdown are distinct typed errors. Only
150
+ `NodeShutdownTimeoutError` includes a status snapshot; ordinary cleanup
151
+ `NodeRenderError` does not. A timeout rejects promptly but
152
+ cannot kill an arbitrary collaborator promise; queue slots and retained bytes remain
153
+ accounted until the underlying promise settles.
154
+
155
+ Prompt errors expose a frozen `receipts` snapshot and a non-rejecting
156
+ `settledReceipts` promise for final receipts from that operation. The latter may remain
157
+ pending if a collaborator never settles; callers choose any wait bound.
158
+
159
+ Mermaid and KaTeX run in isolated browser contexts with strict local assets, bounded
160
+ source/output limits, and browser egress denied. Advanced seams live at
161
+ `slackmark-node/renderers` and `slackmark-node/puppeteer`.
162
+
163
+ See the
164
+ [Rasterize content guide](https://github.com/SirajChokshi/slackmark/blob/main/apps/site/src/docs/slackmark/rasterize-content/overview.mdx).
165
+
166
+ ## License
167
+
168
+ MIT © Siraj. See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,14 @@
1
+ # Third-party notices
2
+
3
+ `slackmark-node` depends on:
4
+
5
+ - [`mermaid`](https://github.com/mermaid-js/mermaid), MIT License.
6
+ - [`katex`](https://github.com/KaTeX/KaTeX), MIT License, copyright Khan Academy and contributors.
7
+ - [`puppeteer`](https://github.com/puppeteer/puppeteer), Apache License 2.0, copyright Google LLC.
8
+
9
+ Puppeteer's install script downloads Chrome for Testing unless installation is configured
10
+ to skip browser downloads. Chrome and its bundled third-party components retain their
11
+ own licenses; the downloaded distribution includes the applicable notices.
12
+
13
+ Dependency license texts are distributed with their respective packages. This notice
14
+ does not alter their terms.
@@ -0,0 +1,72 @@
1
+ import { type ConversionMessagesResult, type ConversionResult, type ConvertOptions, type ImageRenderer, type OperationContext, type OperationOptions, type SlackMarkConverter, type SlackUploader } from "slackmark";
2
+ import type { LaunchOptions } from "puppeteer";
3
+ import type { KatexRendererOptions } from "./katex-renderer.js";
4
+ import type { MermaidRendererOptions } from "./mermaid-renderer.js";
5
+ import { type CloseBehavior, type RenderRuntime } from "./puppeteer-render-runtime.js";
6
+ import { type NodeConverterStatus } from "./status.js";
7
+ import { UploadScheduler } from "./upload-scheduler.js";
8
+ type NodeConversionDefaults = Omit<ConvertOptions, "renderers" | "uploader" | "signal" | "timeoutMs">;
9
+ export interface NodeRenderingOptions {
10
+ readonly concurrency?: number | undefined;
11
+ readonly maxQueueSize?: number | undefined;
12
+ readonly launchOptions?: LaunchOptions | undefined;
13
+ readonly mermaid?: Omit<MermaidRendererOptions, "runtime" | "assets"> | undefined;
14
+ readonly math?: Omit<KatexRendererOptions, "runtime" | "assets"> | undefined;
15
+ }
16
+ export interface NodeUploadOptions {
17
+ readonly concurrency?: number | undefined;
18
+ readonly maxQueueSize?: number | undefined;
19
+ }
20
+ export interface CreateNodeConverterOptions extends NodeConversionDefaults {
21
+ readonly rendering?: NodeRenderingOptions | undefined;
22
+ readonly upload?: NodeUploadOptions | undefined;
23
+ readonly additionalRenderers?: ReadonlyArray<ImageRenderer> | undefined;
24
+ readonly uploader?: SlackUploader | undefined;
25
+ }
26
+ export type NodeConvertOptions = NodeConversionDefaults & OperationOptions & {
27
+ readonly uploader?: SlackUploader | undefined;
28
+ };
29
+ export interface NodeCloseOptions extends OperationOptions {
30
+ readonly behavior?: CloseBehavior | undefined;
31
+ }
32
+ export interface NodeConverter extends AsyncDisposable {
33
+ convert(markdown: string, options?: NodeConvertOptions): Promise<ConversionResult>;
34
+ convertToMessages(markdown: string, options?: NodeConvertOptions): Promise<ConversionMessagesResult>;
35
+ warmup(options?: OperationOptions): Promise<void>;
36
+ close(options?: NodeCloseOptions): Promise<void>;
37
+ status(): NodeConverterStatus;
38
+ }
39
+ export interface ManagedNodeConverterDeps {
40
+ readonly converter: SlackMarkConverter;
41
+ readonly runtime: RenderRuntime;
42
+ readonly defaultUploader: SlackUploader | undefined;
43
+ readonly uploadScheduler: UploadScheduler;
44
+ readonly warmupOperation: (operation: OperationContext) => Promise<void>;
45
+ }
46
+ export declare class ManagedNodeConverter implements NodeConverter {
47
+ private readonly converter;
48
+ private readonly runtime;
49
+ private readonly defaultUploader;
50
+ private readonly uploadScheduler;
51
+ private readonly warmupOperation;
52
+ private readonly activeScopes;
53
+ private readonly activeReceipts;
54
+ private readonly idleResolvers;
55
+ private activeOperations;
56
+ private closePromise;
57
+ private state;
58
+ constructor(deps: ManagedNodeConverterDeps);
59
+ convert(markdown: string, options?: NodeConvertOptions): Promise<ConversionResult>;
60
+ convertToMessages(markdown: string, options?: NodeConvertOptions): Promise<ConversionMessagesResult>;
61
+ warmup(options?: OperationOptions): Promise<void>;
62
+ close(options?: NodeCloseOptions): Promise<void>;
63
+ status(): NodeConverterStatus;
64
+ [Symbol.asyncDispose](): Promise<void>;
65
+ private runTracked;
66
+ private finishTracked;
67
+ private finishClose;
68
+ private waitForIdle;
69
+ }
70
+ export declare function createNodeConverter(options?: CreateNodeConverterOptions): NodeConverter;
71
+ export {};
72
+ //# sourceMappingURL=create-node-converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-node-converter.d.ts","sourceRoot":"","sources":["../src/create-node-converter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { type OperationError, type StructuredRendererError, type UploadReceipt } from "slackmark";
2
+ import type { NodeConverterStatus } from "./status.js";
3
+ export declare const NodeRenderErrorCode: {
4
+ readonly AssetMissing: "asset_missing";
5
+ readonly BrowserBinaryMissing: "browser_binary_missing";
6
+ readonly BrowserDisconnected: "browser_disconnected";
7
+ readonly BrowserFailed: "browser_failed";
8
+ readonly CleanupFailed: "cleanup_failed";
9
+ readonly CloseFailed: "close_failed";
10
+ readonly ContextFailed: "context_failed";
11
+ readonly DimensionLimit: "dimension_limit";
12
+ readonly OutputLimit: "output_limit";
13
+ readonly QueueFull: "queue_full";
14
+ readonly RenderFailed: "render_failed";
15
+ readonly SourceLimit: "source_limit";
16
+ };
17
+ export type NodeRenderErrorCode = (typeof NodeRenderErrorCode)[keyof typeof NodeRenderErrorCode];
18
+ export declare const NodeRenderStage: {
19
+ readonly Admission: "admission";
20
+ readonly AssetLoad: "asset_load";
21
+ readonly Browser: "browser";
22
+ readonly BrowserCleanup: "browser_cleanup";
23
+ readonly BrowserClose: "browser_close";
24
+ readonly BrowserLaunch: "browser_launch";
25
+ readonly ContextCleanup: "context_cleanup";
26
+ readonly ContextCreate: "context_create";
27
+ readonly Layout: "layout";
28
+ readonly OutputValidation: "output_validation";
29
+ readonly Render: "render";
30
+ readonly SourceValidation: "source_validation";
31
+ };
32
+ export type NodeRenderStage = (typeof NodeRenderStage)[keyof typeof NodeRenderStage];
33
+ export interface NodeRenderErrorOptions {
34
+ readonly stage: NodeRenderStage;
35
+ readonly retryable: boolean;
36
+ readonly rendererId?: string | undefined;
37
+ readonly cause?: unknown;
38
+ }
39
+ export declare class NodeShutdownTimeoutError extends Error {
40
+ readonly name: string;
41
+ readonly code: "shutdown_timeout";
42
+ readonly stage: "close";
43
+ readonly retryable: true;
44
+ readonly status: NodeConverterStatus;
45
+ readonly receipts: ReadonlyArray<UploadReceipt>;
46
+ readonly settledReceipts: Promise<ReadonlyArray<UploadReceipt>>;
47
+ constructor(status: NodeConverterStatus, receipts: ReadonlyArray<UploadReceipt>, settledReceipts: Promise<ReadonlyArray<UploadReceipt>>);
48
+ }
49
+ /**
50
+ * Sanitized failure from the Node rendering boundary.
51
+ */
52
+ export declare class NodeRenderError extends Error implements StructuredRendererError {
53
+ readonly code: NodeRenderErrorCode;
54
+ readonly stage: NodeRenderStage;
55
+ readonly retryable: boolean;
56
+ readonly rendererId: string | undefined;
57
+ constructor(code: NodeRenderErrorCode, message: string, options?: NodeRenderErrorOptions);
58
+ }
59
+ export declare function normalizeNodeRenderError(error: unknown, code: NodeRenderErrorCode, message: string, stage?: NodeRenderStage, retryable?: boolean): NodeRenderError | OperationError;
60
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EACnB,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,mBAAmB;aAC9B,YAAY,EAAE,eAAe;aAC7B,oBAAoB,EAAE,wBAAwB;aAC9C,mBAAmB,EAAE,sBAAsB;aAC3C,aAAa,EAAE,gBAAgB;aAC/B,aAAa,EAAE,gBAAgB;aAC/B,WAAW,EAAE,cAAc;aAC3B,aAAa,EAAE,gBAAgB;aAC/B,cAAc,EAAE,iBAAiB;aACjC,WAAW,EAAE,cAAc;aAC3B,SAAS,EAAE,YAAY;aACvB,YAAY,EAAE,eAAe;aAC7B,WAAW,EAAE,cAAc;CACnB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,OAAO,mBAAmB,CAAC,CAAC;AAEjG,eAAO,MAAM,eAAe;aAC1B,SAAS,EAAE,WAAW;aACtB,SAAS,EAAE,YAAY;aACvB,OAAO,EAAE,SAAS;aAClB,cAAc,EAAE,iBAAiB;aACjC,YAAY,EAAE,eAAe;aAC7B,aAAa,EAAE,gBAAgB;aAC/B,cAAc,EAAE,iBAAiB;aACjC,aAAa,EAAE,gBAAgB;aAC/B,MAAM,EAAE,QAAQ;aAChB,gBAAgB,EAAE,mBAAmB;aACrC,MAAM,EAAE,QAAQ;aAChB,gBAAgB,EAAE,mBAAmB;CAC7B,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAErF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,SAAkB,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAEhE,YACE,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,EACtC,eAAe,EAAE,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,EAUvD;CACF;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAM,YAAW,uBAAuB;IAC3E,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC,YACE,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,sBAGR,EAQF;CACF;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,eAAwC,EAC/C,SAAS,UAAQ,GAChB,eAAe,GAAG,cAAc,CAIlC"}
@@ -0,0 +1,9 @@
1
+ export interface ImageLimits {
2
+ readonly maxOutputBytes: number;
3
+ readonly maxWidth: number;
4
+ readonly maxHeight: number;
5
+ }
6
+ export declare function deterministicPngFilename(prefix: string, source: string, optionsFingerprint: string): string;
7
+ export declare function assertSourceLimit(source: string, maxSourceChars: number): void;
8
+ export declare function assertPngLimits(data: Uint8Array, limits: ImageLimits): void;
9
+ //# sourceMappingURL=image-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-output.d.ts","sourceRoot":"","sources":["../src/image-output.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAUR;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAQ9E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAuB3E"}
@@ -0,0 +1,9 @@
1
+ export { createNodeConverter } from "./create-node-converter.js";
2
+ export type { CreateNodeConverterOptions, NodeCloseOptions, NodeConvertOptions, NodeConverter, NodeRenderingOptions, NodeUploadOptions, } from "./create-node-converter.js";
3
+ export { NodeRenderError, NodeRenderErrorCode, NodeRenderStage, NodeShutdownTimeoutError, } from "./errors.js";
4
+ export type { NodeRenderErrorOptions } from "./errors.js";
5
+ export { NodeConverterState } from "./status.js";
6
+ export type { NodeConverterStatus, NodeWorkStatus } from "./status.js";
7
+ export { ConfigurationError, OperationAbortedError, OperationDeadlineExceededError, OperationError, OperationErrorCode, OperationShutdownError, } from "slackmark";
8
+ export type { OperationOptions } from "slackmark";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EACV,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,wBAAwB,GACzB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,8BAA8B,EAC9B,cAAc,EACd,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}