diff --git a/.changeset/lazy-load-docx.md b/.changeset/lazy-load-docx.md new file mode 100644 index 0000000..c818ab5 --- /dev/null +++ b/.changeset/lazy-load-docx.md @@ -0,0 +1,5 @@ +--- +"@cdot65/prisma-airs-cli": patch +--- + +Lazy-load the `docx` dependency so it only loads when generating DOCX output. Previously `docx` was imported eagerly, pulling in browserify polyfills whose `util-deprecate` shim reads `localStorage` at import time and triggered a Node Web Storage warning (`--localstorage-file was provided without a valid path`) on every command. The import is now deferred into the DOCX builders, so unrelated commands (scan, profiles, etc.) no longer emit the warning and start slightly faster. diff --git a/src/dlp/embed/docx.ts b/src/dlp/embed/docx.ts index 7f77cd1..4dc281c 100644 --- a/src/dlp/embed/docx.ts +++ b/src/dlp/embed/docx.ts @@ -1,23 +1,39 @@ -import { Document, HeadingLevel, Packer, Paragraph, TextRun } from 'docx'; import { lorem } from '../lorem.js'; import { makeRng } from '../rng.js'; import type { PayloadValue, Technique } from '../types.js'; const join = (p: PayloadValue[]): string => p.map((v) => `${v.category}: ${v.value}`).join(' | '); -function bodyParagraphs(): Paragraph[] { - return lorem(makeRng(1), 2) - .split('\n\n') - .map((t) => new Paragraph({ children: [new TextRun(t)] })); -} - interface Core { title?: string; subject?: string; keywords?: string; } -async function build(extra: Paragraph[], core: Core = {}): Promise { +/** Technique-specific body content, constructed lazily once docx is loaded. */ +type Extra = + | { kind: 'none' } + | { kind: 'hidden'; text: string } + | { kind: 'visible'; text: string }; + +async function build(extra: Extra, core: Core = {}): Promise { + // Lazy-load docx: importing it eagerly pulls in browserify polyfills whose + // util-deprecate shim reads localStorage at import time, triggering a Node + // Web Storage warning on every CLI command. Deferring the import to here + // means docx (and the warning) only loads when DOCX output is actually built. + const { Document, HeadingLevel, Packer, Paragraph, TextRun } = await import('docx'); + + const body = lorem(makeRng(1), 2) + .split('\n\n') + .map((t) => new Paragraph({ children: [new TextRun(t)] })); + + const extraParagraphs = + extra.kind === 'hidden' + ? [new Paragraph({ children: [new TextRun({ text: extra.text, vanish: true })] })] + : extra.kind === 'visible' + ? [new Paragraph({ children: [new TextRun(extra.text)] })] + : []; + const doc = new Document({ title: core.title, subject: core.subject, @@ -26,8 +42,8 @@ async function build(extra: Paragraph[], core: Core = {}): Promise { { children: [ new Paragraph({ text: 'Generated Document', heading: HeadingLevel.HEADING_1 }), - ...bodyParagraphs(), - ...extra, + ...body, + ...extraParagraphs, ], }, ], @@ -40,19 +56,19 @@ export const docxTechniques: Record = { id: 'core-props', format: 'docx', label: 'core document properties', - embed: (_clean, p) => build([], { title: join(p), subject: join(p), keywords: join(p) }), + embed: (_clean, p) => + build({ kind: 'none' }, { title: join(p), subject: join(p), keywords: join(p) }), }, 'hidden-run': { id: 'hidden-run', format: 'docx', label: 'hidden (vanish) run', - embed: (_clean, p) => - build([new Paragraph({ children: [new TextRun({ text: join(p), vanish: true })] })]), + embed: (_clean, p) => build({ kind: 'hidden', text: join(p) }), }, visible: { id: 'visible', format: 'docx', label: 'visible body line', - embed: (_clean, p) => build([new Paragraph({ children: [new TextRun(join(p))] })]), + embed: (_clean, p) => build({ kind: 'visible', text: join(p) }), }, }; diff --git a/src/dlp/generate/docx.ts b/src/dlp/generate/docx.ts index 5c7d6ff..82fee4c 100644 --- a/src/dlp/generate/docx.ts +++ b/src/dlp/generate/docx.ts @@ -1,8 +1,12 @@ -import { Document, HeadingLevel, Packer, Paragraph, TextRun } from 'docx'; import { lorem } from '../lorem.js'; /** Generate a valid DOCX (zip) filled with lorem ipsum. */ export async function docx(rng: () => number): Promise { + // Lazy-load docx: importing it eagerly pulls in browserify polyfills whose + // util-deprecate shim reads localStorage at import time, triggering a Node + // Web Storage warning on every CLI command. Deferring the import to here + // means docx (and the warning) only loads when DOCX output is actually built. + const { Document, HeadingLevel, Packer, Paragraph, TextRun } = await import('docx'); const paragraphs = lorem(rng, 3) .split('\n\n') .map((p) => new Paragraph({ children: [new TextRun(p)] }));