
Research
/Security News
TensorLake npm SDK Compromised in ChainDrop Shai-Hulud Credential-Stealing Attack
Tensorlake npm SDK version 0.5.144 was compromised in a ChainDrop / Shai-Hulud attack, delivering credential-stealing malware.
@deckops/sdk
Advanced tools
Node.js and browser-compatible SDK for Deckops/Deckflow task APIs.
pnpm add @deckops/sdk
In this monorepo:
pnpm --filter @deckops/sdk build
import { createDeck } from '@deckops/sdk';
const deck = createDeck({
root: 'https://app.deckflow.com/v1',
token: 'user-token',
apiKey: 'api-key',
spaceId: 'space-id',
});
Options:
root?: string - API root address. Defaults to https://app.deckflow.com/v1.token?: string - sent as X-Auth-Token.apiKey?: string - sent as Authorization: Bearer {apiKey}.spaceId?: string - default space id for task and file calls.authUuid?: string - explicit client UUID (UUID v4) sent as X-Auth-UUID. Skips automatic persistence.authUuidStorage?: { get(), set(value) } - custom storage for client UUID (SSR, tests, embedded apps).onUnauthorized?: () => Promise<{ token: string; spaceId?: string } | string> - called once after a 401, then the request is retried.onPaymentRequired?: () => Promise<void> - called once after a 402, then the request is retried.Every Deckops API request automatically includes X-Auth-UUID, a stable UUID v4 used to track the client across sessions.
localStorage under df_uuid.~/.deckops/auth-uuid (override the directory with DECKOPS_CONFIG_DIR).authUuid or set DECKOPS_AUTH_UUID (Node only) for fixed IDs in CI, containers, or multi-tenant servers.const uuid = await deck.getAuthUuid();
console.log('Client UUID:', uuid);
Pass user-selected files directly to task methods. The SDK uploads them internally and sends the resulting file ids to the task API:
const task = await deck.convertPptToPdf({
files: ['./slides.pptx'],
upload: {
onProgress: (p) => console.log(`${Math.round(p * 100)}%`),
},
});
files supports:
'./a.pptx'Uint8Array or ArrayBufferBlob/FileFor browser file pickers, pass the selected File object:
await deck.convertPptToPdf({
files: [file],
});
For binary data without a file name, include per-file upload options:
await deck.imageOcr({
files: [{ input: bytes, name: 'image.png' }],
params: { language: 'en' },
});
For compatibility with existing integrations, fileIds is still accepted and can be combined with files.
const task = await deck.tasks.create({
type: 'convertor.ppt2pdf',
files: ['./slides.pptx'],
name: 'slides',
params: {},
});
await deck.tasks.list({ type: 'convertor.ppt2pdf', startIndex: 0, maxResults: 50 });
await deck.tasks.get(task.id);
await deck.tasks.wait(task.id, { timeout: 300, useEventStream: true });
await deck.tasks.down<'convertor.ppt2pdf'>(task.id);
await deck.tasks.delete(task.id);
const cancel = await deck.tasks.subscribe(task.id, {
onUpdate: (next) => console.log(next.status),
onError: console.error,
});
cancel();
Task detail responses are for status/progress metadata. Task results should be read through deck.tasks.down(...) or the backend-name alias deck.ttask.down(...).
const result = await deck.ttask.down<'convertor.ppt2pdf'>(task.id);
const generationDownload = await deck.ttask.down<'generation'>(task.id, { type: 'pptx' });
console.log(generationDownload.downloadUrl);
The SDK exports concrete result types for every task type through DeckTaskTypeResult.
Most file-producing tasks return tuple-shaped file results because that is the backend contract:
type FileResult = [
path: string,
bytes: number,
hash: string,
];
type ConvertFileResult = [
path: string,
bytes: number,
hash: string,
bounds?: { w?: number; h?: number; total?: number } | null,
];
path is the storage key or relative path in raw backend data. When the task detail API expands downloadable results, it may already be a signed/access URL.
Examples:
deck.convertPptToPdf(...) returns ConvertFileResult[].deck.convertHtmlToPptx(...) returns { target: FileResult; usedFonts: string[] }.deck.pptxSplit(...) returns { ppt, sections, slides } with typed slide file metadata.deck.pptxGetFontInfo(...) returns { fonts, embeddedFont, subsetFont }.deck.pptxGetTextShapes(...) returns typed page/shape/text/image metadata.Every helper accepts { spaceId?, files?, fileIds?, name?, params?, upload? }, sets the backend task type, uploads files when needed, and returns a typed DeckTask.
await deck.fileCompress({ files: ['./document.pdf'] });
await deck.imageOcr({ files: [file], params: { language: 'en' } });
await deck.imageConvertWebp({ files: [file] });
await deck.imageResize({ files: [file], params: { maxWidth: 1024 } });
await deck.pptxSplit({ files: ['./slides.pptx'], params: { indexes: [0, 1] } });
await deck.pptxJoin({ files: ['./part1.pptx', './part2.pptx'], name: 'merged' });
await deck.pptxGetFontInfo({ files: ['./slides.pptx'] });
await deck.pptxGetTextShapes({
files: ['./slides.pptx'],
params: { includeNotes: true, ignoreEmptyText: true },
});
await deck.pptxEmbedFonts({
files: ['./slides.pptx'],
params: { usedFonts: ['Arial'] },
});
await deck.convertPptToImage({
files: ['./slides.pptx'],
params: { resolution: 1920, format: 'jpg' },
});
await deck.convertPptToPptx({ files: ['./slides.ppt'] });
await deck.convertPptToPdf({ files: ['./slides.pptx'] });
await deck.convertDocToPdf({ files: ['./handbook.docx'] });
await deck.convertPptToVideo({ files: ['./slides.pptx'] });
await deck.convertPdfToImage({ files: ['./document.pdf'] });
await deck.convertKeynoteToImage({ files: ['./deck.key'] });
await deck.convertKeynoteToHtml({ files: ['./deck.key'] });
await deck.convertKeynoteToPdf({ files: ['./deck.key'] });
await deck.convertHtmlToPng({
files: [{ input: htmlBytes, name: 'page.html' }],
params: { width: 1280, height: 720, fullPage: true },
});
await deck.convertMarkdownToPng({
files: [{ input: markdownBytes, name: 'page.md' }],
params: { theme: 'dark', pageWidth: 960 },
});
await deck.convertHtmlToPptx({
files: [{ input: htmlBytes, name: 'deck.html' }],
params: { width: 1280, height: 720, needEmbedFonts: false },
});
await deck.convertHtmlToPptx({
files: ['./page1.html', './page2.html'],
params: { width: 1280, height: 720 },
});
Ordered multi-source files are meaningful for task types that map the whole file
array into backend parameters, including pptx.join, convertor.html2pptx,
html.buildPlayer, and generation. Most other task types read one source file;
pass one file per task for those.
await deck.htmlBuildPlayer({
params: {
contents: [{ key: 'pages/1.html' }],
pageWidth: 1280,
pageHeight: 720,
title: 'Deck',
description: 'Deck player',
brandMarkPosition: 'none',
},
});
await deck.generation({
files: [referenceFile],
params: {
inputText: '写一份产品发布会方案',
enableSearch: true,
pageCount: 8,
},
});
await deck.translation({
files: [file],
params: {
from: 'zh',
to: 'en',
model: 'Standard',
useGlossary: false,
imageTranslate: false,
},
});
await deck.revamp({
files: [file],
params: { lang: 'zh' },
});
Blob/File; the SDK reads the file name and calculates MD5.deck.tasks.wait(taskId, { useEventStream: false }) is the most portable option.FAQs
Deckops TypeScript SDK for Node.js and browsers
The npm package @deckops/sdk receives a total of 24 weekly downloads. As such, @deckops/sdk popularity was classified as not popular.
We found that @deckops/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Research
/Security News
Tensorlake npm SDK version 0.5.144 was compromised in a ChainDrop / Shai-Hulud attack, delivering credential-stealing malware.

Research
/Security News
Socket found 16 malicious Firefox extensions designed to steal crypto wallet recovery phrases and private keys using cloned Rabby and OKX interfaces.

Product
Socket now scans VS Code extensions, giving teams early detection of risky behaviors, hidden capabilities, and supply chain threats in developer tools.