react-next-editor-js 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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +877 -0
  3. package/dist/chunk-3QWXTDLY.cjs +486 -0
  4. package/dist/chunk-3QWXTDLY.cjs.map +1 -0
  5. package/dist/chunk-5F6SPYCN.cjs +180 -0
  6. package/dist/chunk-5F6SPYCN.cjs.map +1 -0
  7. package/dist/chunk-6NTSXJX4.js +174 -0
  8. package/dist/chunk-6NTSXJX4.js.map +1 -0
  9. package/dist/chunk-7VYJDBH7.js +261 -0
  10. package/dist/chunk-7VYJDBH7.js.map +1 -0
  11. package/dist/chunk-DBSFCCBG.cjs +1712 -0
  12. package/dist/chunk-DBSFCCBG.cjs.map +1 -0
  13. package/dist/chunk-EFE6RHDL.cjs +4 -0
  14. package/dist/chunk-EFE6RHDL.cjs.map +1 -0
  15. package/dist/chunk-G6YRIEK4.js +3 -0
  16. package/dist/chunk-G6YRIEK4.js.map +1 -0
  17. package/dist/chunk-GFNFJ3FL.cjs +119 -0
  18. package/dist/chunk-GFNFJ3FL.cjs.map +1 -0
  19. package/dist/chunk-IG2YLUFW.js +114 -0
  20. package/dist/chunk-IG2YLUFW.js.map +1 -0
  21. package/dist/chunk-JQXTWLHL.js +176 -0
  22. package/dist/chunk-JQXTWLHL.js.map +1 -0
  23. package/dist/chunk-NJCEHQV3.cjs +454 -0
  24. package/dist/chunk-NJCEHQV3.cjs.map +1 -0
  25. package/dist/chunk-O4GTLC3T.js +478 -0
  26. package/dist/chunk-O4GTLC3T.js.map +1 -0
  27. package/dist/chunk-ODHABIIC.cjs +82 -0
  28. package/dist/chunk-ODHABIIC.cjs.map +1 -0
  29. package/dist/chunk-PZ5AY32C.js +9 -0
  30. package/dist/chunk-PZ5AY32C.js.map +1 -0
  31. package/dist/chunk-Q7SFCCGT.cjs +11 -0
  32. package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
  33. package/dist/chunk-QIUIYBCZ.js +80 -0
  34. package/dist/chunk-QIUIYBCZ.js.map +1 -0
  35. package/dist/chunk-QROUNVQK.js +450 -0
  36. package/dist/chunk-QROUNVQK.js.map +1 -0
  37. package/dist/chunk-T6FR37IC.js +41 -0
  38. package/dist/chunk-T6FR37IC.js.map +1 -0
  39. package/dist/chunk-TI44I654.cjs +265 -0
  40. package/dist/chunk-TI44I654.cjs.map +1 -0
  41. package/dist/chunk-TXPLBAH5.cjs +47 -0
  42. package/dist/chunk-TXPLBAH5.cjs.map +1 -0
  43. package/dist/chunk-U3O54IYI.cjs +187 -0
  44. package/dist/chunk-U3O54IYI.cjs.map +1 -0
  45. package/dist/chunk-VLC7SZMT.js +1669 -0
  46. package/dist/chunk-VLC7SZMT.js.map +1 -0
  47. package/dist/core/index.cjs +232 -0
  48. package/dist/core/index.cjs.map +1 -0
  49. package/dist/core/index.d.cts +122 -0
  50. package/dist/core/index.d.ts +122 -0
  51. package/dist/core/index.js +7 -0
  52. package/dist/core/index.js.map +1 -0
  53. package/dist/defaults-EQD5QKCU.js +4 -0
  54. package/dist/defaults-EQD5QKCU.js.map +1 -0
  55. package/dist/defaults-MLYXD2BG.cjs +49 -0
  56. package/dist/defaults-MLYXD2BG.cjs.map +1 -0
  57. package/dist/docx-BUrf4PFj.d.ts +49 -0
  58. package/dist/docx-DLfSdvXm.d.cts +49 -0
  59. package/dist/docx-LDETXV3L.js +5 -0
  60. package/dist/docx-LDETXV3L.js.map +1 -0
  61. package/dist/docx-N2LKIOK3.cjs +14 -0
  62. package/dist/docx-N2LKIOK3.cjs.map +1 -0
  63. package/dist/export/index.cjs +54 -0
  64. package/dist/export/index.cjs.map +1 -0
  65. package/dist/export/index.d.cts +60 -0
  66. package/dist/export/index.d.ts +60 -0
  67. package/dist/export/index.js +9 -0
  68. package/dist/export/index.js.map +1 -0
  69. package/dist/html-5BXJPQU3.js +7 -0
  70. package/dist/html-5BXJPQU3.js.map +1 -0
  71. package/dist/html-KU2KHLRF.cjs +24 -0
  72. package/dist/html-KU2KHLRF.cjs.map +1 -0
  73. package/dist/import/index.cjs +15 -0
  74. package/dist/import/index.cjs.map +1 -0
  75. package/dist/import/index.d.cts +37 -0
  76. package/dist/import/index.d.ts +37 -0
  77. package/dist/import/index.js +6 -0
  78. package/dist/import/index.js.map +1 -0
  79. package/dist/index.cjs +1035 -0
  80. package/dist/index.cjs.map +1 -0
  81. package/dist/index.d.cts +248 -0
  82. package/dist/index.d.ts +248 -0
  83. package/dist/index.js +885 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/persistence/index.cjs +37 -0
  86. package/dist/persistence/index.cjs.map +1 -0
  87. package/dist/persistence/index.d.cts +279 -0
  88. package/dist/persistence/index.d.ts +279 -0
  89. package/dist/persistence/index.js +4 -0
  90. package/dist/persistence/index.js.map +1 -0
  91. package/dist/sanitize-7IZ-SW1f.d.ts +361 -0
  92. package/dist/sanitize-CvmgqbsA.d.cts +361 -0
  93. package/dist/server/index.cjs +400 -0
  94. package/dist/server/index.cjs.map +1 -0
  95. package/dist/server/index.d.cts +229 -0
  96. package/dist/server/index.d.ts +229 -0
  97. package/dist/server/index.js +390 -0
  98. package/dist/server/index.js.map +1 -0
  99. package/dist/styles.css +680 -0
  100. package/dist/types-B4z0Quvv.d.cts +193 -0
  101. package/dist/types-B4z0Quvv.d.ts +193 -0
  102. package/package.json +183 -0
