Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-load-docx.md
Original file line number Diff line number Diff line change
@@ -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.
44 changes: 30 additions & 14 deletions src/dlp/embed/docx.ts
Original file line number Diff line number Diff line change
@@ -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<Buffer> {
/** 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<Buffer> {
// 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,
Expand All @@ -26,8 +42,8 @@ async function build(extra: Paragraph[], core: Core = {}): Promise<Buffer> {
{
children: [
new Paragraph({ text: 'Generated Document', heading: HeadingLevel.HEADING_1 }),
...bodyParagraphs(),
...extra,
...body,
...extraParagraphs,
],
},
],
Expand All @@ -40,19 +56,19 @@ export const docxTechniques: Record<string, Technique> = {
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) }),
},
};
6 changes: 5 additions & 1 deletion src/dlp/generate/docx.ts
Original file line number Diff line number Diff line change
@@ -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<Buffer> {
// 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)] }));
Expand Down
Loading