Skip to content

Commit 4daa390

Browse files
committed
chore: release DeckOps v1.1.1 with lightweight default installation
1 parent e65d33b commit 4daa390

7 files changed

Lines changed: 39 additions & 147 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## @deckflow/deckops 1.1.1 — 2026-09-07
4+
5+
- Upgrade to `pdf-lite-parse@0.2.1`, which embeds a fixed, allowlisted PDF.js runtime and resources instead of declaring a runtime `pdfjs-dist` dependency.
6+
- Ordinary npm installations no longer pull in canvas for PDF parsing. Keep DeckProbe's independent optional platform CLI packages unchanged; `--omit=optional` remains available for a strict no-native installation.
7+
- Add default-install PDF smoke tests and enforce smaller installed-size budgets plus absence of separate PDF.js/canvas packages.
8+
39
## @deckflow/deckops 1.1.0 — 2026-09-07
410

511
- Upgrade the exact `pdf-lite-parse` dependency to 0.2.0. Local PDF parsing exports embedded images by default without expensive composite-figure rasterization; extractable overlay text and fidelity warnings remain visible.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ npm install -g @deckflow/deckops
2424

2525
The CLI and Node.js entry require Node.js 22.18 or newer. Frontend applications use the separate cloud-only [browser entry](#use-it-in-the-browser).
2626

27-
Local PDF parsing uses `pdf-lite-parse@0.2.0` and exports embedded images without expensive composite-figure rasterization. Extractable overlay text is retained separately; visual fidelity losses are reported in `quality`. `--no-images` (SDK: `includeImages: false`) skips image export entirely.
27+
Local PDF parsing uses `pdf-lite-parse@0.2.1` and exports embedded images without expensive composite-figure rasterization. Extractable overlay text is retained separately; visual fidelity losses are reported in `quality`. `--no-images` (SDK: `includeImages: false`) skips image export entirely.
2828

29-
The default npm install may still include `pdfjs-dist`'s optional `@napi-rs/canvas` platform binary, even though DeckOps does not request composite cropping. For a smaller, strict no-native install use:
29+
Ordinary `npm install @deckflow/deckops` is now lightweight for PDF parsing: the parser embeds a pinned subset of PDF.js and its portable resources, with no separately installed `pdfjs-dist` or automatic canvas dependency. DeckProbe's independent optional platform CLI packages are unchanged. To omit those as well and use the strict no-native installation:
3030

3131
```bash
3232
npm install --omit=optional @deckflow/deckops
3333
```
3434

35-
Embedded-image PDF parsing remains usable without canvas. Use the cloud engine explicitly when full figure fidelity is needed.
35+
Embedded-image PDF parsing works in both installation modes without canvas. Use the cloud engine explicitly when full figure fidelity is needed. Applications calling `pdf-lite-parse` directly can explicitly install canvas for its opt-in composite mode; DeckOps does not enable it automatically.
3636

3737
## Two verbs, deliberately
3838

THIRD_PARTY_NOTICES

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ https://github.com/deckflow/pdf-lite-parse
77
PDF.js / pdfjs-dist
88
Copyright Mozilla Foundation and contributors. Licensed under the Apache License 2.0.
99
https://github.com/mozilla/pdf.js
10+
An allowlisted runtime and resource subset is embedded in pdf-lite-parse.
11+
See its dist/vendor/pdfjs/PROVENANCE.json, LICENSE, and resource license notices.
1012

11-
@napi-rs/canvas (optional, installed through pdfjs-dist on supported platforms)
13+
@napi-rs/canvas (only if explicitly installed by a consumer; not a dependency)
1214
Copyright its contributors. Licensed under the MIT License.
1315
https://github.com/Brooooooklyn/canvas
1416

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@deckflow/deckops",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"description": "Parse any document into an agent-operable representation. Parse once, convert repeatedly: PDF, PPTX, DOCX, Keynote and URLs into durable IR artifacts and Markdown.",
55
"type": "module",
66
"main": "./dist/index.js",
@@ -79,7 +79,7 @@
7979
"open": "^10.1.0",
8080
"p-limit": "^5.0.0",
8181
"parse5": "^7.3.0",
82-
"pdf-lite-parse": "0.2.0",
82+
"pdf-lite-parse": "0.2.1",
8383
"saxes": "^6.0.0",
8484
"axios": "1.19.0",
8585
"eventsource-parser": "1.1.2"

pnpm-lock.yaml

Lines changed: 5 additions & 138 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/check-package-size.mjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ try {
1919
fs.writeFileSync(path.join(strictDir, 'package.json'), '{"private":true}');
2020
execFileSync('npm', ['install', '--ignore-scripts', '--no-audit', '--no-fund', '--prefer-online', '--omit=dev', '--omit=optional', tarball], { cwd: strictDir, stdio: 'inherit' });
2121
const installedBytes = sizeOf(path.join(strictDir, 'node_modules'));
22-
if (installedBytes > 55 * MiB) throw new Error(`Strict production install is ${(installedBytes / MiB).toFixed(2)} MiB; limit is 55 MiB.`);
22+
if (installedBytes > 24 * MiB) throw new Error(`Strict production install is ${(installedBytes / MiB).toFixed(2)} MiB; limit is 24 MiB.`);
2323
const native = filesUnder(path.join(strictDir, 'node_modules')).filter((file) => file.endsWith('.node'));
2424
if (native.length) throw new Error(`Strict production install contains native binaries:\n${native.join('\n')}`);
2525
const installScripts = filesUnder(path.join(strictDir, 'node_modules')).filter((file) => file.endsWith('package.json')).flatMap((file) => {
@@ -44,7 +44,23 @@ try {
4444
fs.writeFileSync(path.join(defaultDir, 'package.json'), '{"private":true}');
4545
execFileSync('npm', ['install', '--ignore-scripts', '--no-audit', '--no-fund', '--prefer-online', '--omit=dev', tarball], { cwd: defaultDir, stdio: 'inherit' });
4646
const defaultBytes = sizeOf(path.join(defaultDir, 'node_modules'));
47+
if (defaultBytes > 30 * MiB) throw new Error(`Default production install is ${(defaultBytes / MiB).toFixed(2)} MiB; limit is 30 MiB.`);
4748
const defaultNative = filesUnder(path.join(defaultDir, 'node_modules')).filter((file) => file.endsWith('.node')).length;
49+
if (defaultNative) throw new Error('Default installation must not pull in native canvas extensions.');
50+
for (const directory of [strictDir, defaultDir]) {
51+
const files = filesUnder(path.join(directory, 'node_modules'));
52+
if (files.some(file => /node_modules[\\/](@napi-rs[\\/]|pdfjs-dist[\\/])/.test(file))) {
53+
throw new Error('PDF parsing must use the embedded runtime, without a separate canvas/PDF.js dependency.');
54+
}
55+
}
56+
const defaultCli = path.join(defaultDir, 'node_modules', '.bin', 'deckops');
57+
const defaultOutput = path.join(workspace, 'default-pdf-smoke');
58+
const defaultSmoke = JSON.parse(execFileSync(defaultCli, ['parse', path.join(root, 'tests/generated/test.pdf'),
59+
'--engine', 'local', '--preflight', 'off', '--output', defaultOutput, '--json'], {encoding:'utf8'}));
60+
if (!defaultSmoke.ok || defaultSmoke.engine !== 'local') throw new Error('Default production install failed the local PDF smoke test.');
61+
const ir = JSON.parse(fs.readFileSync(path.join(defaultOutput, 'ir.json'), 'utf8'));
62+
const parserVersion = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')).dependencies['pdf-lite-parse'];
63+
if (ir.producer.version !== parserVersion) throw new Error('Installed PDF parser version does not match the dependency pin.');
4864
process.stdout.write(`tarball ${(item.size / MiB).toFixed(2)} MiB; strict install ${(installedBytes / MiB).toFixed(2)} MiB; default install ${(defaultBytes / MiB).toFixed(2)} MiB (${defaultNative} native binaries); cold-start P95 ${p95.toFixed(0)} ms; PDF RSS ${(measured.maxRssBytes / MiB).toFixed(2)} MiB; files >1 MiB ${large.length}\n`);
4965
} finally {
5066
if (tarball) fs.rmSync(tarball, { force: true });

tests/integration/local.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { resolveInput } from '../../src/core/input.js';
88
import { runParse } from '../../src/core/parse-op.js';
99
import { validateDeckIR } from '../../src/ir/validate.js';
1010
import { createClient } from '../../src/index.js';
11+
import { PDF_PARSER_VERSION } from '../../src/version.js';
1112

1213
const tmp = (): string => fs.mkdtempSync(path.join(os.tmpdir(), 'deckops-local-'));
1314

@@ -62,13 +63,13 @@ describe('local community engine', () => {
6263
await runParse(options);
6364
const manifestFile = path.join(out, 'manifest.json');
6465
const manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf-8'));
65-
expect(manifest.parse.parser.version).toBe('0.2.0');
66+
expect(manifest.parse.parser.version).toBe(PDF_PARSER_VERSION);
6667
manifest.parse.parser.version = '0.1.2';
6768
fs.writeFileSync(manifestFile, JSON.stringify(manifest));
6869
expect(await runParse(options)).toMatchObject({ engine: 'local', reusedParse: false });
6970
expect(await runParse(options)).toMatchObject({ engine: 'artifact-cache', reusedParse: true });
7071
const current = await readManifest(out);
71-
expect(current).toMatchObject({ parse: { parser: { version: '0.2.0' } } });
72+
expect(current).toMatchObject({ parse: { parser: { version: PDF_PARSER_VERSION } } });
7273
} finally { fs.rmSync(root, { recursive: true, force: true }); }
7374
}, 30_000);
7475

0 commit comments

Comments
 (0)