@@ -0,0 +1,400 @@
1
+ 'use strict';
2
+
3
+ var chunkNJCEHQV3_cjs = require('../chunk-NJCEHQV3.cjs');
4
+ var chunkTI44I654_cjs = require('../chunk-TI44I654.cjs');
5
+ require('../chunk-TXPLBAH5.cjs');
6
+ require('../chunk-5F6SPYCN.cjs');
7
+ var chunkU3O54IYI_cjs = require('../chunk-U3O54IYI.cjs');
8
+ require('../chunk-Q7SFCCGT.cjs');
9
+
10
+ // src/server/types.ts
11
+ var CONTENT_TYPES = {
12
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
13
+ pdf: "application/pdf",
14
+ txt: "text/plain; charset=utf-8",
15
+ html: "text/html; charset=utf-8"
16
+ };
17
+ var FILE_EXTENSIONS = {
18
+ docx: "docx",
19
+ pdf: "pdf",
20
+ txt: "txt",
21
+ html: "html"
22
+ };
23
+
24
+ // src/server/service.ts
25
+ function encodeText(text) {
26
+ return new TextEncoder().encode(text);
27
+ }
28
+ var ExportService = class {
29
+ constructor(options = {}) {
30
+ this.jobs = /* @__PURE__ */ new Map();
31
+ this.jobSeq = 0;
32
+ this.options = options;
33
+ if (!options.authorize) {
34
+ console.warn(
35
+ "react-next-editor: ExportService created without an `authorize` hook \u2014 all requests are allowed. Provide `authorize` to enforce access control (F-6.15)."
36
+ );
37
+ }
38
+ }
39
+ /** Render a single export request (synchronous result). */
40
+ async export(request, context = {}) {
41
+ const base = this.baseResult(request);
42
+ try {
43
+ if (this.options.authorize) {
44
+ let allowed = false;
45
+ try {
46
+ allowed = await this.options.authorize(request, context);
47
+ } catch {
48
+ allowed = false;
49
+ }
50
+ if (!allowed) return { ...base, status: "error", error: "unauthorized" };
51
+ }
52
+ const doc = await this.resolveDocument(request);
53
+ if (!doc) {
54
+ return { ...base, status: "error", error: "document not found" };
55
+ }
56
+ const { bytes, contentType } = await this.render(request.format, doc, request);
57
+ if (request.store) {
58
+ if (!this.options.storage) {
59
+ return { ...base, status: "error", error: "no storage adapter configured" };
60
+ }
61
+ const { url, ref } = await this.options.storage.write(base.filename, bytes, contentType);
62
+ return { ...base, status: "ok", contentType, url, ref };
63
+ }
64
+ return { ...base, status: "ok", contentType, bytes };
65
+ } catch (err) {
66
+ return { ...base, status: "error", error: err?.message ?? "export failed" };
67
+ }
68
+ }
69
+ /**
70
+ * Render multiple requests in one call (F-6.12), each with independent status
71
+ * (F-6.17). Failures of one item do not abort the others.
72
+ */
73
+ async exportBatch(requests, context = {}) {
74
+ return Promise.all(requests.map((req) => this.export(req, context)));
75
+ }
76
+ /**
77
+ * Enqueue a batch as an asynchronous job (F-6.13). Returns immediately with a
78
+ * job id; poll {@link getJob} for status/results. This is a simple in-process
79
+ * runner — swap in a durable queue (e.g. BullMQ) for production scale.
80
+ */
81
+ enqueue(requests, context = {}) {
82
+ const id = `job-${Date.now()}-${++this.jobSeq}`;
83
+ const job = {
84
+ id,
85
+ status: "pending",
86
+ total: requests.length,
87
+ completed: 0,
88
+ results: [],
89
+ createdAt: Date.now()
90
+ };
91
+ this.jobs.set(id, job);
92
+ void (async () => {
93
+ job.status = "running";
94
+ try {
95
+ for (const req of requests) {
96
+ const result = await this.export(req, context);
97
+ job.results.push(result);
98
+ job.completed++;
99
+ }
100
+ job.status = "completed";
101
+ } catch (err) {
102
+ job.status = "failed";
103
+ job.error = err?.message ?? "job failed";
104
+ } finally {
105
+ job.finishedAt = Date.now();
106
+ }
107
+ })();
108
+ return { jobId: id };
109
+ }
110
+ /** Look up an async job's status and results. */
111
+ getJob(jobId) {
112
+ return this.jobs.get(jobId) ?? null;
113
+ }
114
+ /** Release renderer resources (e.g. close the headless browser). */
115
+ async close() {
116
+ await this.options.pdfRenderer?.close?.();
117
+ }
118
+ // --- internals ---
119
+ baseResult(request) {
120
+ const name = request.options?.filename ?? request.documentId ?? request.options?.title ?? "document";
121
+ const ext = FILE_EXTENSIONS[request.format];
122
+ const filename = name.toLowerCase().endsWith(`.${ext}`) ? name : `${name}.${ext}`;
123
+ return {
124
+ status: "error",
125
+ format: request.format,
126
+ filename,
127
+ contentType: CONTENT_TYPES[request.format],
128
+ documentId: request.documentId
129
+ };
130
+ }
131
+ async resolveDocument(request) {
132
+ if (request.documentJson) return request.documentJson;
133
+ if (request.documentId && this.options.store) {
134
+ return this.options.store.loadDocument(request.documentId);
135
+ }
136
+ return null;
137
+ }
138
+ async render(format, doc, request) {
139
+ const page = request.options?.page ?? chunkU3O54IYI_cjs.DEFAULT_PAGE;
140
+ const title = request.options?.title ?? request.options?.filename;
141
+ switch (format) {
142
+ case "docx": {
143
+ const buffer = await chunkNJCEHQV3_cjs.documentToDocxBuffer(doc, {
144
+ page,
145
+ title,
146
+ nodeConverters: this.options.nodeConverters
147
+ });
148
+ return { bytes: new Uint8Array(buffer), contentType: CONTENT_TYPES.docx };
149
+ }
150
+ case "txt":
151
+ return {
152
+ bytes: encodeText(chunkNJCEHQV3_cjs.documentToText(doc, request.options?.text)),
153
+ contentType: CONTENT_TYPES.txt
154
+ };
155
+ case "html":
156
+ return {
157
+ bytes: encodeText(chunkTI44I654_cjs.buildPrintDocument(doc, page, title)),
158
+ contentType: CONTENT_TYPES.html
159
+ };
160
+ case "pdf": {
161
+ if (!this.options.pdfRenderer) {
162
+ throw new Error("no PDF renderer configured");
163
+ }
164
+ const html = chunkTI44I654_cjs.buildPrintDocument(doc, page, title);
165
+ const bytes = await this.options.pdfRenderer.render(html, { page });
166
+ return { bytes, contentType: CONTENT_TYPES.pdf };
167
+ }
168
+ default:
169
+ throw new Error(`unsupported format: ${String(format)}`);
170
+ }
171
+ }
172
+ };
173
+ function createExportService(options = {}) {
174
+ return new ExportService(options);
175
+ }
176
+
177
+ // src/server/http.ts
178
+ function createExportHandler(service) {
179
+ return async function handle(request) {
180
+ if (request.method !== "POST") {
181
+ return json({ error: "method not allowed" }, 405);
182
+ }
183
+ let body;
184
+ try {
185
+ body = await request.json();
186
+ } catch {
187
+ return json({ error: "invalid JSON body" }, 400);
188
+ }
189
+ const context = { token: bearerToken(request), headers: headerRecord(request) };
190
+ if (isRecord(body) && typeof body.jobId === "string") {
191
+ const job = service.getJob(body.jobId);
192
+ return job ? json(job) : json({ error: "job not found" }, 404);
193
+ }
194
+ if (isRecord(body) && Array.isArray(body.requests)) {
195
+ const requests = body.requests;
196
+ if (body.async === true) {
197
+ return json(service.enqueue(requests, context), 202);
198
+ }
199
+ const results = await service.exportBatch(requests, context);
200
+ return json({ results: results.map(serializeResult) });
201
+ }
202
+ if (isRecord(body) && typeof body.format === "string") {
203
+ const result = await service.export(body, context);
204
+ if (result.status === "error") {
205
+ return json({ ...serializeResult(result) }, statusForError(result.error));
206
+ }
207
+ if (result.url) {
208
+ return json(serializeResult(result));
209
+ }
210
+ return new Response(result.bytes, {
211
+ status: 200,
212
+ headers: {
213
+ "Content-Type": result.contentType,
214
+ "Content-Disposition": `attachment; filename="${result.filename}"`,
215
+ "Cache-Control": "no-store"
216
+ }
217
+ });
218
+ }
219
+ return json({ error: "malformed request" }, 400);
220
+ };
221
+ }
222
+ function serializeResult(result) {
223
+ const { bytes, ...rest } = result;
224
+ return bytes && !result.url ? { ...rest, base64: toBase64(bytes) } : rest;
225
+ }
226
+ function statusForError(error) {
227
+ if (error === "unauthorized") return 401;
228
+ if (error === "document not found") return 404;
229
+ return 400;
230
+ }
231
+ function json(data, status = 200) {
232
+ return new Response(JSON.stringify(data), {
233
+ status,
234
+ headers: { "Content-Type": "application/json; charset=utf-8" }
235
+ });
236
+ }
237
+ function bearerToken(request) {
238
+ const auth = request.headers.get("authorization");
239
+ if (!auth) return null;
240
+ const match = /^Bearer\s+(.+)$/i.exec(auth);
241
+ return match ? match[1] : null;
242
+ }
243
+ function headerRecord(request) {
244
+ const out = {};
245
+ request.headers.forEach((value, key) => {
246
+ out[key] = value;
247
+ });
248
+ return out;
249
+ }
250
+ function isRecord(value) {
251
+ return typeof value === "object" && value !== null;
252
+ }
253
+ function toBase64(bytes) {
254
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
255
+ let binary = "";
256
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
257
+ return btoa(binary);
258
+ }
259
+
260
+ // src/server/storage.ts
261
+ var MemoryStorage = class {
262
+ constructor() {
263
+ this.files = /* @__PURE__ */ new Map();
264
+ }
265
+ async write(key, data, contentType) {
266
+ this.files.set(key, { data, contentType });
267
+ return { url: `memory:${key}`, ref: key };
268
+ }
269
+ get(key) {
270
+ return this.files.get(key);
271
+ }
272
+ keys() {
273
+ return [...this.files.keys()];
274
+ }
275
+ };
276
+ var FilesystemStorage = class {
277
+ constructor(options) {
278
+ this.baseDir = options.baseDir;
279
+ this.baseUrl = options.baseUrl;
280
+ }
281
+ async write(key, data, _contentType) {
282
+ const { dirname, resolve, relative, isAbsolute, sep } = await import('path');
283
+ const { mkdir, writeFile } = await import('fs/promises');
284
+ const root = resolve(this.baseDir);
285
+ const cleanedKey = key.replace(/^[/\\]+/, "");
286
+ const filePath = resolve(root, cleanedKey);
287
+ const rel = relative(root, filePath);
288
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) {
289
+ throw new Error(`react-next-editor: unsafe storage key rejected: ${key}`);
290
+ }
291
+ await mkdir(dirname(filePath), { recursive: true });
292
+ await writeFile(filePath, data);
293
+ const urlKey = rel.split(sep).join("/");
294
+ const url = this.baseUrl ? `${this.baseUrl.replace(/\/$/, "")}/${urlKey}` : filePath;
295
+ return { url, ref: filePath };
296
+ }
297
+ };
298
+
299
+ // src/server/pdf-renderer.ts
300
+ function createPlaywrightPdfRenderer(options = {}) {
301
+ let browserPromise = null;
302
+ async function getBrowser() {
303
+ if (!browserPromise) {
304
+ browserPromise = (async () => {
305
+ let mod;
306
+ try {
307
+ const spec = "playwright";
308
+ mod = await import(spec);
309
+ } catch {
310
+ throw new Error(
311
+ "react-next-editor: server PDF requires 'playwright'. Install it (npm i playwright) or provide a custom PdfRenderer."
312
+ );
313
+ }
314
+ if (!mod.chromium) throw new Error("react-next-editor: playwright.chromium is unavailable.");
315
+ return mod.chromium.launch({ args: options.launchArgs ?? [] });
316
+ })();
317
+ }
318
+ return browserPromise;
319
+ }
320
+ return {
321
+ async render(html, _opts) {
322
+ const browser = await getBrowser();
323
+ const page = await browser.newPage();
324
+ try {
325
+ await page.setContent(html, { waitUntil: "networkidle" });
326
+ const buffer = await page.pdf({
327
+ printBackground: options.printBackground ?? true,
328
+ preferCSSPageSize: options.preferCSSPageSize ?? true
329
+ });
330
+ return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
331
+ } finally {
332
+ await page.close();
333
+ }
334
+ },
335
+ async close() {
336
+ if (browserPromise) {
337
+ const browser = await browserPromise;
338
+ await browser.close();
339
+ browserPromise = null;
340
+ }
341
+ }
342
+ };
343
+ }
344
+ function createPuppeteerPdfRenderer(options = {}) {
345
+ let browserPromise = null;
346
+ async function getBrowser() {
347
+ if (!browserPromise) {
348
+ browserPromise = (async () => {
349
+ let mod;
350
+ try {
351
+ const spec = "puppeteer";
352
+ mod = await import(spec);
353
+ } catch {
354
+ throw new Error(
355
+ "react-next-editor: server PDF requires 'puppeteer'. Install it (npm i puppeteer) or provide a custom PdfRenderer."
356
+ );
357
+ }
358
+ const launcher = mod.default;
359
+ if (!launcher) throw new Error("react-next-editor: puppeteer launcher is unavailable.");
360
+ return launcher.launch({ args: options.launchArgs ?? [] });
361
+ })();
362
+ }
363
+ return browserPromise;
364
+ }
365
+ return {
366
+ async render(html, _opts) {
367
+ const browser = await getBrowser();
368
+ const page = await browser.newPage();
369
+ try {
370
+ await page.setContent(html, { waitUntil: "networkidle0" });
371
+ const buffer = await page.pdf({
372
+ printBackground: options.printBackground ?? true,
373
+ preferCSSPageSize: options.preferCSSPageSize ?? true
374
+ });
375
+ return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
376
+ } finally {
377
+ await page.close();
378
+ }
379
+ },
380
+ async close() {
381
+ if (browserPromise) {
382
+ const browser = await browserPromise;
383
+ await browser.close();
384
+ browserPromise = null;
385
+ }
386
+ }
387
+ };
388
+ }
389
+
390
+ exports.CONTENT_TYPES = CONTENT_TYPES;
391
+ exports.ExportService = ExportService;
392
+ exports.FILE_EXTENSIONS = FILE_EXTENSIONS;
393
+ exports.FilesystemStorage = FilesystemStorage;
394
+ exports.MemoryStorage = MemoryStorage;
395
+ exports.createExportHandler = createExportHandler;
396
+ exports.createExportService = createExportService;
397
+ exports.createPlaywrightPdfRenderer = createPlaywrightPdfRenderer;
398
+ exports.createPuppeteerPdfRenderer = createPuppeteerPdfRenderer;
399
+ //# sourceMappingURL=index.cjs.map
400
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/server/types.ts","../../src/server/service.ts","../../src/server/http.ts","../../src/server/storage.ts","../../src/server/pdf-renderer.ts"],"names":["DEFAULT_PAGE","documentToDocxBuffer","documentToText","buildPrintDocument"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { DocumentJSON, PageConfig } from '../config/types';\nimport type { TextConversionOptions } from '../export/text';\nimport type { DocxNodeConverter } from '../export/docx';\n\n/**\n * Programmatic export service types (§5.6.2, §8.8). This module is server-side\n * (Node) and never imports the React layer or any DOM. It consumes the same\n * isomorphic converters the client uses, so output is consistent (F-6.11).\n *\n * It is OPTIONAL and additive (C-1): editing and offline/client export do not\n * depend on it.\n */\n\n/** Supported programmatic export formats. */\nexport type ServerExportFormat = 'docx' | 'pdf' | 'txt' | 'html';\n\n/** MIME types for the supported formats. */\nexport const CONTENT_TYPES: Record<ServerExportFormat, string> = {\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n pdf: 'application/pdf',\n txt: 'text/plain; charset=utf-8',\n html: 'text/html; charset=utf-8',\n};\n\nexport const FILE_EXTENSIONS: Record<ServerExportFormat, string> = {\n docx: 'docx',\n pdf: 'pdf',\n txt: 'txt',\n html: 'html',\n};\n\n/** A single export request: a document (by id or inline) and a target format. */\nexport interface ExportRequest {\n /** Stored document id, resolved via the injected {@link DocumentStoreReader}. */\n documentId?: string;\n /** Inline document JSON (used instead of, or as a fallback for, `documentId`). */\n documentJson?: DocumentJSON;\n format: ServerExportFormat;\n options?: {\n page?: PageConfig;\n title?: string;\n /** Base filename (without extension). Defaults to documentId/title/'document'. */\n filename?: string;\n text?: TextConversionOptions;\n };\n /**\n * When true (and a {@link StorageAdapter} is configured), the rendered file is\n * written to storage and a reference/URL is returned (F-6.10). Otherwise the\n * bytes are returned inline.\n */\n store?: boolean;\n}\n\n/** Result of a single export. Never throws; failures are reported here (F-6.17). */\nexport interface ExportResult {\n status: 'ok' | 'error';\n format: ServerExportFormat;\n filename: string;\n contentType: string;\n /** Present when not stored: the rendered bytes. */\n bytes?: Uint8Array;\n /** Present when stored: a URL to fetch the file. */\n url?: string;\n /** Present when stored: an opaque storage reference (e.g. a path or key). */\n ref?: string;\n /** Identifies which input produced this result in a batch. */\n documentId?: string;\n error?: string;\n}\n\n/**\n * Reads stored document JSON by id, without a live editor (F-6.9). Inject your\n * backend/data-store implementation.\n */\nexport interface DocumentStoreReader {\n loadDocument(id: string): Promise<DocumentJSON | null>;\n}\n\n/**\n * Persists rendered files to system/object storage and returns a reference/URL\n * (F-6.10). Filesystem and in-memory implementations ship with the package.\n */\nexport interface StorageAdapter {\n write(key: string, data: Uint8Array, contentType: string): Promise<{ url: string; ref: string }>;\n}\n\n/**\n * Renders the shared print HTML to a PDF using a headless browser (F-6.14).\n * Injected so the package does not hard-depend on Puppeteer/Playwright. A\n * Playwright-based factory is provided ({@link createPlaywrightPdfRenderer}).\n */\nexport interface PdfRenderer {\n render(html: string, options?: { page?: PageConfig }): Promise<Uint8Array>;\n /** Release resources (e.g. close the browser). */\n close?(): Promise<void>;\n}\n\n/** Context passed to the authorization hook (e.g. headers, token, user). */\nexport interface ExportAuthContext {\n headers?: Record<string, string | undefined>;\n token?: string | null;\n [key: string]: unknown;\n}\n\nexport interface ExportServiceOptions {\n /** Resolves `documentId` to stored JSON (F-6.9). Required for id-based exports. */\n store?: DocumentStoreReader;\n /** Writes rendered files to storage (F-6.10). Required for `store: true` exports. */\n storage?: StorageAdapter;\n /** Server PDF renderer (F-6.14). Required for `format: 'pdf'`. */\n pdfRenderer?: PdfRenderer;\n /** Custom DOCX node converters, matching the client's (F-6.16). */\n nodeConverters?: Record<string, DocxNodeConverter>;\n /**\n * Authorize a request and its document access (F-6.15). Return false to reject.\n * Throwing is also treated as a rejection.\n */\n authorize?: (request: ExportRequest, context: ExportAuthContext) => Promise<boolean> | boolean;\n}\n\n/** Status of an asynchronous batch job (F-6.13). */\nexport interface ExportJob {\n id: string;\n status: 'pending' | 'running' | 'completed' | 'failed';\n total: number;\n completed: number;\n results: ExportResult[];\n createdAt: number;\n finishedAt?: number;\n error?: string;\n}\n","import type { DocumentJSON } from '../config/types';\nimport { DEFAULT_PAGE } from '../config/defaults';\nimport { documentToDocxBuffer } from '../export/docx';\nimport { documentToText } from '../export/text';\nimport { buildPrintDocument } from '../export/html';\nimport {\n CONTENT_TYPES,\n FILE_EXTENSIONS,\n type ExportAuthContext,\n type ExportJob,\n type ExportRequest,\n type ExportResult,\n type ExportServiceOptions,\n type ServerExportFormat,\n} from './types';\n\nfunction encodeText(text: string): Uint8Array {\n return new TextEncoder().encode(text);\n}\n\n/**\n * The programmatic export service (§8.8). Converts our own stored/inline JSON to\n * DOCX/PDF/text/HTML using the shared isomorphic converters, optionally persists\n * the result to storage, and reports per-document status. It is authenticated/\n * access-controlled via the injected `authorize` hook (F-6.15) and never emits a\n * malformed file silently — failures are returned as `status: 'error'` (F-6.17).\n */\nexport class ExportService {\n private readonly options: ExportServiceOptions;\n private readonly jobs = new Map<string, ExportJob>();\n private jobSeq = 0;\n\n constructor(options: ExportServiceOptions = {}) {\n this.options = options;\n if (!options.authorize) {\n // eslint-disable-next-line no-console\n console.warn(\n 'react-next-editor: ExportService created without an `authorize` hook — ' +\n 'all requests are allowed. Provide `authorize` to enforce access control (F-6.15).',\n );\n }\n }\n\n /** Render a single export request (synchronous result). */\n async export(request: ExportRequest, context: ExportAuthContext = {}): Promise<ExportResult> {\n const base = this.baseResult(request);\n try {\n if (this.options.authorize) {\n let allowed = false;\n try {\n allowed = await this.options.authorize(request, context);\n } catch {\n allowed = false;\n }\n if (!allowed) return { ...base, status: 'error', error: 'unauthorized' };\n }\n\n const doc = await this.resolveDocument(request);\n if (!doc) {\n return { ...base, status: 'error', error: 'document not found' };\n }\n\n const { bytes, contentType } = await this.render(request.format, doc, request);\n\n if (request.store) {\n if (!this.options.storage) {\n return { ...base, status: 'error', error: 'no storage adapter configured' };\n }\n const { url, ref } = await this.options.storage.write(base.filename, bytes, contentType);\n return { ...base, status: 'ok', contentType, url, ref };\n }\n\n return { ...base, status: 'ok', contentType, bytes };\n } catch (err) {\n return { ...base, status: 'error', error: (err as Error)?.message ?? 'export failed' };\n }\n }\n\n /**\n * Render multiple requests in one call (F-6.12), each with independent status\n * (F-6.17). Failures of one item do not abort the others.\n */\n async exportBatch(\n requests: ExportRequest[],\n context: ExportAuthContext = {},\n ): Promise<ExportResult[]> {\n return Promise.all(requests.map((req) => this.export(req, context)));\n }\n\n /**\n * Enqueue a batch as an asynchronous job (F-6.13). Returns immediately with a\n * job id; poll {@link getJob} for status/results. This is a simple in-process\n * runner — swap in a durable queue (e.g. BullMQ) for production scale.\n */\n enqueue(requests: ExportRequest[], context: ExportAuthContext = {}): { jobId: string } {\n const id = `job-${Date.now()}-${++this.jobSeq}`;\n const job: ExportJob = {\n id,\n status: 'pending',\n total: requests.length,\n completed: 0,\n results: [],\n createdAt: Date.now(),\n };\n this.jobs.set(id, job);\n\n void (async () => {\n job.status = 'running';\n try {\n for (const req of requests) {\n const result = await this.export(req, context);\n job.results.push(result);\n job.completed++;\n }\n job.status = 'completed';\n } catch (err) {\n job.status = 'failed';\n job.error = (err as Error)?.message ?? 'job failed';\n } finally {\n job.finishedAt = Date.now();\n }\n })();\n\n return { jobId: id };\n }\n\n /** Look up an async job's status and results. */\n getJob(jobId: string): ExportJob | null {\n return this.jobs.get(jobId) ?? null;\n }\n\n /** Release renderer resources (e.g. close the headless browser). */\n async close(): Promise<void> {\n await this.options.pdfRenderer?.close?.();\n }\n\n // --- internals ---\n\n private baseResult(request: ExportRequest): ExportResult {\n const name = request.options?.filename ?? request.documentId ?? request.options?.title ?? 'document';\n const ext = FILE_EXTENSIONS[request.format];\n const filename = name.toLowerCase().endsWith(`.${ext}`) ? name : `${name}.${ext}`;\n return {\n status: 'error',\n format: request.format,\n filename,\n contentType: CONTENT_TYPES[request.format],\n documentId: request.documentId,\n };\n }\n\n private async resolveDocument(request: ExportRequest): Promise<DocumentJSON | null> {\n if (request.documentJson) return request.documentJson;\n if (request.documentId && this.options.store) {\n return this.options.store.loadDocument(request.documentId);\n }\n return null;\n }\n\n private async render(\n format: ServerExportFormat,\n doc: DocumentJSON,\n request: ExportRequest,\n ): Promise<{ bytes: Uint8Array; contentType: string }> {\n const page = request.options?.page ?? DEFAULT_PAGE;\n const title = request.options?.title ?? request.options?.filename;\n switch (format) {\n case 'docx': {\n const buffer = await documentToDocxBuffer(doc, {\n page,\n title,\n nodeConverters: this.options.nodeConverters,\n });\n return { bytes: new Uint8Array(buffer), contentType: CONTENT_TYPES.docx };\n }\n case 'txt':\n return {\n bytes: encodeText(documentToText(doc, request.options?.text)),\n contentType: CONTENT_TYPES.txt,\n };\n case 'html':\n return {\n bytes: encodeText(buildPrintDocument(doc, page, title)),\n contentType: CONTENT_TYPES.html,\n };\n case 'pdf': {\n if (!this.options.pdfRenderer) {\n throw new Error('no PDF renderer configured');\n }\n const html = buildPrintDocument(doc, page, title);\n const bytes = await this.options.pdfRenderer.render(html, { page });\n return { bytes, contentType: CONTENT_TYPES.pdf };\n }\n default:\n throw new Error(`unsupported format: ${String(format)}`);\n }\n }\n}\n\n/** Create a configured {@link ExportService}. */\nexport function createExportService(options: ExportServiceOptions = {}): ExportService {\n return new ExportService(options);\n}\n","import type { ExportService } from './service';\nimport type { ExportRequest, ExportResult } from './types';\n\n/**\n * A web-standard `(Request) => Promise<Response>` handler factory for the export\n * service (F-6.8). It works directly as a Next.js App Router route handler, or\n * in any Fetch-API server. Authentication is delegated to the service's\n * `authorize` hook; the Bearer token (if any) is passed through as context.\n *\n * Request body shapes (POST, JSON):\n * - `{ jobId }` → returns the async job status\n * - `{ async: true, requests: [...] }` → enqueues a batch, returns `{ jobId }`\n * - `{ requests: [...] }` → synchronous batch, returns `{ results }`\n * - a single {@link ExportRequest} → returns the file (binary) or a `{ url }`\n */\nexport function createExportHandler(service: ExportService) {\n return async function handle(request: Request): Promise<Response> {\n if (request.method !== 'POST') {\n return json({ error: 'method not allowed' }, 405);\n }\n\n let body: unknown;\n try {\n body = await request.json();\n } catch {\n return json({ error: 'invalid JSON body' }, 400);\n }\n\n const context = { token: bearerToken(request), headers: headerRecord(request) };\n\n if (isRecord(body) && typeof body.jobId === 'string') {\n const job = service.getJob(body.jobId);\n return job ? json(job) : json({ error: 'job not found' }, 404);\n }\n\n if (isRecord(body) && Array.isArray(body.requests)) {\n const requests = body.requests as ExportRequest[];\n if (body.async === true) {\n return json(service.enqueue(requests, context), 202);\n }\n const results = await service.exportBatch(requests, context);\n return json({ results: results.map(serializeResult) });\n }\n\n if (isRecord(body) && typeof body.format === 'string') {\n const result = await service.export(body as unknown as ExportRequest, context);\n if (result.status === 'error') {\n return json({ ...serializeResult(result) }, statusForError(result.error));\n }\n if (result.url) {\n return json(serializeResult(result));\n }\n // Inline binary download.\n return new Response(result.bytes as BodyInit, {\n status: 200,\n headers: {\n 'Content-Type': result.contentType,\n 'Content-Disposition': `attachment; filename=\"${result.filename}\"`,\n 'Cache-Control': 'no-store',\n },\n });\n }\n\n return json({ error: 'malformed request' }, 400);\n };\n}\n\n/** Serialize a result for JSON transport: bytes become base64 (omit when stored). */\nfunction serializeResult(result: ExportResult): Record<string, unknown> {\n const { bytes, ...rest } = result;\n return bytes && !result.url ? { ...rest, base64: toBase64(bytes) } : rest;\n}\n\nfunction statusForError(error?: string): number {\n if (error === 'unauthorized') return 401;\n if (error === 'document not found') return 404;\n return 400;\n}\n\nfunction json(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json; charset=utf-8' },\n });\n}\n\nfunction bearerToken(request: Request): string | null {\n const auth = request.headers.get('authorization');\n if (!auth) return null;\n const match = /^Bearer\\s+(.+)$/i.exec(auth);\n return match ? match[1]! : null;\n}\n\nfunction headerRecord(request: Request): Record<string, string> {\n const out: Record<string, string> = {};\n request.headers.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64');\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!);\n // eslint-disable-next-line no-undef\n return btoa(binary);\n}\n","import type { StorageAdapter } from './types';\n\n/**\n * In-memory {@link StorageAdapter} — useful for tests and serverless contexts\n * that hand bytes off elsewhere. URLs are `memory:` references.\n */\nexport class MemoryStorage implements StorageAdapter {\n private files = new Map<string, { data: Uint8Array; contentType: string }>();\n\n async write(key: string, data: Uint8Array, contentType: string) {\n this.files.set(key, { data, contentType });\n return { url: `memory:${key}`, ref: key };\n }\n\n get(key: string): { data: Uint8Array; contentType: string } | undefined {\n return this.files.get(key);\n }\n\n keys(): string[] {\n return [...this.files.keys()];\n }\n}\n\nexport interface FilesystemStorageOptions {\n /** Directory rendered files are written under. */\n baseDir: string;\n /**\n * Public base URL files are served from. The returned `url` is\n * `${baseUrl}/${key}`. If omitted, `url` mirrors the on-disk path.\n */\n baseUrl?: string;\n}\n\n/**\n * Filesystem {@link StorageAdapter} (F-6.10). Writes rendered files under a base\n * directory and returns a URL/reference. Uses `node:fs` lazily so the module can\n * be imported anywhere without eagerly pulling Node built-ins.\n */\nexport class FilesystemStorage implements StorageAdapter {\n private readonly baseDir: string;\n private readonly baseUrl?: string;\n\n constructor(options: FilesystemStorageOptions) {\n this.baseDir = options.baseDir;\n this.baseUrl = options.baseUrl;\n }\n\n async write(key: string, data: Uint8Array, _contentType: string) {\n const { dirname, resolve, relative, isAbsolute, sep } = await import('node:path');\n const { mkdir, writeFile } = await import('node:fs/promises');\n\n // Resolve the target and assert it stays inside baseDir — robust against\n // traversal sequences (`../`, `....//`, absolute keys, symlinked separators).\n const root = resolve(this.baseDir);\n const cleanedKey = key.replace(/^[/\\\\]+/, '');\n const filePath = resolve(root, cleanedKey);\n const rel = relative(root, filePath);\n if (rel === '' || rel.startsWith('..') || isAbsolute(rel)) {\n throw new Error(`react-next-editor: unsafe storage key rejected: ${key}`);\n }\n\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, data);\n // The public URL uses the path relative to the storage root.\n const urlKey = rel.split(sep).join('/');\n const url = this.baseUrl ? `${this.baseUrl.replace(/\\/$/, '')}/${urlKey}` : filePath;\n return { url, ref: filePath };\n }\n}\n","import type { PdfRenderer } from './types';\n\n/**\n * Headless-browser PDF renderers (F-6.14). Playwright/Puppeteer are NOT\n * dependencies of this package — install whichever you use. The factories\n * lazily import the engine and throw a clear, actionable error if it is absent,\n * so the rest of the export service works without them.\n *\n * Both render the SAME shared print HTML the client uses, so server PDFs match\n * the on-screen document and client output (F-6.11).\n */\n\ninterface BrowserLike {\n newPage(): Promise<PageLike>;\n close(): Promise<void>;\n}\ninterface PageLike {\n setContent(html: string, options?: Record<string, unknown>): Promise<void>;\n pdf(options?: Record<string, unknown>): Promise<Uint8Array | Buffer>;\n close(): Promise<void>;\n}\n\nexport interface PlaywrightPdfOptions {\n /** Print background colors/images. Default true. */\n printBackground?: boolean;\n /** Honour the document's `@page` size rules. Default true. */\n preferCSSPageSize?: boolean;\n /** Launch arguments forwarded to chromium. */\n launchArgs?: string[];\n}\n\n/**\n * PDF renderer backed by Playwright's bundled Chromium. Requires `playwright`\n * to be installed in the host. The browser is launched lazily and reused;\n * call `close()` to release it.\n */\nexport function createPlaywrightPdfRenderer(options: PlaywrightPdfOptions = {}): PdfRenderer {\n let browserPromise: Promise<BrowserLike> | null = null;\n\n async function getBrowser(): Promise<BrowserLike> {\n if (!browserPromise) {\n browserPromise = (async () => {\n let mod: { chromium?: { launch(opts?: Record<string, unknown>): Promise<BrowserLike> } };\n try {\n // Variable specifier so the optional, possibly-absent dep is not\n // resolved at type-check/build time.\n const spec = 'playwright';\n mod = (await import(spec)) as typeof mod;\n } catch {\n throw new Error(\n \"react-next-editor: server PDF requires 'playwright'. Install it (npm i playwright) \" +\n 'or provide a custom PdfRenderer.',\n );\n }\n if (!mod.chromium) throw new Error('react-next-editor: playwright.chromium is unavailable.');\n return mod.chromium.launch({ args: options.launchArgs ?? [] });\n })();\n }\n return browserPromise;\n }\n\n return {\n async render(html, _opts) {\n const browser = await getBrowser();\n const page = await browser.newPage();\n try {\n await page.setContent(html, { waitUntil: 'networkidle' });\n const buffer = await page.pdf({\n printBackground: options.printBackground ?? true,\n preferCSSPageSize: options.preferCSSPageSize ?? true,\n });\n return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n } finally {\n await page.close();\n }\n },\n async close() {\n if (browserPromise) {\n const browser = await browserPromise;\n await browser.close();\n browserPromise = null;\n }\n },\n };\n}\n\n/**\n * PDF renderer backed by Puppeteer. Requires `puppeteer` to be installed.\n * Equivalent behaviour to the Playwright renderer.\n */\nexport function createPuppeteerPdfRenderer(options: PlaywrightPdfOptions = {}): PdfRenderer {\n let browserPromise: Promise<BrowserLike> | null = null;\n\n async function getBrowser(): Promise<BrowserLike> {\n if (!browserPromise) {\n browserPromise = (async () => {\n let mod: { default?: { launch(opts?: Record<string, unknown>): Promise<BrowserLike> } };\n try {\n // Variable specifier so the optional, possibly-absent dep is not\n // resolved at type-check/build time.\n const spec = 'puppeteer';\n mod = (await import(spec)) as typeof mod;\n } catch {\n throw new Error(\n \"react-next-editor: server PDF requires 'puppeteer'. Install it (npm i puppeteer) \" +\n 'or provide a custom PdfRenderer.',\n );\n }\n const launcher = mod.default;\n if (!launcher) throw new Error('react-next-editor: puppeteer launcher is unavailable.');\n return launcher.launch({ args: options.launchArgs ?? [] });\n })();\n }\n return browserPromise;\n }\n\n return {\n async render(html, _opts) {\n const browser = await getBrowser();\n const page = await browser.newPage();\n try {\n await page.setContent(html, { waitUntil: 'networkidle0' });\n const buffer = await page.pdf({\n printBackground: options.printBackground ?? true,\n preferCSSPageSize: options.preferCSSPageSize ?? true,\n });\n return buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);\n } finally {\n await page.close();\n }\n },\n async close() {\n if (browserPromise) {\n const browser = await browserPromise;\n await browser.close();\n browserPromise = null;\n }\n },\n };\n}\n"]}